Logo Search packages:      
Sourcecode: ardour version File versions

editor_imageframe.cc

/*
    Copyright (C) 2000-2003 Paul Davis 
    Written by Colin Law, CMT, Glasgow

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "imageframe_view.h"
#include "imageframe_time_axis.h"
#include "imageframe_time_axis_view.h"
#include "imageframe_time_axis_group.h"
#include "marker_time_axis_view.h"
#include "marker_time_axis.h"
#include "marker_view.h"
#include "editor.h"
#include "i18n.h"
#include "canvas_impl.h"

#include <gtkmm2ext/gtk_ui.h>
#include <pbd/error.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>

#include "imageframe_socket_handler.h"
#include "ardour_image_compositor_socket.h"
#include "public_editor.h"

using namespace Gtk;
using namespace PBD;

/* <CMT Additions file="editor.cc"> */

void
Editor::add_imageframe_time_axis(const string & track_name, void* src)
{
      // check for duplicate name
      if(get_named_time_axis(track_name))
      {
            warning << "Repeated time axis name" << std::endl ;
      }
      else
      {
            Gtkmm2ext::UI::instance()->call_slot(bind(mem_fun(*this, &Editor::handle_new_imageframe_time_axis_view),track_name, src)) ;
      }
}

void
Editor::connect_to_image_compositor()
{
      if(image_socket_listener == 0)
      {
            image_socket_listener = ImageFrameSocketHandler::create_instance(*this) ;
      }
      
      if(image_socket_listener->is_connected() == true)
      {
            return ;
      }

      // XXX should really put this somewhere safe
      const char * host_ip = "127.0.0.1" ;
      
      bool retcode = image_socket_listener->connect(host_ip, ardourvis::DEFAULT_PORT) ;
      
      if(retcode == false)
      {
            // XXX need to get some return status here
            warning << "Image Compositor Connection attempt failed" << std::endl ;
            return ;
      }
      
      // add the socket to the gui loop, and keep the retuned tag value of the input
      gint tag = gdk_input_add(image_socket_listener->get_socket_descriptor(), GDK_INPUT_READ,ImageFrameSocketHandler::image_socket_callback,image_socket_listener) ;
      image_socket_listener->set_gdk_input_tag(tag) ;
}

void
Editor::scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item)
{
      // GTK2FIX
      //nframes64_t offset = static_cast<nframes64_t>(frames_per_unit * (edit_hscroll_slider_width/2)) ;
      nframes64_t offset = 0;

      nframes64_t x_pos = 0 ;

      if (item->get_position() < offset) {
            x_pos = 0 ;
      } else {
            x_pos = item->get_position() - offset + (item->get_duration() / 2);
      }
      
      reset_x_origin (x_pos);
}

void
Editor::add_imageframe_marker_time_axis(const string & track_name, TimeAxisView* marked_track, void* src)
{
      // Can we only bind 2 data Items?
      // @todo we really want to bind the src attribute too, for the moment tracks can only be added remotely,
      //       so this is not too much of an issue, however will need to be looked at again
      Gtkmm2ext::UI::instance()->call_slot(sigc::bind(mem_fun(*this, &Editor::handle_new_imageframe_marker_time_axis_view),track_name, marked_track)) ;
}

void
Editor::popup_imageframe_edit_menu(int button, int32_t time, ArdourCanvas::Item* ifv, bool with_item)
{
      ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;
      
      if(ifta)
      {
            ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_selected_imageframe_group() ;
      
            if(iftag)
            {
                  ImageFrameView* selected_ifv = ifta->get_view()->get_selected_imageframe_view() ;
                  ifta->popup_imageframe_edit_menu(button, time, selected_ifv, with_item) ;
            }
      }
}

void
Editor::popup_marker_time_axis_edit_menu(int button, int32_t time, ArdourCanvas::Item* ifv, bool with_item)
{
      MarkerTimeAxis* mta = dynamic_cast<MarkerTimeAxis*>(clicked_trackview) ;
      
      if(mta)
      {
            MarkerView* selected_mv = mta->get_view()->get_selected_time_axis_item() ;
            if(selected_mv)
            {
                  mta->popup_marker_time_axis_edit_menu(button,time, selected_mv, with_item) ;
            }
      }
}

