add binfolder path relative filters, fix gbrp color model, vwdw timebar tweaks, title...
[goodguy/history.git] / cinelerra-5.1 / cinelerra / transportque.C
index 16aa45faf352aad41e945a99057f41dc1ed50521..35d6f1f34205447fa71f673de5478718c03eb9f0 100644 (file)
@@ -53,6 +53,8 @@ void TransportCommand::reset()
        realtime = 0;
        resume = 0;
        audio_toggle = 0;
+       play_loop = 0;
+       displacement = 0;
 // Don't reset the change type for commands which don't perform the change
        if(command != STOP) change_type = 0;
        command = COMMAND_NONE;
@@ -87,6 +89,8 @@ void TransportCommand::copy_from(TransportCommand *command)
        this->realtime = command->realtime;
        this->resume = command->resume;
        this->audio_toggle = command->audio_toggle;
+       this->play_loop = command->play_loop;
+       this->displacement = command->displacement;
 }
 
 TransportCommand& TransportCommand::operator=(TransportCommand &command)
@@ -95,137 +99,142 @@ TransportCommand& TransportCommand::operator=(TransportCommand &command)
        return *this;
 }
 
+int TransportCommand::single_frame(int command)
+{
+       return (command == SINGLE_FRAME_FWD || command == SINGLE_FRAME_REWIND ||
+               command == CURRENT_FRAME || command == LAST_FRAME);
+}
 int TransportCommand::single_frame()
 {
-       return (command == SINGLE_FRAME_FWD ||
-               command == SINGLE_FRAME_REWIND ||
-               command == CURRENT_FRAME);
+       return single_frame(command);
 }
 
 
