diff options
author | David Robillard <d@drobilla.net> | 2006-06-15 21:54:26 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-06-15 21:54:26 +0000 |
commit | 6313751f753c4e85116b0fcdaaf21e4d8369b4af (patch) | |
tree | fde36406fa61cc45c18571e6e062a7d23e5f4819 /libs | |
parent | 4ef0bd23109d0a05a46f71e90676a58642dfabc5 (diff) |
Moved SMPTE type/functions into SMPTE namespace;
LGPL'd SMPTE code and moved in to libardour_cp;
Juggled control_protocol dir layout to be the same as other libs;
git-svn-id: svn://localhost/ardour2/trunk@610 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
22 files changed, 540 insertions, 477 deletions
diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index a015bfb313..7f4ee15eee 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -201,8 +201,8 @@ ardour.Merge ([ libraries['pbd3'], libraries['soundtouch'], libraries['midi++2'], - libraries['glib2'], - libraries['glibmm2'] + libraries['glib2'], + libraries['glibmm2'] ]) if ardour['LIBLO']: diff --git a/libs/ardour/ardour/osc.h b/libs/ardour/ardour/osc.h index 69ec76eac6..0a34f44a41 100644 --- a/libs/ardour/ardour/osc.h +++ b/libs/ardour/ardour/osc.h @@ -32,7 +32,7 @@ #include <ardour/types.h> -#include "basic_ui.h" +#include <control_protocol/basic_ui.h> namespace ARDOUR { class Session; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 902510436a..811941791a 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -590,25 +590,13 @@ class Session : public sigc::trackable, public Stateful int set_smpte_type (float fps, bool drop_frames); void bbt_time (jack_nframes_t when, BBT_Time&); + void smpte_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const; + void sample_to_smpte( jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes ) const; + void smpte_time (SMPTE::Time &); + void smpte_time (jack_nframes_t when, SMPTE::Time&); + void smpte_time_subframes (jack_nframes_t when, SMPTE::Time&); - ARDOUR::smpte_wrap_t smpte_increment( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_decrement( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_increment_subframes( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_decrement_subframes( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_increment_seconds( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_increment_minutes( SMPTE_Time& smpte ) const; - ARDOUR::smpte_wrap_t smpte_increment_hours( SMPTE_Time& smpte ) const; - void smpte_frames_floor( SMPTE_Time& smpte ) const; - void smpte_seconds_floor( SMPTE_Time& smpte ) const; - void smpte_minutes_floor( SMPTE_Time& smpte ) const; - void smpte_hours_floor( SMPTE_Time& smpte ) const; - void smpte_to_sample( SMPTE_Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const; - void sample_to_smpte( jack_nframes_t sample, SMPTE_Time& smpte, bool use_offset, bool use_subframes ) const; - void smpte_time (SMPTE_Time &); - void smpte_time (jack_nframes_t when, SMPTE_Time&); - void smpte_time_subframes (jack_nframes_t when, SMPTE_Time&); - - void smpte_duration (jack_nframes_t, SMPTE_Time&) const; + void smpte_duration (jack_nframes_t, SMPTE::Time&) const; void smpte_duration_string (char *, jack_nframes_t) const; void set_smpte_offset (jack_nframes_t); @@ -1346,7 +1334,7 @@ class Session : public sigc::trackable, public Stateful MIDI::byte mtc_smpte_bits; /* encoding of SMTPE type for MTC */ MIDI::byte midi_msg[16]; jack_nframes_t outbound_mtc_smpte_frame; - SMPTE_Time transmitting_smpte_time; + SMPTE::Time transmitting_smpte_time; int next_quarter_frame_to_send; double _frames_per_smpte_frame; /* has to be floating point because of drop frame */ @@ -1362,7 +1350,7 @@ class Session : public sigc::trackable, public Stateful bool last_smpte_valid; jack_nframes_t last_smpte_when; - SMPTE_Time last_smpte; + SMPTE::Time last_smpte; int send_full_time_code (); int send_midi_time_code (); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index cdf71b8cc6..a0a209b569 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -29,6 +29,7 @@ #include <inttypes.h> #include <jack/types.h> +#include <control_protocol/smpte.h> #include <map> #if __GNUC__ < 3 @@ -98,34 +99,7 @@ namespace ARDOUR { Normal, Destructive }; - - enum smpte_wrap_t { - smpte_wrap_none = 0, - smpte_wrap_frames, - smpte_wrap_seconds, - smpte_wrap_minutes, - smpte_wrap_hours - }; - - struct SMPTE_Time { - bool negative; - uint32_t hours; - uint32_t minutes; - uint32_t seconds; - uint32_t frames; - uint32_t subframes; // mostly not used - - SMPTE_Time() { - negative = false; - hours = 0; - minutes = 0; - seconds = 0; - frames = 0; - subframes = 0; - } - - }; - + struct BBT_Time { uint32_t bars; uint32_t beats; @@ -164,7 +138,7 @@ namespace ARDOUR { Type type; - SMPTE_Time smpte; + SMPTE::Time smpte; BBT_Time bbt; union { diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc index 57a89cc2d9..16437cf8ce 100644 --- a/libs/ardour/control_protocol_manager.cc +++ b/libs/ardour/control_protocol_manager.cc @@ -4,7 +4,7 @@ #include <pbd/error.h> #include <pbd/pathscanner.h> -#include "control_protocol.h" +#include <control_protocol/control_protocol.h> #include <ardour/session.h> #include <ardour/control_protocol_manager.h> diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index cb35c0c785..c1f87bf36d 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -87,7 +87,7 @@ void MTC_Slave::update_mtc_time (const byte *msg, bool was_full) { jack_nframes_t now = session.engine().frame_time(); - SMPTE_Time smpte; + SMPTE::Time smpte; smpte.hours = msg[3]; smpte.minutes = msg[2]; diff --git a/libs/ardour/session_control.cc b/libs/ardour/session_control.cc index 8e0a3e99a1..afecc146b7 100644 --- a/libs/ardour/session_control.cc +++ b/libs/ardour/session_control.cc @@ -1,8 +1,8 @@ #include <ardour/session.h> -#include <ardour/control_protocol.h> -#include <ardour/generic_midi_control_protocol.h> -#include <ardour/tranzport_control_protocol.h> +#include <control_protocol/control_protocol.h> +#include <generic_midi/generic_midi_control_protocol.h> +#include <transport/tranzport_control_protocol.h> using namespace ARDOUR; diff --git a/libs/ardour/session_feedback.cc b/libs/ardour/session_feedback.cc index b409686ce7..6fab01ec9d 100644 --- a/libs/ardour/session_feedback.cc +++ b/libs/ardour/session_feedback.cc @@ -39,7 +39,7 @@ #include <ardour/session.h> #include <ardour/audio_track.h> #include <ardour/audio_diskstream.h> -#include <ardour/control_protocol.h> +#include <control_protocol/control_protocol.h> #include "i18n.h" diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index fa9fa4a2a3..1fb5658761 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -724,7 +724,7 @@ Session::mmc_locate (MIDI::MachineControl &mmc, const MIDI::byte* mmc_tc) } jack_nframes_t target_frame; - SMPTE_Time smpte; + SMPTE::Time smpte; smpte.hours = mmc_tc[0] & 0xf; smpte.minutes = mmc_tc[1]; @@ -858,7 +858,7 @@ Session::send_full_time_code () { MIDI::byte msg[10]; - SMPTE_Time smpte; + SMPTE::Time smpte; if (_mtc_port == 0 || !send_mtc) { return 0; @@ -884,7 +884,7 @@ Session::send_full_time_code () outbound_mtc_smpte_frame = _transport_frame; if (((mtc_smpte_bits >> 5) != MIDI::MTC_25_FPS) && (transmitting_smpte_time.frames % 2)) { // start MTC quarter frame transmission on an even frame - smpte_increment( transmitting_smpte_time ); + SMPTE::increment( transmitting_smpte_time ); outbound_mtc_smpte_frame += (jack_nframes_t) _frames_per_smpte_frame; } } @@ -985,8 +985,8 @@ Session::send_midi_time_code () // Wrap quarter frame counter next_quarter_frame_to_send = 0; // Increment smpte time twice - smpte_increment( transmitting_smpte_time ); - smpte_increment( transmitting_smpte_time ); + SMPTE::increment( transmitting_smpte_time ); + SMPTE::increment( transmitting_smpte_time ); // Re-calculate timing of first quarter frame smpte_to_sample( transmitting_smpte_time, outbound_mtc_smpte_frame, true /* use_offset */, false ); // Compensate for audio latency @@ -1024,7 +1024,7 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where) { using namespace MIDI; int nbytes = 4; - SMPTE_Time smpte; + SMPTE::Time smpte; if (_mmc_port == 0 || !send_mmc) { return; diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index a272f55737..504492aeab 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -109,377 +109,9 @@ Session::set_smpte_offset_negative (bool neg) SMPTEOffsetChanged (); /* EMIT SIGNAL */ } -#define SMPTE_IS_AROUND_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours) -#define SMPTE_IS_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours && !(sm.subframes)) - -// Increment by exactly one frame (keep subframes value) -// Return true if seconds wrap -smpte_wrap_t -Session::smpte_increment( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - if (smpte.negative) { - if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) { - // We have a zero transition involving only subframes - smpte.subframes = 80 - smpte.subframes; - smpte.negative = false; - return smpte_wrap_seconds; - } - - smpte.negative = false; - wrap = smpte_decrement( smpte ); - if (!SMPTE_IS_ZERO( smpte )) { - smpte.negative = true; - } - return wrap; - } - - switch (mtc_smpte_bits >> 5) { - case MIDI::MTC_24_FPS: - if (smpte.frames == 23) { - smpte.frames = 0; - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_25_FPS: - if (smpte.frames == 24) { - smpte.frames = 0; - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_30_FPS_DROP: - if (smpte.frames == 29) { - if ( ((smpte.minutes + 1) % 10) && (smpte.seconds == 59) ) { - smpte.frames = 2; - } - else { - smpte.frames = 0; - } - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_30_FPS: - if (smpte.frames == 29) { - smpte.frames = 0; - wrap = smpte_wrap_seconds; - } - break; - } - - if (wrap == smpte_wrap_seconds) { - if (smpte.seconds == 59) { - smpte.seconds = 0; - wrap = smpte_wrap_minutes; - if (smpte.minutes == 59) { - smpte.minutes = 0; - wrap = smpte_wrap_hours; - smpte.hours++; - } else { - smpte.minutes++; - } - } else { - smpte.seconds++; - } - } else { - smpte.frames++; - } - - return wrap; -} - -// Decrement by exactly one frame (keep subframes value) -smpte_wrap_t -Session::smpte_decrement( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - - if (smpte.negative || SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - wrap = smpte_increment( smpte ); - smpte.negative = true; - return wrap; - } else if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) { - // We have a zero transition involving only subframes - smpte.subframes = 80 - smpte.subframes; - smpte.negative = true; - return smpte_wrap_seconds; - } - - switch (mtc_smpte_bits >> 5) { - case MIDI::MTC_24_FPS: - if (smpte.frames == 0) { - smpte.frames = 23; - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_25_FPS: - if (smpte.frames == 0) { - smpte.frames = 24; - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_30_FPS_DROP: - if ((smpte.minutes % 10) && (smpte.seconds == 0)) { - if (smpte.frames <= 2) { - smpte.frames = 29; - wrap = smpte_wrap_seconds; - } - } else if (smpte.frames == 0) { - smpte.frames = 29; - wrap = smpte_wrap_seconds; - } - break; - case MIDI::MTC_30_FPS: - if (smpte.frames == 0) { - smpte.frames = 29; - wrap = smpte_wrap_seconds; - } - break; - } - - if (wrap == smpte_wrap_seconds) { - if (smpte.seconds == 0) { - smpte.seconds = 59; - wrap = smpte_wrap_minutes; - if (smpte.minutes == 0) { - smpte.minutes = 59; - wrap = smpte_wrap_hours; - smpte.hours--; - } - else { - smpte.minutes--; - } - } else { - smpte.seconds--; - } - } else { - smpte.frames--; - } - - if (SMPTE_IS_ZERO( smpte )) { - smpte.negative = false; - } - - return wrap; -} - -// Go to lowest absolute subframe value in this frame (set to 0 :-) -void -Session::smpte_frames_floor( SMPTE_Time& smpte ) const -{ - smpte.subframes = 0; - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } -} - -// Increment by one subframe -smpte_wrap_t -Session::smpte_increment_subframes( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - if (smpte.negative) { - smpte.negative = false; - wrap = smpte_decrement_subframes( smpte ); - if (!SMPTE_IS_ZERO(smpte)) { - smpte.negative = true; - } - return wrap; - } - - smpte.subframes++; - if (smpte.subframes >= 80) { - smpte.subframes = 0; - smpte_increment( smpte ); - return smpte_wrap_frames; - } - return smpte_wrap_none; -} - - -// Decrement by one subframe -smpte_wrap_t -Session::smpte_decrement_subframes( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - if (smpte.negative) { - smpte.negative = false; - wrap = smpte_increment_subframes( smpte ); - smpte.negative = true; - return wrap; - } - - if (smpte.subframes <= 0) { - smpte.subframes = 0; - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = true; - smpte.subframes = 1; - return smpte_wrap_frames; - } else { - smpte_decrement( smpte ); - smpte.subframes = 79; - return smpte_wrap_frames; - } - } else { - smpte.subframes--; - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } - return smpte_wrap_none; - } -} - - -// Go to next whole second (frames == 0 or frames == 2) -smpte_wrap_t -Session::smpte_increment_seconds( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - // Clear subframes - smpte_frames_floor( smpte ); - - if (smpte.negative) { - // Wrap second if on second boundary - wrap = smpte_increment(smpte); - // Go to lowest absolute frame value - smpte_seconds_floor( smpte ); - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } - } else { - // Go to highest possible frame in this second - switch (mtc_smpte_bits >> 5) { - case MIDI::MTC_24_FPS: - smpte.frames = 23; - break; - case MIDI::MTC_25_FPS: - smpte.frames = 24; - break; - case MIDI::MTC_30_FPS_DROP: - case MIDI::MTC_30_FPS: - smpte.frames = 29; - break; - } - - // Increment by one frame - wrap = smpte_increment( smpte ); - } - - return wrap; -} - -// Go to lowest (absolute) frame value in this second -// Doesn't care about positive/negative -void -Session::smpte_seconds_floor( SMPTE_Time& smpte ) const -{ - // Clear subframes - smpte_frames_floor( smpte ); - - // Go to lowest possible frame in this second - switch (mtc_smpte_bits >> 5) { - case MIDI::MTC_24_FPS: - case MIDI::MTC_25_FPS: - case MIDI::MTC_30_FPS: - smpte.frames = 0; - break; - case MIDI::MTC_30_FPS_DROP: - if ((smpte.minutes % 10) && (smpte.seconds == 0)) { - smpte.frames = 2; - } else { - smpte.frames = 0; - } - break; - } - - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } -} - - -// Go to next whole minute (seconds == 0, frames == 0 or frames == 2) -smpte_wrap_t -Session::smpte_increment_minutes( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - // Clear subframes - smpte_frames_floor( smpte ); - - if (smpte.negative) { - // Wrap if on minute boundary - wrap = smpte_increment_seconds( smpte ); - // Go to lowest possible value in this minute - smpte_minutes_floor( smpte ); - } else { - // Go to highest possible second - smpte.seconds = 59; - // Wrap minute by incrementing second - wrap = smpte_increment_seconds( smpte ); - } - - return wrap; -} - -// Go to lowest absolute value in this minute -void -Session::smpte_minutes_floor( SMPTE_Time& smpte ) const -{ - // Go to lowest possible second - smpte.seconds = 0; - // Go to lowest possible frame - smpte_seconds_floor( smpte ); - - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } -} - -// Go to next whole hour (minute = 0, second = 0, frame = 0) -smpte_wrap_t -Session::smpte_increment_hours( SMPTE_Time& smpte ) const -{ - smpte_wrap_t wrap = smpte_wrap_none; - - // Clear subframes - smpte_frames_floor(smpte); - - if (smpte.negative) { - // Wrap if on hour boundary - wrap = smpte_increment_minutes( smpte ); - // Go to lowest possible value in this hour - smpte_hours_floor( smpte ); - } else { - smpte.minutes = 59; - wrap = smpte_increment_minutes( smpte ); - } - - return wrap; -} - -// Go to lowest absolute value in this hour -void -Session::smpte_hours_floor( SMPTE_Time& smpte ) const -{ - smpte.minutes = 0; - smpte.seconds = 0; - smpte.frames = 0; - smpte.subframes = 0; - - if (SMPTE_IS_ZERO(smpte)) { - smpte.negative = false; - } -} - void -Session::smpte_to_sample( SMPTE_Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const +Session::smpte_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const { if (smpte_drop_frames) { // The drop frame format was created to better approximate the 30000/1001 = 29.97002997002997.... @@ -562,7 +194,7 @@ Session::smpte_to_sample( SMPTE_Time& smpte, jack_nframes_t& sample, bool use_of void -Session::sample_to_smpte( jack_nframes_t sample, SMPTE_Time& smpte, bool use_offset, bool use_subframes ) const +Session::sample_to_smpte( jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes ) const { jack_nframes_t offset_sample; @@ -656,7 +288,7 @@ Session::sample_to_smpte( jack_nframes_t sample, SMPTE_Time& smpte, bool use_off } void -Session::smpte_time (jack_nframes_t when, SMPTE_Time& smpte) +Session::smpte_time (jack_nframes_t when, SMPTE::Time& smpte) { if (last_smpte_valid && when == last_smpte_when) { smpte = last_smpte; @@ -671,7 +303,7 @@ Session::smpte_time (jack_nframes_t when, SMPTE_Time& smpte) } void -Session::smpte_time_subframes (jack_nframes_t when, SMPTE_Time& smpte) +Session::smpte_time_subframes (jack_nframes_t when, SMPTE::Time& smpte) { if (last_smpte_valid && when == last_smpte_when) { smpte = last_smpte; @@ -686,7 +318,7 @@ Session::smpte_time_subframes (jack_nframes_t when, SMPTE_Time& smpte) } void -Session::smpte_duration (jack_nframes_t when, SMPTE_Time& smpte) const +Session::smpte_duration (jack_nframes_t when, SMPTE::Time& smpte) const { sample_to_smpte( when, smpte, false /* use_offset */, true /* use_subframes */ ); } @@ -694,14 +326,14 @@ Session::smpte_duration (jack_nframes_t when, SMPTE_Time& smpte) const void Session::smpte_duration_string (char* buf, jack_nframes_t when) const { - SMPTE_Time smpte; + SMPTE::Time smpte; smpte_duration (when, smpte); snprintf (buf, sizeof (buf), "%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32 ":%02" PRIu32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); } void -Session::smpte_time (SMPTE_Time &t) +Session::smpte_time (SMPTE::Time &t) { smpte_time (_transport_frame, t); diff --git a/libs/surfaces/control_protocol/SConscript b/libs/surfaces/control_protocol/SConscript index 38ff95d9f0..f8a7d574f5 100644 --- a/libs/surfaces/control_protocol/SConscript +++ b/libs/surfaces/control_protocol/SConscript @@ -23,6 +23,7 @@ cp.Append(POTFILE = domain + '.pot') cp_files=Split(""" basic_ui.cc control_protocol.cc +smpte.cc """) cp.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") @@ -53,4 +54,4 @@ env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), li env.Alias('tarball', env.Distribute (env['DISTTREE'], [ 'SConscript' ] + cp_files + - glob.glob('po/*.po') + glob.glob('*.h'))) + glob.glob('po/*.po') + glob.glob('*.h') + glob.glob('control_protocol/*.h'))) diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc index 8cf157c26c..3dc93cc64a 100644 --- a/libs/surfaces/control_protocol/basic_ui.cc +++ b/libs/surfaces/control_protocol/basic_ui.cc @@ -24,7 +24,8 @@ #include <ardour/session.h> #include <ardour/location.h> -#include "basic_ui.h" +#include <control_protocol/basic_ui.h> + #include "i18n.h" using namespace ARDOUR; @@ -263,19 +264,19 @@ BasicUI::smpte_frames_per_hour () } void -BasicUI::smpte_time (jack_nframes_t where, SMPTE_t& smpte) +BasicUI::smpte_time (jack_nframes_t where, SMPTE::Time& smpte) { - session->smpte_time (where, *((SMPTE_Time *) &smpte)); + session->smpte_time (where, *((SMPTE::Time *) &smpte)); } void -BasicUI::smpte_to_sample (SMPTE_t& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const +BasicUI::smpte_to_sample (SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const { - session->smpte_to_sample (*((SMPTE_Time*)&smpte), sample, use_offset, use_subframes); + session->smpte_to_sample (*((SMPTE::Time*)&smpte), sample, use_offset, use_subframes); } void -BasicUI::sample_to_smpte (jack_nframes_t sample, SMPTE_t& smpte, bool use_offset, bool use_subframes) const +BasicUI::sample_to_smpte (jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes) const { - session->sample_to_smpte (sample, *((SMPTE_Time*)&smpte), use_offset, use_subframes); + session->sample_to_smpte (sample, *((SMPTE::Time*)&smpte), use_offset, use_subframes); } diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc index 6407c64385..10295bc698 100644 --- a/libs/surfaces/control_protocol/control_protocol.cc +++ b/libs/surfaces/control_protocol/control_protocol.cc @@ -23,7 +23,7 @@ #include <ardour/route.h> #include <ardour/audio_track.h> -#include "control_protocol.h" +#include <control_protocol/control_protocol.h> using namespace ARDOUR; using namespace std; diff --git a/libs/surfaces/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h index 81f2727264..23b274ca01 100644 --- a/libs/surfaces/control_protocol/basic_ui.h +++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h @@ -25,6 +25,7 @@ #include <string> #include <jack/types.h> +#include <control_protocol/smpte.h> namespace ARDOUR { class Session; @@ -72,27 +73,9 @@ class BasicUI { jack_nframes_t smpte_frames_per_hour (); - struct SMPTE_t { - bool negative; - uint32_t hours; - uint32_t minutes; - uint32_t seconds; - uint32_t frames; - uint32_t subframes; // mostly not used - - SMPTE_t () { - negative = false; - hours = 0; - minutes = 0; - seconds = 0; - frames = 0; - subframes = 0; - } - }; - - void smpte_time (jack_nframes_t where, SMPTE_t&); - void smpte_to_sample (SMPTE_t& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const; - void sample_to_smpte (jack_nframes_t sample, SMPTE_t& smpte, bool use_offset, bool use_subframes) const; + void smpte_time (jack_nframes_t where, SMPTE::Time&); + void smpte_to_sample (SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes) const; + void sample_to_smpte (jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes) const; protected: BasicUI (); diff --git a/libs/surfaces/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 720188c666..69135f2b4b 100644 --- a/libs/surfaces/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -27,7 +27,7 @@ #include <list> #include <sigc++/sigc++.h> -#include "basic_ui.h" +#include <control_protocol/basic_ui.h> namespace ARDOUR { diff --git a/libs/surfaces/control_protocol/control_protocol/smpte.h b/libs/surfaces/control_protocol/control_protocol/smpte.h new file mode 100644 index 0000000000..09c1c9616a --- /dev/null +++ b/libs/surfaces/control_protocol/control_protocol/smpte.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser 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. +*/ + +#ifndef __ardour_smpte_h__ +#define __ardour_smpte_h__ + +#include <inttypes.h> + +namespace SMPTE { + +enum Wrap { + NONE = 0, + FRAMES, + SECONDS, + MINUTES, + HOURS +}; + +/** SMPTE frame rate (in frames per second). + * + * This should be eliminated in favour of a float to support arbitrary rates. + */ +enum FPS { + MTC_24_FPS = 0, + MTC_25_FPS = 1, + MTC_30_FPS_DROP = 2, + MTC_30_FPS = 3 +}; + +struct Time { + bool negative; + uint32_t hours; + uint32_t minutes; + uint32_t seconds; + uint32_t frames; ///< SMPTE frames (not audio samples) + uint32_t subframes; ///< Typically unused + FPS rate; ///< Frame rate of this Time + static FPS default_rate; ///< Rate to use for default constructor + + Time(FPS a_rate = default_rate) { + negative = false; + hours = 0; + minutes = 0; + seconds = 0; + frames = 0; + subframes = 0; + rate = a_rate; + } +}; + +Wrap increment( Time& smpte ); +Wrap decrement( Time& smpte ); +Wrap increment_subframes( Time& smpte ); +Wrap decrement_subframes( Time& smpte ); +Wrap increment_seconds( Time& smpte ); +Wrap increment_minutes( Time& smpte ); +Wrap increment_hours( Time& smpte ); +void frames_floor( Time& smpte ); +void seconds_floor( Time& smpte ); +void minutes_floor( Time& smpte ); +void hours_floor( Time& smpte ); + +} // namespace SMPTE + +#endif // __ardour_smpte_h__ diff --git a/libs/surfaces/control_protocol/smpte.cc b/libs/surfaces/control_protocol/smpte.cc new file mode 100644 index 0000000000..55d0660c59 --- /dev/null +++ b/libs/surfaces/control_protocol/smpte.cc @@ -0,0 +1,406 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser 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. +*/ + +#define SMPTE_IS_AROUND_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours) +#define SMPTE_IS_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours && !(sm.subframes)) + +#include <control_protocol/smpte.h> + +namespace SMPTE { + +FPS Time::default_rate = MTC_30_FPS; + + +/** Increment @a smpte by exactly one frame (keep subframes value). + * Realtime safe. + * @return true if seconds wrap. + */ +Wrap +increment( Time& smpte ) +{ + Wrap wrap = NONE; + + if (smpte.negative) { + if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) { + // We have a zero transition involving only subframes + smpte.subframes = 80 - smpte.subframes; + smpte.negative = false; + return SECONDS; + } + + smpte.negative = false; + wrap = decrement( smpte ); + if (!SMPTE_IS_ZERO( smpte )) { + smpte.negative = true; + } + return wrap; + } + + switch (smpte.rate) { + case MTC_24_FPS: + if (smpte.frames == 23) { + smpte.frames = 0; + wrap = SECONDS; + } + break; + case MTC_25_FPS: + if (smpte.frames == 24) { + smpte.frames = 0; + wrap = SECONDS; + } + break; + case MTC_30_FPS_DROP: + if (smpte.frames == 29) { + if ( ((smpte.minutes + 1) % 10) && (smpte.seconds == 59) ) { + smpte.frames = 2; + } + else { + smpte.frames = 0; + } + wrap = SECONDS; + } + break; + case MTC_30_FPS: + if (smpte.frames == 29) { + smpte.frames = 0; + wrap = SECONDS; + } + break; + } + + if (wrap == SECONDS) { + if (smpte.seconds == 59) { + smpte.seconds = 0; + wrap = MINUTES; + if (smpte.minutes == 59) { + smpte.minutes = 0; + wrap = HOURS; + smpte.hours++; + } else { + smpte.minutes++; + } + } else { + smpte.seconds++; + } + } else { + smpte.frames++; + } + + return wrap; +} + + +/** Decrement @a smpte by exactly one frame (keep subframes value) + * Realtime safe. + * @return true if seconds wrap. */ +Wrap +decrement( Time& smpte ) +{ + Wrap wrap = NONE; + + + if (smpte.negative || SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + wrap = increment( smpte ); + smpte.negative = true; + return wrap; + } else if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) { + // We have a zero transition involving only subframes + smpte.subframes = 80 - smpte.subframes; + smpte.negative = true; + return SECONDS; + } + + switch (smpte.rate) { + case MTC_24_FPS: + if (smpte.frames == 0) { + smpte.frames = 23; + wrap = SECONDS; + } + break; + case MTC_25_FPS: + if (smpte.frames == 0) { + smpte.frames = 24; + wrap = SECONDS; + } + break; + case MTC_30_FPS_DROP: + if ((smpte.minutes % 10) && (smpte.seconds == 0)) { + if (smpte.frames <= 2) { + smpte.frames = 29; + wrap = SECONDS; + } + } else if (smpte.frames == 0) { + smpte.frames = 29; + wrap = SECONDS; + } + break; + case MTC_30_FPS: + if (smpte.frames == 0) { + smpte.frames = 29; + wrap = SECONDS; + } + break; + } + + if (wrap == SECONDS) { + if (smpte.seconds == 0) { + smpte.seconds = 59; + wrap = MINUTES; + if (smpte.minutes == 0) { + smpte.minutes = 59; + wrap = HOURS; + smpte.hours--; + } + else { + smpte.minutes--; + } + } else { + smpte.seconds--; + } + } else { + smpte.frames--; + } + + if (SMPTE_IS_ZERO( smpte )) { + smpte.negative = false; + } + + return wrap; +} + + +/** Go to lowest absolute subframe value in this frame (set to 0 :-) ) */ +void +frames_floor( Time& smpte ) +{ + smpte.subframes = 0; + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } +} + + +/** Increment @a smpte by one subframe */ +Wrap +increment_subframes( Time& smpte ) +{ + Wrap wrap = NONE; + + if (smpte.negative) { + smpte.negative = false; + wrap = decrement_subframes( smpte ); + if (!SMPTE_IS_ZERO(smpte)) { + smpte.negative = true; + } + return wrap; + } + + smpte.subframes++; + if (smpte.subframes >= 80) { + smpte.subframes = 0; + increment( smpte ); + return FRAMES; + } + return NONE; +} + + +/** Decrement @a smpte by one subframe */ +Wrap +decrement_subframes( Time& smpte ) +{ + Wrap wrap = NONE; + + if (smpte.negative) { + smpte.negative = false; + wrap = increment_subframes( smpte ); + smpte.negative = true; + return wrap; + } + + if (smpte.subframes <= 0) { + smpte.subframes = 0; + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = true; + smpte.subframes = 1; + return FRAMES; + } else { + decrement( smpte ); + smpte.subframes = 79; + return FRAMES; + } + } else { + smpte.subframes--; + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } + return NONE; + } +} + + +/** Go to next whole second (frames == 0 or frames == 2) */ +Wrap +increment_seconds( Time& smpte ) +{ + Wrap wrap = NONE; + + // Clear subframes + frames_floor( smpte ); + + if (smpte.negative) { + // Wrap second if on second boundary + wrap = increment(smpte); + // Go to lowest absolute frame value + seconds_floor( smpte ); + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } + } else { + // Go to highest possible frame in this second + switch (smpte.rate) { + case MTC_24_FPS: + smpte.frames = 23; + break; + case MTC_25_FPS: + smpte.frames = 24; + break; + case MTC_30_FPS_DROP: + case MTC_30_FPS: + smpte.frames = 29; + break; + } + + // Increment by one frame + wrap = increment( smpte ); + } + + return wrap; +} + + +/** Go to lowest (absolute) frame value in this second + * Doesn't care about positive/negative */ +void +seconds_floor( Time& smpte ) +{ + // Clear subframes + frames_floor( smpte ); + + // Go to lowest possible frame in this second + switch (smpte.rate) { + case MTC_24_FPS: + case MTC_25_FPS: + case MTC_30_FPS: + smpte.frames = 0; + break; + case MTC_30_FPS_DROP: + if ((smpte.minutes % 10) && (smpte.seconds == 0)) { + smpte.frames = 2; + } else { + smpte.frames = 0; + } + break; + } + + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } +} + + +/** Go to next whole minute (seconds == 0, frames == 0 or frames == 2) */ +Wrap +increment_minutes( Time& smpte ) +{ + Wrap wrap = NONE; + + // Clear subframes + frames_floor( smpte ); + + if (smpte.negative) { + // Wrap if on minute boundary + wrap = increment_seconds( smpte ); + // Go to lowest possible value in this minute + minutes_floor( smpte ); + } else { + // Go to highest possible second + smpte.seconds = 59; + // Wrap minute by incrementing second + wrap = increment_seconds( smpte ); + } + + return wrap; +} + + +/** Go to lowest absolute value in this minute */ +void +minutes_floor( Time& smpte ) +{ + // Go to lowest possible second + smpte.seconds = 0; + // Go to lowest possible frame + seconds_floor( smpte ); + + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } +} + + +/** Go to next whole hour (minute = 0, second = 0, frame = 0) */ +Wrap +increment_hours( Time& smpte ) +{ + Wrap wrap = NONE; + + // Clear subframes + frames_floor(smpte); + + if (smpte.negative) { + // Wrap if on hour boundary + wrap = increment_minutes( smpte ); + // Go to lowest possible value in this hour + hours_floor( smpte ); + } else { + smpte.minutes = 59; + wrap = increment_minutes( smpte ); + } + + return wrap; +} + + +/** Go to lowest absolute value in this hour */ +void +hours_floor( Time& smpte ) +{ + smpte.minutes = 0; + smpte.seconds = 0; + smpte.frames = 0; + smpte.subframes = 0; + + if (SMPTE_IS_ZERO(smpte)) { + smpte.negative = false; + } +} + + +} // namespace SMPTE diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 77a4dca805..70cbd181c8 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -1,7 +1,7 @@ #ifndef ardour_generic_midi_control_protocol_h #define ardour_generic_midi_control_protocol_h -#include "control_protocol.h" +#include <control_protocol/control_protocol.h> namespace MIDI { class Port; diff --git a/libs/surfaces/generic_midi/interface.cc b/libs/surfaces/generic_midi/interface.cc index 625ac65273..c6c59c6589 100644 --- a/libs/surfaces/generic_midi/interface.cc +++ b/libs/surfaces/generic_midi/interface.cc @@ -1,5 +1,4 @@ -#include "control_protocol.h" - +#include <control_protocol/control_protocol.h> #include "generic_midi_control_protocol.h" using namespace ARDOUR; diff --git a/libs/surfaces/tranzport/interface.cc b/libs/surfaces/tranzport/interface.cc index 20f38dce08..29a0fde043 100644 --- a/libs/surfaces/tranzport/interface.cc +++ b/libs/surfaces/tranzport/interface.cc @@ -1,5 +1,4 @@ -#include "control_protocol.h" - +#include <control_protocol/control_protocol.h> #include "tranzport_control_protocol.h" using namespace ARDOUR; diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.cc b/libs/surfaces/tranzport/tranzport_control_protocol.cc index 0b08bd633e..619f65678a 100644 --- a/libs/surfaces/tranzport/tranzport_control_protocol.cc +++ b/libs/surfaces/tranzport/tranzport_control_protocol.cc @@ -324,7 +324,7 @@ TranzportControlProtocol::show_transport_time () if (where != last_where) { char buf[5]; - SMPTE_Time smpte; + SMPTE::Time smpte; session->smpte_time (where, smpte); diff --git a/libs/surfaces/tranzport/tranzport_control_protocol.h b/libs/surfaces/tranzport/tranzport_control_protocol.h index 44045f6834..546cc2f2af 100644 --- a/libs/surfaces/tranzport/tranzport_control_protocol.h +++ b/libs/surfaces/tranzport/tranzport_control_protocol.h @@ -11,7 +11,7 @@ #include <ardour/types.h> -#include "control_protocol.h" +#include <control_protocol/control_protocol.h> class TranzportControlProtocol : public ARDOUR::ControlProtocol { |