TimeAxisView*
Editor::get_named_time_axis(const string & name)
{
      TimeAxisView* tav = 0 ;
      
      for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i)
      {
            if (((TimeAxisView*)*i)->name() == name)
            {
                  tav = ((TimeAxisView*)*i) ;
                  break ;
            }
      }
      return(tav) ;
}

/* </CMT Additions file="editor.cc"> */






/* <CMT Additions file="editor_canvas_events.cc"> */
bool
Editor::canvas_imageframe_item_view_event (GdkEvent *event, ArdourCanvas::Item* item, ImageFrameView *ifv)
{
      gint ret = FALSE ;
      ImageFrameTimeAxisGroup* iftag = 0 ;
      
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &ifv->get_time_axis_view();
                  iftag = ifv->get_time_axis_group() ;
                  dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
                  ret = button_press_handler (item, event, ImageFrameItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler (item, event, ImageFrameItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler (item, event, ImageFrameItem) ;
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_imageframe_start_handle_event (GdkEvent *event, ArdourCanvas::Item* item, ImageFrameView *ifv)
{
      gint ret = FALSE ;
      ImageFrameTimeAxisGroup* iftag = 0 ;
      
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &ifv->get_time_axis_view() ;
                  iftag = ifv->get_time_axis_group() ;
                  dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
                  
                  ret = button_press_handler (item, event, ImageFrameHandleStartItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler (item, event, ImageFrameHandleStartItem) ;
                  break;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler (item, event, ImageFrameHandleStartItem) ;
                  break ;
            case GDK_ENTER_NOTIFY:
                  ret = enter_handler (item, event, ImageFrameHandleStartItem) ;
                  break ;
            case GDK_LEAVE_NOTIFY:
                  ret = leave_handler (item, event, ImageFrameHandleStartItem) ;
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_imageframe_end_handle_event (GdkEvent *event, ArdourCanvas::Item* item, ImageFrameView *ifv)
{
      gint ret = FALSE ;
      ImageFrameTimeAxisGroup* iftag = 0 ;
      
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &ifv->get_time_axis_view() ;
                  iftag = ifv->get_time_axis_group() ;
                  dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv);
                  
                  ret = button_press_handler (item, event, ImageFrameHandleEndItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler (item, event, ImageFrameHandleEndItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler (item, event, ImageFrameHandleEndItem) ;
                  break ;
            case GDK_ENTER_NOTIFY:
                  ret = enter_handler (item, event, ImageFrameHandleEndItem) ;
                  break ;
            case GDK_LEAVE_NOTIFY:
                  ret = leave_handler (item, event, ImageFrameHandleEndItem);
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_imageframe_view_event (GdkEvent* event, ArdourCanvas::Item* item, ImageFrameTimeAxis* ifta)
{
      gint ret = FALSE ;
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = ifta ;
                  ret = button_press_handler (item, event, ImageFrameTimeAxisItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler (item, event, ImageFrameTimeAxisItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_marker_time_axis_view_event (GdkEvent* event, ArdourCanvas::Item* item, MarkerTimeAxis* mta)
{
      gint ret = FALSE ;
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = mta ;
                  ret = button_press_handler(item, event, MarkerTimeAxisItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler(item, event, MarkerTimeAxisItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
            default:
                  break ;
      }
      return(ret) ;
}


bool
Editor::canvas_markerview_item_view_event (GdkEvent* event, ArdourCanvas::Item* item, MarkerView* mta)
{
      gint ret = FALSE ;
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &mta->get_time_axis_view() ;
                  dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta);
                  ret = button_press_handler(item, event, MarkerViewItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler(item, event, MarkerViewItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler(item, event, MarkerViewItem) ;
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_markerview_start_handle_event (GdkEvent* event, ArdourCanvas::Item* item, MarkerView* mta)
{
      gint ret = FALSE ;
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &mta->get_time_axis_view() ;
                  dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ;
                  ret = button_press_handler(item, event, MarkerViewHandleStartItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler(item, event, MarkerViewHandleStartItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler(item, event, MarkerViewHandleStartItem) ;
                  break ;
            case GDK_ENTER_NOTIFY:
                  ret = enter_handler(item, event, MarkerViewHandleStartItem) ;
                  break ;
            case GDK_LEAVE_NOTIFY:
                  ret = leave_handler(item, event, MarkerViewHandleStartItem) ;
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}

bool
Editor::canvas_markerview_end_handle_event (GdkEvent* event, ArdourCanvas::Item* item, MarkerView* mta)
{
      gint ret = FALSE ;
      switch (event->type)
      {
            case GDK_BUTTON_PRESS:
            case GDK_2BUTTON_PRESS:
            case GDK_3BUTTON_PRESS:
                  clicked_trackview = &mta->get_time_axis_view() ;
                  dynamic_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ;
                  ret = button_press_handler(item, event, MarkerViewHandleEndItem) ;
                  break ;
            case GDK_BUTTON_RELEASE:
                  ret = button_release_handler(item, event, MarkerViewHandleEndItem) ;
                  break ;
            case GDK_MOTION_NOTIFY:
                  ret = motion_handler(item, event, MarkerViewHandleEndItem) ;
                  break ;
            case GDK_ENTER_NOTIFY:
                  ret = enter_handler(item, event, MarkerViewHandleEndItem) ;
                  break ;
            case GDK_LEAVE_NOTIFY:
                  ret = leave_handler(item, event, MarkerViewHandleEndItem) ;
                  break ;
            default:
                  break ;
      }
      return(ret) ;
}


/* </CMT Additions file="editor_canvas_events.cc"> */


/*
      ---------------------------------------------------------------------------------------------------
      ---------------------------------------------------------------------------------------------------
      ---------------------------------------------------------------------------------------------------
*/



/* <CMT Additions file="editor_mouse.cc"> */

void
Editor::start_imageframe_grab(ArdourCanvas::Item* item, GdkEvent* event)
{
      ImageFrameView* ifv = ((ImageFrameTimeAxis*)clicked_trackview)->get_view()->get_selected_imageframe_view() ;
      drag_info.copy = false ;
      drag_info.item = item ;
      drag_info.data = ifv ;
      drag_info.motion_callback = &Editor::imageframe_drag_motion_callback;
      drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
      drag_info.last_frame_position = ifv->get_position() ;
 
      drag_info.source_trackview = &ifv->get_time_axis_view() ;
      drag_info.dest_trackview = drag_info.source_trackview;
      
      /* this is subtle. raising the regionview itself won't help,
         because raise_to_top() just puts the item on the top of
         its parent's stack. so, we need to put the trackview canvas_display group
         on the top, since its parent is the whole canvas.

         however, this hides the measure bars within that particular trackview,
         so move them to the top afterwards.
      */

      drag_info.item->raise_to_top();
      drag_info.source_trackview->canvas_display->raise_to_top();
      //time_line_group->raise_to_top();
      cursor_group->raise_to_top ();

      start_grab(event) ;

      drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position;
}


void
Editor::start_markerview_grab(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = ((MarkerTimeAxis*)clicked_trackview)->get_view()->get_selected_time_axis_item() ;
      drag_info.copy = false ;
      drag_info.item = item ;
      drag_info.data = mv ;
      drag_info.motion_callback = &Editor::markerview_drag_motion_callback;
      drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback;
      drag_info.last_frame_position = mv->get_position() ;

      drag_info.source_trackview = &mv->get_time_axis_view() ;
      drag_info.dest_trackview = drag_info.source_trackview;

      /* this is subtle. raising the regionview itself won't help,
         because raise_to_top() just puts the item on the top of
         its parent's stack. so, we need to put the trackview canvas_display group
         on the top, since its parent is the whole canvas.

         however, this hides the measure bars within that particular trackview,
         so move them to the top afterwards.
      */

      drag_info.item->raise_to_top();
      drag_info.source_trackview->canvas_display->raise_to_top();
      //time_line_group->raise_to_top();
      cursor_group->raise_to_top ();

      start_grab(event) ;
  
      drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position ;
}


void
Editor::markerview_drag_motion_callback(ArdourCanvas::Item*, GdkEvent* event)
{
      double cx, cy ;

      MarkerView* mv = reinterpret_cast<MarkerView*>(drag_info.data) ;
      nframes64_t pending_region_position ;
      nframes64_t pointer_frame ;

      pointer_frame = event_frame(event, &cx, &cy) ;

      snap_to(pointer_frame) ;

      if (pointer_frame > (nframes64_t) drag_info.pointer_frame_offset)
      {
            pending_region_position = pointer_frame - drag_info.pointer_frame_offset ;
            snap_to(pending_region_position) ;
            
            // we dont allow marker items to extend beyond, or in front of the marked items so
            // cap the value to the marked items position and duration
            if((pending_region_position + mv->get_duration()) >= ((mv->get_marked_item()->get_position()) + (mv->get_marked_item()->get_duration()))) 
            {
                  pending_region_position = (mv->get_marked_item()->get_position() + mv->get_marked_item()->get_duration()) - (mv->get_duration()) ;
            }
            else if(pending_region_position <= mv->get_marked_item()->get_position()) 
            {
                  pending_region_position = mv->get_marked_item()->get_position() ;
            }
      }
      else
      {
            pending_region_position = mv->get_marked_item()->get_position() ;
      }

      drag_info.last_frame_position = pending_region_position ;
      
      // we treat this as a special case, usually we want to send the identitiy of the caller
      // but in this case, that would trigger our socket handler to handle the event, sending
      // notification to the image compositor. This would be fine, except that we have not
      // finished the drag, we therefore do not want to sent notification until we have
      // completed the drag, only then do we want the image compositor notofied.
      // We therefore set the caller identity to the special case of 0
      mv->set_position(pending_region_position, 0) ;

      show_verbose_time_cursor(pending_region_position) ;
}

void
Editor::imageframe_drag_motion_callback(ArdourCanvas::Item*, GdkEvent* event)
{
      double cx, cy ;
      
      ImageFrameView* ifv = reinterpret_cast<ImageFrameView*>(drag_info.data) ;
      
      nframes64_t pending_region_position;
      nframes64_t pointer_frame;

      pointer_frame = event_frame(event, &cx, &cy) ;

      snap_to(pointer_frame) ;

      if (pointer_frame > (nframes64_t) drag_info.pointer_frame_offset)
      {
            pending_region_position = pointer_frame - drag_info.pointer_frame_offset ;
            snap_to(pending_region_position) ;
      }
      else
      {
            pending_region_position = 0 ;
      }

      drag_info.grab_x = cx;
      //drag_info.last_frame_position = pending_region_position ;
      drag_info.current_pointer_frame = pending_region_position ;
      
      // we treat this as a special case, usually we want to send the identitiy of the caller
      // but in this case, that would trigger our socket handler to handle the event, sending
      // notification to the image compositor. This would be fine, except that we have not
      // finished the drag, we therefore do not want to sent notification until we have
      // completed the drag, only then do we want the image compositor notofied.
      // We therefore set the caller identity to the special case of 0
      ifv->set_position(pending_region_position, 0) ;
      
      show_verbose_time_cursor(pending_region_position) ;
}

void
Editor::timeaxis_item_drag_finished_callback(ArdourCanvas::Item*, GdkEvent* event)
{
      nframes64_t where ;
      TimeAxisViewItem* tavi = reinterpret_cast<TimeAxisViewItem*>(drag_info.data) ;

      bool item_x_movement = (drag_info.last_frame_position != tavi->get_position()) ;

      hide_verbose_canvas_cursor() ;

      /* no x or y movement either means the regionview hasn't been moved, or has been moved
         but is back in it's original position/trackview.*/

      if(!item_x_movement && event && event->type == GDK_BUTTON_RELEASE)
      {
            /* No motion: either set the current region, or align the clicked region
               with the current one.
             */
             return;
      }

      if(item_x_movement)
      {
            /* base the new region position on the current position of the regionview.*/
            where = drag_info.current_pointer_frame ;
            
            // final call to set position after the motion to tell interested parties of the new position
            tavi->set_position(where, this) ;
      }
      else
      {
            //where = tavi->get_position() ;
      }
  

}


void
Editor::imageframe_start_handle_op(ArdourCanvas::Item* item, GdkEvent* event)
{
      // get the selected item from the parent time axis
      ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;
      if(ifta)
      {
            ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ;

            if (ifv == 0) {
                  fatal << _("programming error: no ImageFrameView selected") << endmsg;
                  /*NOTREACHED*/
                  return ;
            }

            drag_info.item = ifv->get_canvas_frame() ;
            drag_info.data = ifv;
            drag_info.grab_x = event->motion.x;
            drag_info.cumulative_x_drag = 0;
            drag_info.motion_callback = &Editor::imageframe_start_handle_trim_motion ;
            drag_info.finished_callback = &Editor::imageframe_start_handle_end_trim ;
            
            start_grab(event) ;
            
            show_verbose_time_cursor(ifv->get_position(), 10) ;
      }
}

void
Editor::imageframe_end_handle_op(ArdourCanvas::Item* item, GdkEvent* event)
{
      // get the selected item from the parent time axis
      ImageFrameTimeAxis* ifta = dynamic_cast<ImageFrameTimeAxis*>(clicked_trackview) ;

      if(ifta)
      {
            ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ;
      
            if (ifv == 0)
            {
                  fatal << _("programming error: no ImageFrameView selected") << endmsg ;
                  /*NOTREACHED*/
                  return ;
            }
      
            drag_info.item = ifv->get_canvas_frame() ;
            drag_info.data = ifv ;
            drag_info.grab_x = event->motion.x ;
            drag_info.cumulative_x_drag = 0 ;
            drag_info.motion_callback = &Editor::imageframe_end_handle_trim_motion ;
            drag_info.finished_callback = &Editor::imageframe_end_handle_end_trim ;

            start_grab(event, trimmer_cursor) ;

            show_verbose_time_cursor(ifv->get_position() + ifv->get_duration(), 10) ;
      }
}

void
Editor::imageframe_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event)
{
      ImageFrameView* ifv = reinterpret_cast<ImageFrameView*> (drag_info.data) ;
      
      nframes64_t start = 0 ;
      nframes64_t end = 0 ;
      nframes64_t pointer_frame = event_frame(event) ;
      
      // chekc th eposition of the item is not locked
      if(!ifv->get_position_locked()) {
            snap_to(pointer_frame) ;

            if(pointer_frame != drag_info.last_pointer_frame) {
                  start = ifv->get_position() ;
                  end = ifv->get_position() + ifv->get_duration() ;
                  
                  if (pointer_frame > end) {
                        start = end ;
                  } else {
                        start = pointer_frame ;
                  }
                  
                  // are we getting bigger or smaller?
                  nframes64_t new_dur_val = end - start ;
                  
                  // start handle, so a smaller pointer frame increases our component size
                  if(pointer_frame <= drag_info.grab_frame) 
                  {
                        if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration()))
                        {
                              new_dur_val = ifv->get_max_duration() ;
                              start = end - new_dur_val ;
                        }
                        else
                        {
                              // current values are ok
                        }
                  }
                  else
                  {
                        if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration()))
                        {
                              new_dur_val = ifv->get_min_duration() ;
                              start = end - new_dur_val ;
                        }
                        else
                        {
                              // current values are ok
                        }
                  }
            
                  drag_info.last_pointer_frame = pointer_frame ;
      
                  /* re-calculatethe duration and position of the imageframeview */
                  drag_info.cumulative_x_drag = new_dur_val ;

                  // we treat this as a special case, usually we want to send the identitiy of the caller
                  // but in this case, that would trigger our socket handler to handle the event, sending
                  // notification to the image compositor. This would be fine, except that we have not
                  // finished the drag, we therefore do not want to sent notification until we have
                  // completed the drag, only then do we want the image compositor notofied.
                  // We therefore set the caller identity to the special case of 0
                  ifv->set_duration(new_dur_val, 0) ;
                  ifv->set_position(start, 0) ;
            }
      }
      
      show_verbose_time_cursor(start, 10) ;
}

void
Editor::imageframe_start_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* event)
{
      ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;
      
      if (drag_info.cumulative_x_drag == 0)
      {
            /* just a click */
      }
      else
      {
            nframes64_t temp = ifv->get_position() + ifv->get_duration() ;
            
            ifv->set_position((nframes64_t) (temp - drag_info.cumulative_x_drag), this) ;
            ifv->set_duration((nframes64_t) drag_info.cumulative_x_drag, this) ;
      }
}

void
Editor::imageframe_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event)
{
      ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;
      
      nframes64_t start = 0 ;
      nframes64_t end = 0 ;
      nframes64_t pointer_frame = event_frame(event) ;
      nframes64_t new_dur_val = 0 ;

      snap_to(pointer_frame) ;
      
      if (pointer_frame != drag_info.last_pointer_frame)
      {
            start = ifv->get_position() ;
            end = ifv->get_position() + ifv->get_duration() ;
            if (pointer_frame < start)
            {
                  end = start ;
            }
            else
            {
                  end = pointer_frame ;
            }
            
            new_dur_val = end - start ;
            
            // are we getting bigger or smaller?
            if(pointer_frame >= drag_info.last_pointer_frame)
            {
                  if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration()))
                  {
                        new_dur_val = ifv->get_max_duration() ;
                  }
            }
            else
            {
                  if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration()))
                  {
                        new_dur_val = ifv->get_min_duration() ;
                  }
            }
            
            drag_info.last_pointer_frame = pointer_frame ;
            drag_info.cumulative_x_drag = new_dur_val ;
            
            // we treat this as a special case, usually we want to send the identitiy of the caller
            // but in this case, that would trigger our socket handler to handle the event, sending
            // notification to the image compositor. This would be fine, except that we have not
            // finished the drag, we therefore do not want to sent notification until we have
            // completed the drag, only then do we want the image compositor notofied.
            // We therefore set the caller identity to the special case of 0
            ifv->set_duration(new_dur_val, 0) ;
      }
      
      show_verbose_time_cursor(new_dur_val, 10) ;
}


void
Editor::imageframe_end_handle_end_trim (ArdourCanvas::Item* item, GdkEvent* event)
{
      ImageFrameView* ifv = reinterpret_cast<ImageFrameView *> (drag_info.data) ;

      if (drag_info.cumulative_x_drag == 0)
      {
            /* just a click */
      }
      else
      {
            nframes64_t new_duration = (nframes64_t)drag_info.cumulative_x_drag ;
            if((new_duration <= ifv->get_max_duration()) && (new_duration >= ifv->get_min_duration()))
            {
                  ifv->set_duration(new_duration, this) ;
            }
      }
}


void
Editor::markerview_item_start_handle_op(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->get_selected_time_axis_item() ;

      if (mv == 0)
      {
            fatal << _("programming error: no MarkerView selected") << endmsg ;
            /*NOTREACHED*/
            return ;
      }

      drag_info.item = mv->get_canvas_frame() ;
      drag_info.data = mv;
      drag_info.grab_x = event->motion.x;

      drag_info.cumulative_x_drag = 0 ;
      drag_info.motion_callback = &Editor::markerview_start_handle_trim_motion ;
      drag_info.finished_callback = &Editor::markerview_start_handle_end_trim ;

      start_grab(event, trimmer_cursor) ;
}

void
Editor::markerview_item_end_handle_op(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerTimeAxis*>(clicked_trackview)->get_view()->get_selected_time_axis_item() ;
      if (mv == 0)
      {
            fatal << _("programming error: no MarkerView selected") << endmsg ;
            /*NOTREACHED*/
            return ;
      }
      
      drag_info.item = mv->get_canvas_frame() ;
      drag_info.data = mv ;
      drag_info.grab_x = event->motion.x ;
      drag_info.cumulative_x_drag = 0 ;
      
      drag_info.motion_callback = &Editor::markerview_end_handle_trim_motion ;
      drag_info.finished_callback = &Editor::markerview_end_handle_end_trim ;
      
      start_grab(event, trimmer_cursor) ;
}


void
Editor::markerview_start_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
      
      nframes64_t start = 0 ;
      nframes64_t end = 0 ;
      nframes64_t pointer_frame = event_frame(event) ;
      
      // chekc th eposition of the item is not locked
      if(!mv->get_position_locked())
      {
            snap_to(pointer_frame) ;
            if(pointer_frame != drag_info.last_pointer_frame)
            {
                  start = mv->get_position() ;
                  end = mv->get_position() + mv->get_duration() ;
                  
                  if (pointer_frame > end)
                  {
                        start = end ;
                  }
                  else
                  {
                        start = pointer_frame ;
                  }
                  
                  // are we getting bigger or smaller?
                  nframes64_t new_dur_val = end - start ;
                  
                  if(pointer_frame <= drag_info.grab_frame)
                  {
                        if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration()))
                        {
                              new_dur_val = mv->get_max_duration() ;
                              start = end - new_dur_val ;
                        }
                        else
                        {
                              // current values are ok
                        }
                  }
                  else
                  {
                        if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration()))
                        {
                              new_dur_val = mv->get_min_duration() ;
                              start = end - new_dur_val ;
                        }
                        else
                        {
                              // current values are ok
                        }
                  }
            
                  drag_info.last_pointer_frame = pointer_frame ;
      
                  /* re-calculatethe duration and position of the imageframeview */
                  drag_info.cumulative_x_drag = new_dur_val ;
       
                  // we treat this as a special case, usually we want to send the identitiy of the caller
                  // but in this case, that would trigger our socket handler to handle the event, sending
                  // notification to the image compositor. This would be fine, except that we have not
                  // finished the drag, we therefore do not want to sent notification until we have
                  // completed the drag, only then do we want the image compositor notofied.
                  // We therefore set the caller identity to the special case of 0
                  mv->set_duration(new_dur_val, 0) ;
                  mv->set_position(start, 0) ;
            }
      }
      
      show_verbose_time_cursor(start, 10) ;
}