-int TransportCommand::get_direction()
+int TransportCommand::get_direction(int command)
 {
-       switch(command)
-       {
-               case SINGLE_FRAME_FWD:
-               case NORMAL_FWD:
-               case FAST_FWD:
-               case SLOW_FWD:
-               case CURRENT_FRAME:
-                       return PLAY_FORWARD;
-
-               case SINGLE_FRAME_REWIND:
-               case NORMAL_REWIND:
-               case FAST_REWIND:
-               case SLOW_REWIND:
-                       return PLAY_REVERSE;
-
-               default:
-                       break;
+       switch(command) {
+       case SINGLE_FRAME_FWD:
+       case NORMAL_FWD:
+       case FAST_FWD:
+       case SLOW_FWD:
+       case CURRENT_FRAME:
+               return PLAY_FORWARD;
+
+       case SINGLE_FRAME_REWIND:
+       case NORMAL_REWIND:
+       case FAST_REWIND:
+       case SLOW_REWIND:
+       case LAST_FRAME:
+               return PLAY_REVERSE;
+
+       default:
+               break;
        }
        return PLAY_FORWARD;
 }
-
-float TransportCommand::get_speed()
+int TransportCommand::get_direction()
 {
-       switch(command)
-       {
-               case SLOW_FWD:
-               case SLOW_REWIND:
-                       return 0.5;
-
-               case NORMAL_FWD:
-               case NORMAL_REWIND:
-               case SINGLE_FRAME_FWD:
-               case SINGLE_FRAME_REWIND:
-               case CURRENT_FRAME:
-                       return 1.;
+       return get_direction(command);
+}
 
-               case FAST_FWD:
-               case FAST_REWIND:
-                       return 2.;
+float TransportCommand::get_speed(int command)
+{
+       switch(command) {
+       case SLOW_FWD:
+       case SLOW_REWIND:
+               return 0.5;
+
+       case NORMAL_FWD:
+       case NORMAL_REWIND:
+       case SINGLE_FRAME_FWD:
+       case SINGLE_FRAME_REWIND:
+       case CURRENT_FRAME:
+       case LAST_FRAME:
+               return 1.;
+
+       case FAST_FWD:
+       case FAST_REWIND:
+               return 2.;
        }
 
        return 0.;
 }
+float TransportCommand::get_speed()
+{
+       return get_speed(command);
+}
 
 // Assume starting without pause
-void TransportCommand::set_playback_range(EDL *edl, int use_inout, int toggle_audio)
+void TransportCommand::set_playback_range(EDL *edl,
+       int use_inout, int toggle_audio, int loop_play, int use_displacement)
 {
        if(!edl) edl = this->edl;
+       double length = edl->tracks->total_playable_length();
+       double frame_period = 1.0 / edl->session->frame_rate;
 
-       switch(command)
-       {
+       displacement = 0;
+       audio_toggle = toggle_audio;
+       play_loop = loop_play;
+
+       start_position = use_inout && edl->local_session->inpoint_valid() ?
+               edl->local_session->get_inpoint() :
+               !loop_play ? edl->local_session->get_selectionstart(1) : 0;
+       end_position = use_inout && edl->local_session->outpoint_valid() ?
+               edl->local_session->get_outpoint() :
+               !loop_play ? edl->local_session->get_selectionend(1) : length;
+
+       if( !use_inout && EQUIV(start_position, end_position) ) {
+// starting play at or past end_position, play to end_position of media (for mixers)
+               if( start_position >= length )
+                       length = edl->tracks->total_length();
+               switch( command ) {
                case SLOW_FWD:
                case FAST_FWD:
-               case NORMAL_FWD:
-                       start_position = edl->local_session->get_selectionstart(1);
-                       if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
-                               end_position = edl->tracks->total_playable_length();
-                       else
-                               end_position = edl->local_session->get_selectionend(1);
-// this prevents a crash if start position is after the loop when playing forwards
-                   if (edl->local_session->loop_playback &&
-                               start_position > edl->local_session->loop_end)
-                       {
-                                   start_position = edl->local_session->loop_start;
+               case NORMAL_FWD: {
+                       end_position = length;
+// this prevents a crash if start_position position is after the loop when playing forwards
+                       if( edl->local_session->loop_playback &&
+                           start_position > edl->local_session->loop_end ) {
+                               start_position = edl->local_session->loop_start;
                        }
-                       break;
+                       break; }
 
                case SLOW_REWIND:
                case FAST_REWIND:
                case NORMAL_REWIND:
-                       end_position = edl->local_session->get_selectionend(1);
-                       if(EQUIV(edl->local_session->get_selectionend(1), edl->local_session->get_selectionstart(1)))
-                               start_position = 0;
-                       else
-                               start_position = edl->local_session->get_selectionstart(1);
-
-// this prevents a crash if start position is before the loop when playing backwards
-                       if (edl->local_session->loop_playback &&
-                               end_position <= edl->local_session->loop_start)
-                       {
+                       start_position = 0;
+// this prevents a crash if start_position position is before the loop when playing backwards
+                       if( edl->local_session->loop_playback &&
+                           end_position <= edl->local_session->loop_start ) {
                                        end_position = edl->local_session->loop_end;
                        }
                        break;
 
                case CURRENT_FRAME:
+               case LAST_FRAME:
                case SINGLE_FRAME_FWD:
-                       start_position = edl->local_session->get_selectionstart(1);
-                       end_position = start_position +
-                               1.0 /
-                               edl->session->frame_rate;
+                       end_position = start_position + frame_period;
                        break;
 
                case SINGLE_FRAME_REWIND:
-                       start_position = edl->local_session->get_selectionend(1);
-                       end_position = start_position -
-                               1.0 /
-                               edl->session->frame_rate;
+                       start_position = end_position - frame_period;
                        break;
-       }
-
+               }
 
-       if(use_inout)
-       {
-               if(edl->local_session->inpoint_valid())
-                       start_position = edl->local_session->get_inpoint();
-               if(edl->local_session->outpoint_valid())
-                       end_position = edl->local_session->get_outpoint();
+               if( use_displacement && (
+                   (command != CURRENT_FRAME && get_direction() == PLAY_FORWARD ) ||
+                   (command != LAST_FRAME    && get_direction() == PLAY_REVERSE ) ) ) {
+                       start_position += frame_period;
+                       end_position += frame_period;
+                       displacement = 1;
+               }
        }
 
-       switch(get_direction())
-       {
-               case PLAY_FORWARD:
-                       playbackstart = start_position;
-                       break;
-
-               case PLAY_REVERSE:
-                       playbackstart = end_position;
-                       break;
-       }
+       if( end_position < start_position )
+               end_position = start_position;
 
-       audio_toggle = toggle_audio;
+       playbackstart = get_direction() == PLAY_FORWARD ?
+               start_position : end_position;
 }
 
 void TransportCommand::playback_range_adjust_inout()
@@ -246,8 +255,11 @@ void TransportCommand::playback_range_inout()
 
        if(edl->local_session->outpoint_valid())
                end_position = edl->local_session->get_outpoint();
-       else
+       else {
                end_position = edl->tracks->total_playable_length();
+               if( start_position >= end_position )
+                       end_position = edl->tracks->total_length();
+       }
 }
 
 void TransportCommand::playback_range_project()
@@ -275,8 +287,9 @@ TransportQue::~TransportQue()
        delete output_lock;
 }
 
-int TransportQue::send_command(int command, int change_type, EDL *new_edl,
-               int realtime, int resume, int use_inout, int toggle_audio)
+int TransportQue::send_command(int command, int change_type,
+               EDL *new_edl, int realtime, int resume, int use_inout,
+               int toggle_audio, int loop_play, int use_displacement)
 {
        input_lock->lock("TransportQue::send_command 1");
        this->command.command = command;
@@ -303,7 +316,8 @@ int TransportQue::send_command(int command, int change_type, EDL *new_edl,
                }
 
 // Set playback range
-               this->command.set_playback_range(new_edl, use_inout, toggle_audio);
+               this->command.set_playback_range(new_edl, use_inout,
+                               toggle_audio, loop_play, use_displacement);
        }
 
        input_lock->unlock();