void
Editor::markerview_start_handle_end_trim(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
      
      if (drag_info.cumulative_x_drag == 0)
      {
            /* just a click */
      }
      else
      {
            nframes64_t temp = mv->get_position() + mv->get_duration() ;
            
            mv->set_position((nframes64_t) (temp - drag_info.cumulative_x_drag), this) ;
            mv->set_duration((nframes64_t) drag_info.cumulative_x_drag, this) ;
      }
}

void
Editor::markerview_end_handle_trim_motion(ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;
      
      nframes64_t start = 0 ;
      nframes64_t end = 0 ;
      nframes64_t pointer_frame = event_frame(event) ;
      nframes64_t new_dur_val = 0 ;

      snap_to(pointer_frame) ;
      
      if (pointer_frame != drag_info.last_pointer_frame)
      {
            start = mv->get_position() ;
            end = mv->get_position() + mv->get_duration() ;
            
            if(pointer_frame < start)
            {
                  end = start ;
            }
            else
            {
                  end = pointer_frame ;
            }
            
            new_dur_val = end - start ;
            
            // are we getting bigger or smaller?
            if(pointer_frame >= drag_info.last_pointer_frame)
            {
                  // we cant extend beyond the item we are marking
                  ImageFrameView* marked_item = mv->get_marked_item() ;
                  nframes64_t marked_end = marked_item->get_position() + marked_item->get_duration() ;
                  
                  if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration()))
                  {
                        if((start + mv->get_max_duration()) > marked_end)
                        {
                              new_dur_val = marked_end - start ;
                        }
                        else
                        {
                              new_dur_val = mv->get_max_duration() ;
                        }
                  }
                  else if(end > marked_end)
                  {
                        new_dur_val = marked_end - start ;
                  }
            }
            else
            {
                  if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration()))
                  {
                        new_dur_val = mv->get_min_duration() ;
                  }
            }


            drag_info.last_pointer_frame = pointer_frame ;
            drag_info.cumulative_x_drag = new_dur_val ;
            
            // we treat this as a special case, usually we want to send the identitiy of the caller
            // but in this case, that would trigger our socket handler to handle the event, sending
            // notification to the image compositor. This would be fine, except that we have not
            // finished the drag, we therefore do not want to sent notification until we have
            // completed the drag, only then do we want the image compositor notofied.
            // We therefore set the caller identity to the special case of 0
            mv->set_duration(new_dur_val, 0) ;
      }
      
      show_verbose_time_cursor(new_dur_val, 10) ;
}


void
Editor::markerview_end_handle_end_trim (ArdourCanvas::Item* item, GdkEvent* event)
{
      MarkerView* mv = reinterpret_cast<MarkerView*> (drag_info.data) ;

      if (drag_info.cumulative_x_drag == 0)
      {
            /* just a click */
      }
      else
      {
            nframes64_t new_duration = (nframes64_t)drag_info.cumulative_x_drag ;
            mv->set_duration(new_duration, this) ;
      }
}


/* </CMT Additions file="editor_mouse.cc"> */







/* <CMT Additions file="editor_route_list.cc"> */

void
Editor::handle_new_imageframe_time_axis_view(const string & track_name, void* src)
{
      route_redisplay_does_not_sync_order_keys = true;
      no_route_list_redisplay = true;

      ImageFrameTimeAxis* iftav ;
      iftav = new ImageFrameTimeAxis(track_name, *this, *session, *track_canvas) ;
      iftav->set_time_axis_name(track_name, this) ;
      track_views.push_back(iftav) ;


      TreeModel::Row row = *(route_display_model->append());
#if 1 // fake Route workaround
      row[route_display_columns.route] = 
            session->new_video_track(iftav->name());
#endif
      row[route_display_columns.text] = iftav->name();
      row[route_display_columns.tv] = iftav;
      row[route_display_columns.visible] = true;
      route_list_display.get_selection()->select (row);

      iftav->GoingAway.connect(bind(mem_fun(*this, &Editor::remove_route), (TimeAxisView*)iftav)) ;
      iftav->set_old_order_key (route_display_model->children().size() - 1);
      iftav->gui_changed.connect(mem_fun(*this, &Editor::handle_gui_changes)) ;

      no_route_list_redisplay = false;
      redisplay_route_list ();
      route_redisplay_does_not_sync_order_keys = false;
}

void
Editor::handle_new_imageframe_marker_time_axis_view(const string & track_name, TimeAxisView* marked_track)
{
      MarkerTimeAxis* mta = new MarkerTimeAxis (*this, *this->current_session(), *track_canvas, track_name, marked_track) ;
      ((ImageFrameTimeAxis*)marked_track)->add_marker_time_axis(mta, this) ;
      track_views.push_back(mta) ;

      TreeModel::Row row = *(route_display_model->append());

      row[route_display_columns.text] = mta->name();
      row[route_display_columns.tv] = mta;
      route_list_display.get_selection()->select (row);

      mta->GoingAway.connect(bind(mem_fun(*this, &Editor::remove_route), (TimeAxisView*)mta)) ;
 }


/* </CMT Additions file="editor_route_list.cc"> */

Generated by  Doxygen 1.6.0   Back to index