diff options
51 files changed, 833 insertions, 1037 deletions
diff --git a/SConstruct b/SConstruct index af89a24a2d..fbe018d80c 100644 --- a/SConstruct +++ b/SConstruct @@ -11,6 +11,8 @@ import platform from sets import Set import SCons.Node.FS +#import pickle + SConsignFile() EnsureSConsVersion(0, 96) @@ -459,7 +461,12 @@ libraries['dmalloc'] = conf.Finish () conf = Configure(env) -if conf.CheckCHeader('alsa/asoundlib.h'): +if conf.CheckCHeader('jack/midiport.h'): + libraries['sysmidi'] = LibraryInfo (LIBS='jack') + env['SYSMIDI'] = 'JACK MIDI' + subst_dict['%MIDITAG%'] = "control" + subst_dict['%MIDITYPE%'] = "jack" +elif conf.CheckCHeader('alsa/asoundlib.h'): libraries['sysmidi'] = LibraryInfo (LIBS='asound') env['SYSMIDI'] = 'ALSA Sequencer' subst_dict['%MIDITAG%'] = "seq" @@ -587,6 +594,12 @@ Help(opts.GenerateHelpText(env)) if os.environ.has_key('PATH'): env.Append(PATH = os.environ['PATH']) +if os.environ.has_key('TERM'): + env.Append(PATH = os.environ['TERM']) + +if os.environ.has_key('HOME'): + env.Append(HOME = os.environ['HOME']) + if os.environ.has_key('PKG_CONFIG_PATH'): env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH']) @@ -859,7 +872,9 @@ for subdir in coredirs: for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]: for subdir in sublistdir: SConscript (subdir + '/SConscript') - + +#pickle.dump(env, open('.scons_env', 'w'), pickle.HIGHEST_PROTOCOL) + # cleanup env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log']) diff --git a/ardour.dox b/ardour.dox index bd9d6a34db..ad694477c4 100644 --- a/ardour.dox +++ b/ardour.dox @@ -202,7 +202,7 @@ OPTIMIZE_OUTPUT_JAVA = NO # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. -BUILTIN_STL_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first @@ -233,12 +233,12 @@ EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. -EXTRACT_PRIVATE = NO +EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. @@ -295,7 +295,7 @@ INTERNAL_DOCS = NO # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. -CASE_SENSE_NAMES = NO +CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the @@ -342,7 +342,7 @@ SORT_BY_SCOPE_NAME = NO # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. -GENERATE_TODOLIST = NO +GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test @@ -354,13 +354,13 @@ GENERATE_TESTLIST = NO # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. -GENERATE_BUGLIST = NO +GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. -GENERATE_DEPRECATEDLIST= NO +GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. @@ -459,7 +459,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = libs/pbd3 libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour +INPUT = libs/pbd3 libs/midi++2 libs/ardour #libs/gtkmm2ext gtk2_ardour # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -1082,7 +1082,7 @@ CLASS_DIAGRAMS = YES # inheritance and usage relations if the target is undocumented # or is not a class. -HIDE_UNDOC_RELATIONS = YES +HIDE_UNDOC_RELATIONS = NO # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization diff --git a/gtk2_ardour/ardev_common.sh b/gtk2_ardour/ardev_common.sh index a705101adb..9483ae2971 100755 --- a/gtk2_ardour/ardev_common.sh +++ b/gtk2_ardour/ardev_common.sh @@ -1,6 +1,6 @@ #export G_DEBUG=fatal_criticals -export ARDOUR_PATH=./glade:./pixmaps:.:.. +export ARDOUR_PATH=./glade:./pixmaps:. export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd3:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libglademm:$LD_LIBRARY_PATH diff --git a/gtk2_ardour/ardour2_ui.rc b/gtk2_ardour/ardour2_ui.rc index 0e3f067b57..ac4f055df6 100644 --- a/gtk2_ardour/ardour2_ui.rc +++ b/gtk2_ardour/ardour2_ui.rc @@ -81,16 +81,20 @@ style "time_axis_view_item_name" style "default_base" = "medium_text" { GtkWidget::cursor_color = {1.0, 1.0, 1.0 } + GtkButton::default_border = { 0, 0, 0, 0 } + GtkButton::default_outside_border = { 0, 0, 0, 0 } + GtkTreeView::vertical-padding = 0 + GtkTreeView::horizontal-padding = 0 fg[NORMAL] = { 0.80, 0.80, 0.80 } fg[ACTIVE] = { 0.80, 0.80, 0.80 } - fg[PRELIGHT] = { 0.50, 1.0, 1.0 } + fg[PRELIGHT] = { 1.0, 1.0, 1.0 } fg[INSENSITIVE] = { 0.80, 0.80, 0.80 } fg[SELECTED] = { 0.80, 0.80, 0.80 } bg[NORMAL] = { 0.40, 0.40, 0.40 } bg[ACTIVE] = { 0.40, 0.40, 0.40 } - bg[PRELIGHT] = { 0.40, 0.40, 0.40 } + bg[PRELIGHT] = "#565690" bg[INSENSITIVE] = { 0.10, 0.10, 0.10 } bg[SELECTED] = { 0, 0.40, 0.60 } @@ -105,6 +109,13 @@ style "default_base" = "medium_text" base[PRELIGHT] = { 0.20, 0.20, 0.20 } base[INSENSITIVE] = "#4c5159" base[SELECTED] = { 0.25, 0.25, 0.25 } + + engine "clearlooks" { + menubarstyle = 2 # 0 = flat, 1 = sunken, 2 = flat gradient + menuitemstyle = 1 # 0 = flat, 1 = 3d-ish (gradient), 2 = 3d-ish (button) + listviewitemstyle = 1 # 0 = flat, 1 = 3d-ish (gradient) + progressbarstyle = 0 # 0 = candy bar, 1 = flat + } } style "base_frame" @@ -131,11 +142,11 @@ style "black_mackie_menu_bar" = "medium_bold_text" style "default_buttons_menus" { font_name = "sans 8" - fg[ACTIVE] = { 0, 0, 0 } + fg[ACTIVE] = { 1.0, 1.0, 1.0 } - bg[NORMAL] = { 0.25, 0.25, 0.25 } - bg[ACTIVE] = { 0.50, 1.0, 1.0 } - bg[PRELIGHT] = { 0.15, 0.15, 0.15 } + bg[NORMAL] = { 0.35, 0.35, 0.35 } + bg[ACTIVE] = "#565690" + bg[PRELIGHT] = { 0.20, 0.20, 0.20 } bg[INSENSITIVE] = { 0.20, 0.20, 0.20 } bg[SELECTED] = { 0.20, 0.20, 0.20 } } @@ -239,6 +250,7 @@ style "time_button" = "default_buttons_menus" style "transport_button" { bg[ACTIVE] = { 0.50, 1.0, 0.50 } + fg[ACTIVE] = { 0, 0, 0 } } style "transport_rec_button" @@ -853,8 +865,8 @@ style "region_list_whole_file" style "ardour_button" ="default_buttons_menus" { - xthickness = 0 - ythickness = 2 + xthickness = 1 + ythickness = 1 } #--------------------------------------------------------------- diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 3baa9ede18..146d4d2ffe 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -409,7 +409,7 @@ If you still wish to quit, please use the\n\n\ break; } } - + Config->save_state(); quit (); } diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc index 826823885c..dbdcd6ae45 100644 --- a/gtk2_ardour/ardour_ui_options.cc +++ b/gtk2_ardour/ardour_ui_options.cc @@ -39,24 +39,48 @@ using namespace ARDOUR; void ARDOUR_UI::setup_config_options () { + std::vector<Glib::ustring> groups; + groups.push_back("options"); + groups.push_back("Editor"); + struct { char* name; bool (Configuration::*method)(void) const; + char act_type; // (t)oggle or (r)adio } options[] = { - { "ToggleTimeMaster", &Configuration::get_jack_time_master }, - { "StopPluginsWithTransport", &Configuration::get_plugins_stop_with_transport }, - { "LatchedRecordEnable", &Configuration::get_latched_record_enable }, - { "VerifyRemoveLastCapture", &Configuration::get_verify_remove_last_capture }, - { "StopRecordingOnXrun", &Configuration::get_stop_recording_on_xrun }, - { "StopTransportAtEndOfSession", &Configuration::get_stop_at_session_end }, - { 0, 0 } + { "ToggleTimeMaster", &Configuration::get_jack_time_master, 't' }, + { "StopPluginsWithTransport", &Configuration::get_plugins_stop_with_transport, 't' }, + { "LatchedRecordEnable", &Configuration::get_latched_record_enable, 't' }, + { "VerifyRemoveLastCapture", &Configuration::get_verify_remove_last_capture, 't' }, + { "StopRecordingOnXrun", &Configuration::get_stop_recording_on_xrun, 't' }, + { "StopTransportAtEndOfSession", &Configuration::get_stop_at_session_end, 't' }, + { "UseHardwareMonitoring", &Configuration::get_use_hardware_monitoring, 'r' }, + { "UseSoftwareMonitoring", &Configuration::get_use_sw_monitoring, 'r' }, + { "UseExternalMonitoring", &Configuration::get_use_external_monitoring, 'r' }, + { "MeterFalloffOff", &Configuration::get_meter_falloff_off, 'r' }, + { "MeterFalloffSlowest", &Configuration::get_meter_falloff_slowest, 'r' }, + { "MeterFalloffSlow", &Configuration::get_meter_falloff_slow, 'r' }, + { "MeterFalloffMedium", &Configuration::get_meter_falloff_medium, 'r' }, + { "MeterFalloffFast", &Configuration::get_meter_falloff_fast, 'r' }, + { "MeterFalloffFaster", &Configuration::get_meter_falloff_faster, 'r' }, + { "MeterFalloffFastest", &Configuration::get_meter_falloff_fastest, 'r' }, + { "MeterHoldOff", &Configuration::get_meter_hold_off, 'r' }, + { "MeterHoldShort", &Configuration::get_meter_hold_short, 'r' }, + { "MeterHoldMedium", &Configuration::get_meter_hold_medium, 'r' }, + { "MeterHoldLong", &Configuration::get_meter_hold_long, 'r' }, + { 0, 0, 0 } }; for (uint32_t n = 0; options[n].name; ++n) { - Glib::RefPtr<Action> act = ActionManager::get_action ("options", options[n].name); - if (act) { - Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); - tact->set_active ((Config->*(options[n].method))()); + for (std::vector<Glib::ustring>::iterator i = groups.begin(); i != groups.end(); i++) { + Glib::RefPtr<Action> act = ActionManager::get_action (i->c_str(), options[n].name); + if (act) { + Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); + cerr << "action = " << (options[n].name) << " val = " << (Config->*(options[n].method))() << endl;//DEBUG + if (options[n].act_type == 't' || (options[n].act_type == 'r' && (Config->*(options[n].method))())) + tact->set_active ((Config->*(options[n].method))()); + continue; + } } } } @@ -230,12 +254,14 @@ ARDOUR_UI::toggle_editing_space() void ARDOUR_UI::toggle_UseHardwareMonitoring() { - Glib::RefPtr<Action> act = ActionManager::get_action ("options", "UseSoftwareMonitoring"); + Glib::RefPtr<Action> act = ActionManager::get_action ("options", "UseHardwareMonitoring"); if (act) { Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act); + cerr << "get_active() cond = " << tact->get_active() << endl;//DEBUG if (tact->get_active()) { Config->set_use_hardware_monitoring (true); Config->set_use_sw_monitoring (false); + Config->set_use_external_monitoring (false); if (session) { session->reset_input_monitor_state(); } @@ -252,6 +278,7 @@ ARDOUR_UI::toggle_UseSoftwareMonitoring() if (tact->get_active()) { Config->set_use_hardware_monitoring (false); Config->set_use_sw_monitoring (true); + Config->set_use_external_monitoring (false); if (session) { session->reset_input_monitor_state(); } @@ -268,6 +295,7 @@ ARDOUR_UI::toggle_UseExternalMonitoring() if (tact->get_active()) { Config->set_use_hardware_monitoring (false); Config->set_use_sw_monitoring (false); + Config->set_use_external_monitoring (true); if (session) { session->reset_input_monitor_state(); } diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc index 506b082b53..cd97489120 100644 --- a/gtk2_ardour/audio_clock.cc +++ b/gtk2_ardour/audio_clock.cc @@ -435,7 +435,7 @@ void AudioClock::set_smpte (jack_nframes_t when, bool force) { char buf[32]; - SMPTE_Time smpte; + SMPTE::Time smpte; if (is_duration) { session->smpte_duration (when, smpte); @@ -1259,7 +1259,7 @@ AudioClock::smpte_frame_from_display () const return 0; } - SMPTE_Time smpte; + SMPTE::Time smpte; jack_nframes_t sample; smpte.hours = atoi (hours_label.get_text()); @@ -1280,19 +1280,19 @@ AudioClock::smpte_frame_from_display () const #define SMPTE_SAMPLE_TEST_7 // Testcode for smpte<->sample conversions (P.S.) - SMPTE_Time smpte1; + SMPTE::Time smpte1; jack_nframes_t sample1; jack_nframes_t oldsample = 0; - SMPTE_Time smpte2; + SMPTE::Time smpte2; jack_nframes_t sample_increment; - sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second); + sample_increment = (long)rint(session->frame_rate() / SMPTE::frames_per_second); #ifdef SMPTE_SAMPLE_TEST_1 // Test 1: use_offset = false, use_subframes = false cout << "use_offset = false, use_subframes = false" << endl; for (int i = 0; i < 108003; i++) { - session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ ); if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) { @@ -1313,7 +1313,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment( smpte1 ); + SMPTE::increment( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; @@ -1337,7 +1337,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 108003; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; @@ -1363,7 +1363,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment( smpte1 ); + SMPTE::increment( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; @@ -1380,7 +1380,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 108003; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; @@ -1406,7 +1406,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_decrement( smpte1 ); + SMPTE::decrement( smpte1 ); } cout << "sample_decrement: " << sample_increment << endl; @@ -1433,7 +1433,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 108003; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ ); if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) { @@ -1454,7 +1454,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment( smpte1 ); + SMPTE::increment( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; @@ -1462,7 +1462,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; for (int i = 0; i < 108003; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ ); if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) { @@ -1483,7 +1483,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_decrement( smpte1 ); + SMPTE::decrement( smpte1 ); } cout << "sample_decrement: " << sample_increment << endl; @@ -1510,7 +1510,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 3600; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; @@ -1533,7 +1533,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment_seconds( smpte1 ); + SMPTE::increment_seconds( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; @@ -1559,7 +1559,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 60; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; @@ -1582,7 +1582,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment_minutes( smpte1 ); + SMPTE::increment_minutes( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; @@ -1607,7 +1607,7 @@ AudioClock::smpte_frame_from_display () const cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; for (int i = 0; i < 10; i++) { - session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; @@ -1630,7 +1630,7 @@ AudioClock::smpte_frame_from_display () const break; } oldsample = sample1; - session->smpte_increment_hours( smpte1 ); + SMPTE::increment_hours( smpte1 ); } cout << "sample_increment: " << sample_increment << endl; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 6d834ef7a4..307cd71799 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -296,7 +296,7 @@ class Editor : public PublicEditor void toggle_waveforms_while_recording (); void toggle_measure_visibility (); - void set_meter_falloff (float); + void set_meter_falloff (int); void set_meter_hold (int32_t); /* xfades */ diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 161d015583..d88cda61e6 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -371,13 +371,13 @@ Editor::register_actions () Slow = 6.8dB/sec falloff at update rate of 40ms */ - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffOff"), _("Off"), bind (mem_fun (*this, &Editor::set_meter_falloff), 0.0f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffSlowest"), _("Slowest"), bind (mem_fun (*this, &Editor::set_meter_falloff), 0.266f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffSlow"), _("Slow"), bind (mem_fun (*this, &Editor::set_meter_falloff), 0.342f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffMedium"), _("Medium"), bind (mem_fun (*this, &Editor::set_meter_falloff), 0.7f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFast"), _("Fast"), bind (mem_fun (*this, &Editor::set_meter_falloff), 1.1f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFaster"), _("Faster"), bind (mem_fun (*this, &Editor::set_meter_falloff), 1.5f)); - ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFastest"), _("Fastest"), bind (mem_fun (*this, &Editor::set_meter_falloff), 2.5f)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffOff"), _("Off"), bind (mem_fun (*this, &Editor::set_meter_falloff), 0)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffSlowest"), _("Slowest"), bind (mem_fun (*this, &Editor::set_meter_falloff), 1)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffSlow"), _("Slow"), bind (mem_fun (*this, &Editor::set_meter_falloff), 2)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffMedium"), _("Medium"), bind (mem_fun (*this, &Editor::set_meter_falloff), 3)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFast"), _("Fast"), bind (mem_fun (*this, &Editor::set_meter_falloff), 4)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFaster"), _("Faster"), bind (mem_fun (*this, &Editor::set_meter_falloff), 5)); + ActionManager::register_radio_action (editor_actions, meter_falloff_group, X_("MeterFalloffFastest"), _("Fastest"), bind (mem_fun (*this, &Editor::set_meter_falloff), 6)); ActionManager::register_radio_action (editor_actions, meter_hold_group, X_("MeterHoldOff"), _("Off"), bind (mem_fun (*this, &Editor::set_meter_hold), 0)); ActionManager::register_radio_action (editor_actions, meter_hold_group, X_("MeterHoldShort"), _("Short"), bind (mem_fun (*this, &Editor::set_meter_hold), 40)); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 1409da77a9..bca0942841 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -3417,7 +3417,7 @@ void Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xpos, double ypos) { char buf[128]; - SMPTE_Time smpte; + SMPTE::Time smpte; BBT_Time bbt; float secs; @@ -3461,7 +3461,7 @@ void Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset, double xpos, double ypos) { char buf[128]; - SMPTE_Time smpte; + SMPTE::Time smpte; BBT_Time sbbt; BBT_Time ebbt; float secs; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index bccdce27c1..acf205d06f 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -93,14 +93,78 @@ Editor::redo (uint32_t n) void Editor::set_meter_hold (int32_t cnt) { + Config->set_meter_hold_off(false); + Config->set_meter_hold_short(false); + Config->set_meter_hold_medium(false); + Config->set_meter_hold_long(false); + + switch (cnt) + { + case 0: + Config->set_meter_hold_off(true); + break; + case 40: + Config->set_meter_hold_short(true); + break; + case 100: + Config->set_meter_hold_medium(true); + break; + case 200: + Config->set_meter_hold_long(true); + break; + } + if (session) { session->set_meter_hold (cnt); } } void -Editor::set_meter_falloff (float val) -{ +Editor::set_meter_falloff (int intval) +{ + float val; + std::string str; + cerr << "set_meter_falloff () called: intval = " << intval << endl; + Config->set_meter_falloff_off(false); + Config->set_meter_falloff_slowest(false); + Config->set_meter_falloff_slow(false); + Config->set_meter_falloff_medium(false); + Config->set_meter_falloff_fast(false); + Config->set_meter_falloff_faster(false); + Config->set_meter_falloff_fastest(false); + + switch (intval) + { + case 0: + val = 0.0f; + Config->set_meter_falloff_off(true); + break; + case 1: + val = 0.266f; + Config->set_meter_falloff_slowest(true); + break; + case 2: + val = 0.342f; + Config->set_meter_falloff_slow(true); + break; + case 3: + val = 0.7f; + Config->set_meter_falloff_medium(true); + break; + case 4: + val = 1.1f; + Config->set_meter_falloff_fast(true); + break; + case 5: + val = 1.5f; + Config->set_meter_falloff_faster(true); + break; + case 6: + val = 2.5f; + Config->set_meter_falloff_fastest(true); + break; + } + if (session) { session->set_meter_falloff (val); } diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc index 1fe4e0711c..d3a1e9670b 100644 --- a/gtk2_ardour/editor_rulers.cc +++ b/gtk2_ardour/editor_rulers.cc @@ -24,6 +24,7 @@ #include <string> #include <ardour/tempo.h> +#include <ardour/smpte.h> #include <gtkmm2ext/gtk_ui.h> #include "editor.h" @@ -798,7 +799,7 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp jack_nframes_t pos; jack_nframes_t spacer; jack_nframes_t fr; - SMPTE_Time smpte; + SMPTE::Time smpte; gchar buf[16]; gint nmarks = 0; gint n; @@ -927,13 +928,13 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp (*marks)[n].position = pos; // Increment subframes by one - session->smpte_increment_subframes( smpte ); + SMPTE::increment_subframes( smpte ); } } else if (show_seconds) { // Find smpte time of this sample (pos) session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); // Go to next whole second down - session->smpte_seconds_floor( smpte ); + SMPTE::seconds_floor( smpte ); for (n = 0; n < nmarks; n++) { session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); @@ -953,13 +954,13 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp } (*marks)[n].label = g_strdup (buf); - session->smpte_increment_seconds( smpte ); + SMPTE::increment_seconds( smpte ); } } else if (show_minutes) { // Find smpte time of this sample (pos) session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); // Go to next whole minute down - session->smpte_minutes_floor( smpte ); + SMPTE::minutes_floor( smpte ); for (n = 0; n < nmarks; n++) { session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); @@ -977,13 +978,13 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp } (*marks)[n].label = g_strdup (buf); (*marks)[n].position = pos; - session->smpte_increment_minutes( smpte ); + SMPTE::increment_minutes( smpte ); } } else if (show_hours) { // Find smpte time of this sample (pos) session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); // Go to next whole hour down - session->smpte_hours_floor( smpte ); + SMPTE::hours_floor( smpte ); for (n = 0; n < nmarks; n++) { session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); @@ -998,13 +999,13 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp (*marks)[n].label = g_strdup (buf); (*marks)[n].position = pos; - session->smpte_increment_hours( smpte ); + SMPTE::increment_hours( smpte ); } } else { // show_frames // Find smpte time of this sample (pos) session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); // Go to next whole frame down - session->smpte_frames_floor( smpte ); + SMPTE::frames_floor( smpte ); for (n = 0; n < nmarks; n++) { session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); @@ -1019,7 +1020,7 @@ Editor::metric_get_smpte (GtkCustomRulerMark **marks, gdouble lower, gdouble upp } (*marks)[n].label = g_strdup (buf); - session->smpte_increment( smpte ); + SMPTE::increment( smpte ); } } diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc index b4eb2df9e9..20630e4f1c 100644 --- a/gtk2_ardour/main.cc +++ b/gtk2_ardour/main.cc @@ -251,8 +251,10 @@ which_ui_rcfile () if (rcfile.empty()) { warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg; + } else { + cerr << "Loading ui configuration file " << rcfile << endl; } - + return rcfile; } diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 2e4c3a6ae7..9bdc8c340a 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -414,14 +414,14 @@ MixerStrip::set_width (Width w) set_size_request (-1, -1); xml_node->add_property ("strip_width", "wide"); - rec_enable_button->set_label (_("Record")); - mute_button->set_label (_("Mute")); - solo_button->set_label (_("Solo")); + rec_enable_button->set_label (_("record")); + mute_button->set_label (_("mute")); + solo_button->set_label (_("solo")); if (_route.comment() == "") { - comment_button.set_label (_("Comments")); + comment_button.set_label (_("comments")); } else { - comment_button.set_label (_("*Comments*")); + comment_button.set_label (_("*comments*")); } gpm.gain_automation_style_button.set_label (gpm.astyle_string(_route.gain_automation_curve().automation_style())); diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 93593bad18..a9d5daab1d 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -93,6 +93,7 @@ tempo.cc utils.cc version.cc mix.cc +smpte.cc """) arch_specific_objects = [ ] diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 9a45fd3c7c..85c7897026 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -17,12 +17,13 @@ CONFIG_VARIABLE(bool, mute_affects_post_fader, "mute-affects-post-fader", true) CONFIG_VARIABLE(bool, mute_affects_control_outs, "mute-affects-control-outs", true) CONFIG_VARIABLE(bool, mute_affects_main_outs, "mute-affects-main-outs", true) CONFIG_VARIABLE(bool, solo_latch, "solo-latch", true) -CONFIG_VARIABLE(bool, use_hardware_monitoring, "use-hardware-monitoring", true) +CONFIG_VARIABLE(bool, use_hardware_monitoring, "use-hardware-monitoring", false) +CONFIG_VARIABLE(bool, use_sw_monitoring, "use-sw-monitoring", false) +CONFIG_VARIABLE(bool, use_external_monitoring, "use-external-monitoring", true) CONFIG_VARIABLE(bool, jack_time_master, "jack-time-master", true) CONFIG_VARIABLE(bool, trace_midi_input, "trace-midi-input", false) CONFIG_VARIABLE(bool, trace_midi_output, "trace-midi-output", false) CONFIG_VARIABLE(bool, plugins_stop_with_transport, "plugins-stop-with-transport", false) -CONFIG_VARIABLE(bool, use_sw_monitoring, "use-sw-monitoring", true) CONFIG_VARIABLE(bool, stop_recording_on_xrun, "stop-recording-on-xrun", false) CONFIG_VARIABLE(bool, verify_remove_last_capture, "verify-remove-last-capture", true) CONFIG_VARIABLE(bool, stop_at_session_end, "stop-at-session-end", true) @@ -41,6 +42,19 @@ CONFIG_VARIABLE(HeaderFormat, native_file_header_format, "native-file-header-fo CONFIG_VARIABLE(bool, use_tranzport, "use-tranzport", false) CONFIG_VARIABLE(uint32_t, osc_port, "osc-port", 3819) CONFIG_VARIABLE(bool, use_osc, "use-osc", true) +CONFIG_VARIABLE(bool, use_overlap_equivalency, "use-overlap-equivalency", true) +CONFIG_VARIABLE(bool, meter_falloff_off, "meter-falloff-off", false) +CONFIG_VARIABLE(bool, meter_falloff_slowest, "meter-falloff-slowest", false) +CONFIG_VARIABLE(bool, meter_falloff_slower, "meter-falloff-slower", false) +CONFIG_VARIABLE(bool, meter_falloff_slow, "meter-falloff-slow", false) +CONFIG_VARIABLE(bool, meter_falloff_medium, "meter-falloff-medium", false) +CONFIG_VARIABLE(bool, meter_falloff_fast, "meter-falloff-fast", true) +CONFIG_VARIABLE(bool, meter_falloff_faster, "meter-falloff-faster", false) +CONFIG_VARIABLE(bool, meter_falloff_fastest, "meter-falloff-fastest", false) +CONFIG_VARIABLE(bool, meter_hold_off, "meter-hold-off", false) +CONFIG_VARIABLE(bool, meter_hold_short, "meter-hold-short", false) +CONFIG_VARIABLE(bool, meter_hold_medium, "meter-hold-medium", false) +CONFIG_VARIABLE(bool, meter_hold_long, "meter-hold-long", false) /* these variables have custom set() methods */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 0d968fcff1..189cf77ac9 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -585,24 +585,13 @@ class Session : public sigc::trackable, public Stateful void bbt_time (jack_nframes_t when, BBT_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_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_string (char *, jack_nframes_t) const; void set_smpte_offset (jack_nframes_t); @@ -1271,7 +1260,7 @@ class Session : public sigc::trackable, public Stateful void remove_empty_sounds (); void setup_midi_control (); - int midi_read (MIDI::Port *); + //int midi_read (MIDI::Port *); void enable_record (); @@ -1297,13 +1286,13 @@ class Session : public sigc::trackable, public Stateful void *do_work(); void set_next_event (); - void process_event (Event *); + void process_event (Event *ev); /* MIDI Machine Control */ void deliver_mmc (MIDI::MachineControl::Command, jack_nframes_t); - void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes); - void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size); + //void deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t, MIDI::EventTwoBytes); + //void deliver_data (MIDI::Port* port, MIDI::byte*, int32_t size); void spp_start (MIDI::Parser&); void spp_continue (MIDI::Parser&); @@ -1338,7 +1327,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 */ @@ -1347,22 +1336,18 @@ class Session : public sigc::trackable, public Stateful jack_nframes_t _smpte_offset; bool _smpte_offset_negative; - /* cache the most-recently requested time conversions. - this helps when we have multiple clocks showing the - same time (e.g. the transport frame) - */ - - bool last_smpte_valid; - jack_nframes_t last_smpte_when; - SMPTE_Time last_smpte; + /* cache the most-recently requested time conversions. This helps when we + * have multiple clocks showing the same time (e.g. the transport frame) */ + bool last_smpte_valid; + jack_nframes_t last_smpte_when; + SMPTE::Time last_smpte; + + bool _send_smpte_update; ///< Send a full MTC timecode this cycle - int send_full_time_code (); - int send_midi_time_code (); + int send_full_time_code(jack_nframes_t nframes); + int send_midi_time_code_for_cycle(jack_nframes_t nframes); - void send_full_time_code_in_another_thread (); - void send_midi_time_code_in_another_thread (); - void send_time_code_in_another_thread (bool full); - void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0); + //void send_mmc_in_another_thread (MIDI::MachineControl::Command, jack_nframes_t frame = 0); jack_nframes_t adjust_apparent_position (jack_nframes_t frames); @@ -1417,17 +1402,17 @@ class Session : public sigc::trackable, public Stateful static MultiAllocSingleReleasePool pool; }; - PBD::Lock midi_lock; - pthread_t midi_thread; - int midi_request_pipe[2]; + //PBD::Lock midi_lock; + //pthread_t midi_thread; + //int midi_request_pipe[2]; atomic_t butler_active; - RingBuffer<MIDIRequest*> midi_requests; - + //RingBuffer<MIDIRequest*> midi_requests; +/* int start_midi_thread (); void terminate_midi_thread (); void poke_midi_thread (); static void *_midi_thread_work (void *arg); - void midi_thread_work (); + void midi_thread_work ();*/ void change_midi_ports (); int use_config_midi_ports (); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 3d7ab4b59a..9cfe9d3a27 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 <ardour/smpte.h> #include <map> #if __GNUC__ < 3 @@ -99,33 +100,6 @@ namespace ARDOUR { 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/audioengine.cc b/libs/ardour/audioengine.cc index 9d736f765e..a0cf29eb89 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -212,6 +212,7 @@ AudioEngine::_graph_order_callback (void *arg) return 0; } +/** @callgraph */ int AudioEngine::_process_callback (jack_nframes_t nframes, void *arg) { @@ -224,6 +225,7 @@ AudioEngine::_freewheel_callback (int onoff, void *arg) static_cast<AudioEngine*>(arg)->_freewheeling = onoff; } +/** @callgraph */ int AudioEngine::process_callback (jack_nframes_t nframes) { diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 4879e373d5..82310b3564 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -40,6 +40,7 @@ #include <midi++/mmc.h> #include <ardour/ardour.h> +#include <ardour/audioengine.h> #include <ardour/audio_library.h> #include <ardour/configuration.h> #include <ardour/plugin_manager.h> @@ -91,7 +92,7 @@ setup_osc () } static int -setup_midi () +setup_midi (AudioEngine& engine) { std::map<string,Configuration::MidiPortDescriptor*>::iterator i; int nports; @@ -101,6 +102,8 @@ setup_midi () return 0; } + MIDI::Manager::instance()->set_api_data(engine.jack()); + for (i = Config->midi_ports.begin(); i != Config->midi_ports.end(); ++i) { Configuration::MidiPortDescriptor* port_descriptor; @@ -112,7 +115,9 @@ setup_midi () port_descriptor->type); if (request.status != MIDI::PortRequest::OK) { - error << string_compose(_("MIDI port specifications for \"%1\" are not understandable."), port_descriptor->tag) << endmsg; + error << string_compose( + _("MIDI port specifications for \"%1\" (%2, %3) are not understandable."), + port_descriptor->tag, port_descriptor->mode, port_descriptor->type) << endmsg; continue; } @@ -163,12 +168,15 @@ setup_midi () if (default_mmc_port == 0) { warning << string_compose (_("No MMC control (MIDI port \"%1\" not available)"), Config->get_mmc_port_name()) << endmsg; - return 0; + //return 0; } if (default_mtc_port == 0) { warning << string_compose (_("No MTC support (MIDI port \"%1\" not available)"), Config->get_mtc_port_name()) << endmsg; + } else { + // [DR] + warning << "MTC port available" << endl; } if (default_midi_port == 0) { @@ -194,7 +202,7 @@ ARDOUR::init (AudioEngine& engine, bool use_vst, bool try_optimization, void (*s Config->set_use_vst (use_vst); - if (setup_midi ()) { + if (setup_midi (engine)) { return -1; } 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.cc b/libs/ardour/session.cc index a8ab2204dc..569060fe65 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -247,7 +247,8 @@ Session::Session (AudioEngine &eng, _mtc_port (default_mtc_port), _midi_port (default_midi_port), pending_events (2048), - midi_requests (128), // the size of this should match the midi request pool size + //midi_requests (128), // the size of this should match the midi request pool size + _send_smpte_update (false), main_outs (0) { bool new_session; @@ -294,7 +295,7 @@ Session::Session (AudioEngine &eng, _mtc_port (default_mtc_port), _midi_port (default_midi_port), pending_events (2048), - midi_requests (16), + //midi_requests (16), main_outs (0) { @@ -360,7 +361,7 @@ Session::~Session () going_away (); /* EMIT SIGNAL */ terminate_butler_thread (); - terminate_midi_thread (); + //terminate_midi_thread (); if (click_data && click_data != default_click) { delete [] click_data; @@ -1250,7 +1251,8 @@ Session::enable_record () if (atomic_read (&_record_status) != Recording) { atomic_set (&_record_status, Recording); _last_record_location = _transport_frame; - send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe); + // FIXME + //send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe); if (Config->get_use_hardware_monitoring() && auto_input) { /* Even though this can be called from RT context we are using @@ -1285,7 +1287,8 @@ Session::disable_record (bool rt_context, bool force) } } - send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit); + // FIXME + //send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit); if (Config->get_use_hardware_monitoring() && auto_input) { /* Even though this can be called from RT context we are using @@ -1346,7 +1349,8 @@ Session::maybe_enable_record () enable_record (); } } else { - send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordPause); + // FIXME + //send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordPause); RecordStateChanged (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc index 2aeace81f4..5687e3f733 100644 --- a/libs/ardour/session_events.cc +++ b/libs/ardour/session_events.cc @@ -120,6 +120,7 @@ Session::queue_event (Event* ev) } } +/* [DR] Always called from audio thread? */ void Session::merge_event (Event* ev) { @@ -171,10 +172,10 @@ Session::merge_event (Event* ev) set_next_event (); } +/** @return true when @a ev is deleted. */ bool Session::_replace_event (Event* ev) { - // returns true when we deleted the passed in event bool ret = false; Events::iterator i; @@ -203,10 +204,10 @@ Session::_replace_event (Event* ev) return ret; } +/** @return true when @a ev is deleted. */ bool Session::_remove_event (Session::Event* ev) { - // returns true when we deleted the passed in event bool ret = false; Events::iterator i; @@ -310,6 +311,9 @@ Session::process_event (Event* ev) return; } + // FIXME [DR] + printf("Processing event: %s\n", event_names[ev->type]); + switch (ev->type) { case Event::SetLoop: set_auto_loop (ev->yes_or_no); @@ -323,6 +327,7 @@ Session::process_event (Event* ev) // cerr << "soft locate to " << ev->target_frame << endl; start_locate (ev->target_frame, false, true, false); } + _send_smpte_update = true; break; case Event::LocateRoll: @@ -333,6 +338,7 @@ Session::process_event (Event* ev) // cerr << "soft locate to+roll " << ev->target_frame << endl; start_locate (ev->target_frame, true, true, false); } + _send_smpte_update = true; break; case Event::SetTransportSpeed: diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc index aa079f8827..95d6d02f39 100644 --- a/libs/ardour/session_midi.cc +++ b/libs/ardour/session_midi.cc @@ -40,6 +40,7 @@ #include <ardour/diskstream.h> #include <ardour/slave.h> #include <ardour/cycles.h> +#include <ardour/smpte.h> #include "i18n.h" @@ -87,6 +88,7 @@ Session::use_config_midi_ports () void Session::set_mmc_control (bool yn) { +#if 0 if (mmc_control == yn) { return; } @@ -94,13 +96,14 @@ Session::set_mmc_control (bool yn) mmc_control = yn; set_dirty(); poke_midi_thread (); - +#endif ControlChanged (MMCControl); /* EMIT SIGNAL */ } void Session::set_midi_control (bool yn) { +#if 0 if (midi_control == yn) { return; } @@ -115,7 +118,7 @@ Session::set_midi_control (bool yn) (*i)->reset_midi_control (_midi_port, midi_control); } } - +#endif ControlChanged (MidiControl); /* EMIT SIGNAL */ } @@ -468,7 +471,7 @@ void Session::setup_midi_control () { outbound_mtc_smpte_frame = 0; - next_quarter_frame_to_send = -1; + next_quarter_frame_to_send = 0; /* setup the MMC buffer */ @@ -508,6 +511,7 @@ Session::setup_midi_control () } } +#if 0 int Session::midi_read (MIDI::Port* port) { @@ -545,6 +549,7 @@ Session::midi_read (MIDI::Port* port) return 0; } +#endif void Session::spp_start (Parser& ignored) @@ -724,7 +729,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]; @@ -798,76 +803,43 @@ Session::mmc_record_enable (MIDI::MachineControl &mmc, size_t trk, bool enabled) } } -void -Session::send_full_time_code_in_another_thread () -{ - send_time_code_in_another_thread (true); -} - -void -Session::send_midi_time_code_in_another_thread () -{ - send_time_code_in_another_thread (false); -} - -void -Session::send_time_code_in_another_thread (bool full) -{ - jack_nframes_t two_smpte_frames_duration; - jack_nframes_t quarter_frame_duration; - - /* Duration of two smpte frames */ - two_smpte_frames_duration = ((long) _frames_per_smpte_frame) << 1; - - /* Duration of one quarter frame */ - quarter_frame_duration = ((long) _frames_per_smpte_frame) >> 2; - - if (_transport_frame < (outbound_mtc_smpte_frame + (next_quarter_frame_to_send * quarter_frame_duration))) - { - /* There is no work to do. - We throttle this here so that we don't overload - the transport thread with requests. - */ - return; - } - - MIDIRequest* request = new MIDIRequest; - - if (full) { - request->type = MIDIRequest::SendFullMTC; - } else { - request->type = MIDIRequest::SendMTC; - } - - midi_requests.write (&request, 1); - poke_midi_thread (); -} void Session::change_midi_ports () { +/* MIDIRequest* request = new MIDIRequest; request->type = MIDIRequest::PortChange; midi_requests.write (&request, 1); poke_midi_thread (); +*/ } +/** Send MTC Full Frame message (complete SMPTE time) for the start of this cycle. + * Audio thread only, realtime safe. MIDI::Manager::cycle_start must + * have been called with the appropriate nframes parameter this cycle. + */ int -Session::send_full_time_code () - +Session::send_full_time_code(jack_nframes_t nframes) { + /* This function could easily send at a given frame offset, but would + * that be useful? [DR] */ + MIDI::byte msg[10]; - SMPTE_Time smpte; + SMPTE::Time smpte; + + _send_smpte_update = false; if (_mtc_port == 0 || !send_mtc) { return 0; } - + // Get smpte time for this transport frame sample_to_smpte(_transport_frame, smpte, true /* use_offset */, false /* no subframes */); // Check for negative smpte time and prepare for quarter frame transmission + assert(!smpte.negative); // this shouldn't happen if (smpte.negative) { // Negative mtc is not defined, so sync slave to smpte zero. // When _transport_frame gets there we will start transmitting quarter frames @@ -884,7 +856,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; } } @@ -907,42 +879,87 @@ Session::send_full_time_code () msg[7] = smpte.seconds; msg[8] = smpte.frames; - { - LockMonitor lm (midi_lock, __LINE__, __FILE__); - - if (_mtc_port->midimsg (msg, sizeof (msg))) { - error << _("Session: could not send full MIDI time code") << endmsg; - - return -1; - } + // Send message at offset 0, sent time is for the start of this cycle + if (!_mtc_port->midimsg (msg, sizeof (msg), 0)) { + error << _("Session: could not send full MIDI time code") << endmsg; + return -1; } return 0; } +/** Sends all time code messages for this cycle. + * Must be called exactly once per cycle from the audio thread. Realtime safe. + * This function assumes the state of full SMPTE is sane, eg. the slave is + * expecting quarter frame messages and has the right frame of reference (any + * full MTC SMPTE time messages that needed to be sent should have been sent + * earlier in the cycle). + */ int -Session::send_midi_time_code () -{ - if (_mtc_port == 0 || !send_mtc || transmitting_smpte_time.negative || (next_quarter_frame_to_send < 0) ) { - return 0; - } +Session::send_midi_time_code_for_cycle(jack_nframes_t nframes) +{ + //cerr << "----------------------" << endl; - jack_nframes_t two_smpte_frames_duration; - jack_nframes_t quarter_frame_duration; + // FIXME: remove, just for debug print statement + static jack_nframes_t last_time = 0; - /* Duration of two smpte frames */ - two_smpte_frames_duration = ((long) _frames_per_smpte_frame) << 1; + assert (next_quarter_frame_to_send >= 0); + if (_mtc_port == 0 || !send_mtc || transmitting_smpte_time.negative + /*|| (next_quarter_frame_to_send < 0)*/ ) { + printf("Not sending MTC\n"); + return 0; + } + /* Duration of one quarter frame */ - quarter_frame_duration = ((long) _frames_per_smpte_frame) >> 2; + jack_nframes_t quarter_frame_duration = ((long) _frames_per_smpte_frame) >> 2; + + // FIXME: what was transmitting_smpte_time before?? + //smpte_time(_transport_frame, transmitting_smpte_time); + //smpte_to_sample( transmitting_smpte_time, outbound_mtc_smpte_frame, true /* use_offset */, false ); + - while (_transport_frame >= (outbound_mtc_smpte_frame + (next_quarter_frame_to_send * quarter_frame_duration))) { +#if 0 + if (_send_smpte_update) { + // Send full SMPTE time and reset quarter frames + cerr << "[DR] Sending full SMTPE update" << endl; + // 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 + //outbound_mtc_smpte_frame += _worst_output_latency; + send_full_time_code(nframes); + _send_smpte_update = false; + next_quarter_frame_to_send = 0; + } +#endif + + //cerr << "A - " << _transport_frame << " - " << outbound_mtc_smpte_frame + //<< " - " << next_quarter_frame_to_send << " - " << quarter_frame_duration << endl; + + // Note: Unlike the previous implementation of this function (for slow MIDI I/O), + // this now sends all MTC messages for _this_ frame, not messages from the past + // up until the start of the current frame (any messages in the past must have + // been sent last cycle). This assertion enforces this: + //assert(outbound_mtc_smpte_frame >= _transport_frame + // && (outbound_mtc_smpte_frame - _transport_frame) < nframes); + /*if ( ! (outbound_mtc_smpte_frame >= _transport_frame + && (outbound_mtc_smpte_frame - _transport_frame) < nframes)) { */ + if (outbound_mtc_smpte_frame + (next_quarter_frame_to_send * quarter_frame_duration) + < _transport_frame) { + cerr << "[MTC] ERROR: MTC message stamped " << outbound_mtc_smpte_frame + << " in cycle starting " << _transport_frame << endl; + return 0; + } else { + //cerr << "[MTC] OK" << endl; + } + + // Send quarter frames for this cycle + while (_transport_frame + nframes > (outbound_mtc_smpte_frame + + (next_quarter_frame_to_send * quarter_frame_duration))) { - // Send quarter frames up to current time - { - LockMonitor lm (midi_lock, __LINE__, __FILE__); + //cerr << "B: Next frame to send: " << next_quarter_frame_to_send << endl; - switch(next_quarter_frame_to_send) { + switch (next_quarter_frame_to_send) { case 0: mtc_msg[1] = 0x00 | (transmitting_smpte_time.frames & 0xf); break; @@ -967,40 +984,56 @@ Session::send_midi_time_code () case 7: mtc_msg[1] = 0x70 | (((mtc_smpte_bits|transmitting_smpte_time.hours) & 0xf0) >> 4); break; - } - - if (_mtc_port->midimsg (mtc_msg, 2)) { - error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno)) - << endmsg; - - return -1; - } + } - // cout << "smpte = " << transmitting_smpte_time.hours << ":" << transmitting_smpte_time.minutes << ":" << transmitting_smpte_time.seconds << ":" << transmitting_smpte_time.frames << ", qfm = " << next_quarter_frame_to_send << endl; - - // Increment quarter frame counter - next_quarter_frame_to_send++; - - if (next_quarter_frame_to_send >= 8) { - // Wrap quarter frame counter - next_quarter_frame_to_send = 0; - // Increment smpte time twice - 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 - outbound_mtc_smpte_frame += _worst_output_latency; - } + jack_nframes_t msg_time = (outbound_mtc_smpte_frame + + (quarter_frame_duration * next_quarter_frame_to_send)); + assert(msg_time >= _transport_frame); + assert(msg_time < _transport_frame + nframes); + + jack_nframes_t out_stamp = msg_time - _transport_frame; + assert(out_stamp < nframes); + + if (!_mtc_port->midimsg (mtc_msg, 2, out_stamp)) { + error << string_compose(_("Session: cannot send quarter-frame MTC message (%1)"), strerror (errno)) + << endmsg; + return -1; + } + + /*cerr << "smpte = " << transmitting_smpte_time.hours + << ":" << transmitting_smpte_time.minutes + << ":" << transmitting_smpte_time.seconds + << ":" << transmitting_smpte_time.frames + << ", qfm = " << next_quarter_frame_to_send + << ", stamp = " << out_stamp + << ", delta = " << _transport_frame + out_stamp - last_time << endl;*/ + + last_time = _transport_frame + out_stamp; + + // Increment quarter frame counter + next_quarter_frame_to_send++; + + if (next_quarter_frame_to_send >= 8) { + // Wrap quarter frame counter + next_quarter_frame_to_send = 0; + // Increment smpte time twice + 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 ); + outbound_mtc_smpte_frame += 8 * quarter_frame_duration; + // Compensate for audio latency + outbound_mtc_smpte_frame += _worst_output_latency; } } + return 0; } /*********************************************************************** OUTBOUND MMC STUFF **********************************************************************/ - +/* void Session::send_mmc_in_another_thread (MIDI::MachineControl::Command cmd, jack_nframes_t target_frame) { @@ -1018,13 +1051,14 @@ Session::send_mmc_in_another_thread (MIDI::MachineControl::Command cmd, jack_nfr midi_requests.write (&request, 1); poke_midi_thread (); } - +*/ void Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where) { +#if 0 using namespace MIDI; int nbytes = 4; - SMPTE_Time smpte; + SMPTE::Time smpte; if (_mmc_port == 0 || !send_mmc) { return; @@ -1081,6 +1115,8 @@ Session::deliver_mmc (MIDI::MachineControl::Command cmd, jack_nframes_t where) error << string_compose(_("MMC: cannot send command %1%2%3"), &hex, cmd, &dec) << endmsg; } } +#endif + cout << "MMC support broken." << endl; } bool @@ -1117,7 +1153,7 @@ void Session::send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t ch, MIDI::EventTwoBytes data) { // in another thread, really - + /* MIDIRequest* request = new MIDIRequest; request->type = MIDIRequest::SendMessage; @@ -1128,13 +1164,14 @@ Session::send_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel midi_requests.write (&request, 1); poke_midi_thread (); + */ } void Session::deliver_midi (MIDI::Port * port, MIDI::byte* buf, int32_t bufsize) { // in another thread, really - + /* MIDIRequest* request = new MIDIRequest; request->type = MIDIRequest::Deliver; @@ -1144,8 +1181,10 @@ Session::deliver_midi (MIDI::Port * port, MIDI::byte* buf, int32_t bufsize) midi_requests.write (&request, 1); poke_midi_thread (); + */ } +#if 0 void Session::deliver_midi_message (MIDI::Port * port, MIDI::eventType ev, MIDI::channel_t ch, MIDI::EventTwoBytes data) { @@ -1171,11 +1210,14 @@ Session::deliver_data (MIDI::Port * port, MIDI::byte* buf, int32_t size) delete [] buf; } +#endif + /*--------------------------------------------------------------------------- MIDI THREAD ---------------------------------------------------------------------------*/ +#if 0 int Session::start_midi_thread () { @@ -1456,6 +1498,7 @@ Session::midi_thread_work () } } } +#endif bool Session::get_mmc_control () const diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 3280a5f4bb..bbd35a9055 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -38,6 +38,8 @@ #include <ardour/cycles.h> #include <ardour/cycle_timer.h> +#include <midi++/manager.h> + #include "i18n.h" using namespace ARDOUR; @@ -47,6 +49,10 @@ using namespace std; void Session::process (jack_nframes_t nframes) { + cerr << "CYCLE START " << _transport_frame << "-------------------" << endl; + + MIDI::Manager::instance()->cycle_start(nframes); + if (synced_to_jack() && waiting_to_start) { if ( _engine.transport_state() == AudioEngine::TransportRolling) { actually_start_transport (); @@ -60,6 +66,10 @@ Session::process (jack_nframes_t nframes) } (this->*process_function) (nframes); + + MIDI::Manager::instance()->cycle_end(); + + cerr << "CYCLE END " << _transport_frame << "-----------------------" << endl; } void @@ -77,6 +87,8 @@ Session::no_roll (jack_nframes_t nframes, jack_nframes_t offset) int ret = 0; bool declick = get_transport_declick_required(); + cerr << "[DR] no_roll\n"; + if (_click_io) { _click_io->silence (nframes, offset); } @@ -237,16 +249,19 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler) } } + void Session::process_with_events (jack_nframes_t nframes) { - Event* ev; + Event* ev; jack_nframes_t this_nframes; jack_nframes_t end_frame; jack_nframes_t offset; - bool session_needs_butler = false; jack_nframes_t stop_limit; long frames_moved; + bool session_needs_butler = false; + + cerr << "[DR] with events" << endl; if (auditioner) { auditioner->silence (nframes, 0); @@ -267,6 +282,13 @@ Session::process_with_events (jack_nframes_t nframes) process_event (ev); } + /* Events caused a transport change and we need to send MTC + * [DR] FIXME: best place for this? */ + if (_send_smpte_update) { + cerr << "[DR] TIME CHANGE\n" << endl; + send_full_time_code(nframes); + } + if (!process_can_proceed()) { no_roll (nframes, 0); return; @@ -400,17 +422,11 @@ Session::process_with_events (jack_nframes_t nframes) } /* implicit release of route lock */ - - if (session_needs_butler) { + if (session_needs_butler) summon_butler (); - } - if (!_engine.freewheeling() && send_mtc) { - send_midi_time_code_in_another_thread (); - } - - return; -} + send_midi_time_code_for_cycle(nframes); +} void Session::reset_slave_state () @@ -725,6 +741,8 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset) void Session::process_without_events (jack_nframes_t nframes) { + cerr << "[DR] without events" << endl; + bool session_needs_butler = false; jack_nframes_t stop_limit; long frames_moved; @@ -788,16 +806,11 @@ Session::process_without_events (jack_nframes_t nframes) } /* implicit release of route lock */ - if (session_needs_butler) { - summon_butler (); - } - - if (!_engine.freewheeling() && send_mtc) { - send_midi_time_code_in_another_thread (); - } + send_midi_time_code_for_cycle(nframes); - return; -} + if (session_needs_butler) + summon_butler (); +} void Session::process_audition (jack_nframes_t nframes) diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index eaadec0fd3..602ac94314 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -150,7 +150,7 @@ Session::first_stage_init (string fullpath, string snapshot_name) state_was_pending = false; set_next_event (); outbound_mtc_smpte_frame = 0; - next_quarter_frame_to_send = -1; + next_quarter_frame_to_send = 0; current_block_size = 0; _solo_latched = true; _solo_model = InverseMute; @@ -297,9 +297,11 @@ Session::second_stage_init (bool new_session) return -1; } + /* FIXME if (start_midi_thread ()) { return -1; } + */ if (state_tree) { if (set_state (*state_tree->root())) { @@ -336,10 +338,11 @@ Session::second_stage_init (bool new_session) first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running)); } - send_full_time_code (); + // FIXME + //send_full_time_code (); _engine.transport_locate (0); - deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0); - deliver_mmc (MIDI::MachineControl::cmdLocate, 0); + //deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0); + //deliver_mmc (MIDI::MachineControl::cmdLocate, 0); ControlProtocolManager::instance().set_session (*this); diff --git a/libs/ardour/session_time.cc b/libs/ardour/session_time.cc index e3badc5b11..453f5d6d27 100644 --- a/libs/ardour/session_time.cc +++ b/libs/ardour/session_time.cc @@ -63,18 +63,22 @@ Session::set_smpte_type (float fps, bool drop_frames) switch ((int) ceil (fps)) { case 24: mtc_smpte_bits = 0; + SMPTE::Time::default_rate = SMPTE::MTC_24_FPS; break; case 25: mtc_smpte_bits = 0x20; + SMPTE::Time::default_rate = SMPTE::MTC_25_FPS; break; case 30: default: if (drop_frames) { mtc_smpte_bits = 0x40; + SMPTE::Time::default_rate = SMPTE::MTC_30_FPS_DROP; } else { mtc_smpte_bits = 0x60; + SMPTE::Time::default_rate = SMPTE::MTC_30_FPS; } break; }; @@ -102,377 +106,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.... @@ -555,7 +191,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; @@ -649,7 +285,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; @@ -664,7 +300,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; @@ -679,7 +315,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 */ ); } @@ -687,14 +323,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), "%02ld:%02ld:%02ld:%02ld", 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/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 6e756b28b7..313e56ed20 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -375,7 +375,8 @@ Session::non_realtime_stop (bool abort) } } - deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); + //FIXME + //deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); #ifdef LEAVE_TRANSPORT_UNADJUSTED } @@ -383,9 +384,11 @@ Session::non_realtime_stop (bool abort) last_stop_frame = _transport_frame; - send_full_time_code (); + /* FIXME + send_full_time_code(); deliver_mmc (MIDI::MachineControl::cmdStop, 0); deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); + */ if (did_record) { @@ -594,6 +597,15 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b } _transport_frame = target_frame; + smpte_time(_transport_frame, transmitting_smpte_time); + outbound_mtc_smpte_frame = _transport_frame; + next_quarter_frame_to_send = 0; + cerr << "[DR] LOCATE ----------" << endl; + cerr << "\t_transport_frame = " << _transport_frame << endl; + cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4", + transmitting_smpte_time.hours,transmitting_smpte_time.minutes, + transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl; + cerr << "-------------" << endl; if (_transport_speed && (!with_loop || loop_changing)) { /* schedule a declick. we'll be called again when its done */ @@ -680,6 +692,8 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b } loop_changing = false; + + _send_smpte_update = true; } void @@ -875,11 +889,28 @@ Session::actually_start_transport () (*i)->realtime_set_speed ((*i)->speed(), true); } + /* FIXME send_mmc_in_another_thread (MIDI::MachineControl::cmdDeferredPlay, 0); - + */ + + // [DR] Update SMPTE time from transport frame + smpte_time(_transport_frame, transmitting_smpte_time); + outbound_mtc_smpte_frame = _transport_frame; + next_quarter_frame_to_send = 0; + + cerr << "[DR] ACTUALLY START TRANSPORT ----------" << endl; + cerr << "\t_transport_frame = " << _transport_frame << endl; + cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4", + transmitting_smpte_time.hours,transmitting_smpte_time.minutes, + transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl; + cerr << "-------------" << endl; + TransportStateChange (); /* EMIT SIGNAL */ } +/** Do any transport work in the audio thread that needs to be done after the + * transport thread is finished. Audio thread, realtime safe. + */ void Session::post_transport () { @@ -910,6 +941,18 @@ Session::post_transport () set_next_event (); post_transport_work = PostTransportWork (0); + + // [DR] Update SMPTE time from transport frame + smpte_time(_transport_frame, transmitting_smpte_time); + outbound_mtc_smpte_frame = _transport_frame; + next_quarter_frame_to_send = 0; + + cerr << "[DR] POST TRANSPORT ----------" << endl; + cerr << "\t_transport_frame = " << _transport_frame << endl; + cerr << "\ttransmitting_smpte_time = " << string_compose("%1:%2:%3:%4", + transmitting_smpte_time.hours,transmitting_smpte_time.minutes, + transmitting_smpte_time.seconds,transmitting_smpte_time.frames) << endl; + cerr << "-------------" << endl; } void diff --git a/libs/midi++2/SConscript b/libs/midi++2/SConscript index 7c3267a6c7..5230bfc391 100644 --- a/libs/midi++2/SConscript +++ b/libs/midi++2/SConscript @@ -30,18 +30,24 @@ version.cc """) sysdep_sources = Split (""" +jack_midiport.cc alsa_sequencer_midiport.cc coremidi_midiport.cc """) -if env['SYSMIDI'] == 'CoreMIDI': +if env['SYSMIDI'] == 'JACK MIDI': + sysdep_src = [ 'jack_midiport.cc' ] + midi2.Append (CCFLAGS="-DWITH_JACK_MIDI") +elif env['SYSMIDI'] == 'ALSA Sequencer': + sysdep_src = [ 'alsa_sequencer_midiport.cc' ] + midi2.Append (CCFLAGS="-DWITH_ALSA") +elif env['SYSMIDI'] == 'CoreMIDI': sysdep_src = [ 'coremidi_midiport.cc' ] midi2.Append (CCFLAGS="-DWITH_COREMIDI") midi2.Append (LINKFLAGS="-framework CoreMIDI") midi2.Append (LINKFLAGS="-framework CoreFoundation") -else: - sysdep_src = [ 'alsa_sequencer_midiport.cc' ] - midi2.Append (CCFLAGS="-DWITH_ALSA") + + midi2.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") midi2.Append(CCFLAGS="-DLIBSIGC_DISABLE_DEPRECATED") diff --git a/libs/midi++2/alsa_sequencer_midiport.cc b/libs/midi++2/alsa_sequencer_midiport.cc index fca6707efd..1a758b275d 100644 --- a/libs/midi++2/alsa_sequencer_midiport.cc +++ b/libs/midi++2/alsa_sequencer_midiport.cc @@ -79,7 +79,7 @@ int ALSA_SequencerMidiPort::selectable () const return -1; } -int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen) +int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp) { TR_FN (); int R; @@ -118,7 +118,7 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen) return totwritten; } -int ALSA_SequencerMidiPort::read (byte *buf, size_t max) +int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp) { TR_FN(); int err; diff --git a/libs/midi++2/coremidi_midiport.cc b/libs/midi++2/coremidi_midiport.cc index 8d1d927b7b..2cd98239ec 100644 --- a/libs/midi++2/coremidi_midiport.cc +++ b/libs/midi++2/coremidi_midiport.cc @@ -56,7 +56,7 @@ void CoreMidi_MidiPort::Close () if (midi_client) MIDIClientDispose(midi_client); } -int CoreMidi_MidiPort::write (byte *msg, size_t msglen) +int CoreMidi_MidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp) { OSStatus err; MIDIPacketList* pktlist = (MIDIPacketList*)midi_buffer; diff --git a/libs/midi++2/fd_midiport.cc b/libs/midi++2/fd_midiport.cc index 2ced63c259..ef387e7c49 100644 --- a/libs/midi++2/fd_midiport.cc +++ b/libs/midi++2/fd_midiport.cc @@ -151,7 +151,7 @@ FD_MidiPort::do_slow_write (byte *msg, unsigned int msglen) } int -FD_MidiPort::read (byte* buf, size_t max) +FD_MidiPort::read (byte* buf, size_t max, timestamp_t timestamp) { int nread; diff --git a/libs/midi++2/midi++/alsa_rawmidi.h b/libs/midi++2/midi++/alsa_rawmidi.h index 655b673174..f6c17541c2 100644 --- a/libs/midi++2/midi++/alsa_rawmidi.h +++ b/libs/midi++2/midi++/alsa_rawmidi.h @@ -29,6 +29,8 @@ #include <midi++/port.h> #include <midi++/fd_midiport.h> +namespace MIDI { + class ALSA_RawMidiPort : public MIDI::FD_MidiPort { @@ -38,6 +40,7 @@ class ALSA_RawMidiPort : public MIDI::FD_MidiPort virtual ~ALSA_RawMidiPort () {} }; +} // namespace MIDI #endif // __alsa_rawmidi_h__ diff --git a/libs/midi++2/midi++/alsa_sequencer.h b/libs/midi++2/midi++/alsa_sequencer.h index 8ddb2a7dd7..cb02ed961c 100644 --- a/libs/midi++2/midi++/alsa_sequencer.h +++ b/libs/midi++2/midi++/alsa_sequencer.h @@ -44,9 +44,8 @@ class ALSA_SequencerMidiPort : public Port protected: /* Direct I/O */ - - int write (byte *msg, size_t msglen); - int read (byte *buf, size_t max); + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t max, timestamp_t timestamp); private: snd_seq_t *seq; diff --git a/libs/midi++2/midi++/channel.h b/libs/midi++2/midi++/channel.h index f534f7e6da..0d24bf8bbe 100644 --- a/libs/midi++2/midi++/channel.h +++ b/libs/midi++2/midi++/channel.h @@ -32,17 +32,22 @@ namespace MIDI { class Port; +/** Stateful MIDI channel class. + * + * This remembers various useful information about the current 'state' of a + * MIDI channel (eg current pitch bend value). + */ class Channel : public sigc::trackable { public: Channel (byte channel_number, Port &); - Port &midi_port() { return port; } - byte channel() { return channel_number; } - byte program() { return program_number; } - byte bank() { return bank_number; } - byte pressure () { return chanpress; } - byte poly_pressure (byte n) { return polypress[n]; } + Port &midi_port() { return _port; } + byte channel() { return _channel_number; } + byte program() { return _program_number; } + byte bank() { return _bank_number; } + byte pressure () { return _chanpress; } + byte poly_pressure (byte n) { return _polypress[n]; } byte last_note_on () { return _last_note_on; @@ -58,53 +63,52 @@ class Channel : public sigc::trackable { } pitchbend_t pitchbend () { - return pitch_bend; + return _pitch_bend; } controller_value_t controller_value (byte n) { - return controller_val[n%128]; + return _controller_val[n%128]; } controller_value_t *controller_addr (byte n) { - return &controller_val[n%128]; + return &_controller_val[n%128]; } void set_controller (byte n, byte val) { - controller_val[n%128] = val; + _controller_val[n%128] = val; } - bool channel_msg (byte id, byte val1, byte val2); - - bool all_notes_off () { - return channel_msg (MIDI::controller, 123, 0); + bool channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp); + bool all_notes_off (timestamp_t timestamp) { + return channel_msg (MIDI::controller, 123, 0, timestamp); } - bool control (byte id, byte value) { - return channel_msg (MIDI::controller, id, value); + bool control (byte id, byte value, timestamp_t timestamp) { + return channel_msg (MIDI::controller, id, value, timestamp); } - bool note_on (byte note, byte velocity) { - return channel_msg (MIDI::on, note, velocity); + bool note_on (byte note, byte velocity, timestamp_t timestamp) { + return channel_msg (MIDI::on, note, velocity, timestamp); } - bool note_off (byte note, byte velocity) { - return channel_msg (MIDI::off, note, velocity); + bool note_off (byte note, byte velocity, timestamp_t timestamp) { + return channel_msg (MIDI::off, note, velocity, timestamp); } - bool aftertouch (byte value) { - return channel_msg (MIDI::chanpress, value, 0); + bool aftertouch (byte value, timestamp_t timestamp) { + return channel_msg (MIDI::chanpress, value, 0, timestamp); } - bool poly_aftertouch (byte note, byte value) { - return channel_msg (MIDI::polypress, note, value); + bool poly_aftertouch (byte note, byte value, timestamp_t timestamp) { + return channel_msg (MIDI::polypress, note, value, timestamp); } - bool program_change (byte value) { - return channel_msg (MIDI::program, value, 0); + bool program_change (byte value, timestamp_t timestamp) { + return channel_msg (MIDI::program, value, 0, timestamp); } - bool pitchbend (byte msb, byte lsb) { - return channel_msg (MIDI::pitchbend, lsb, msb); + bool pitchbend (byte msb, byte lsb, timestamp_t timestamp) { + return channel_msg (MIDI::pitchbend, lsb, msb, timestamp); } protected: @@ -113,34 +117,33 @@ class Channel : public sigc::trackable { void connect_output_signals (); private: - Port &port; + Port & _port; /* Current channel values */ - - byte channel_number; - byte bank_number; - byte program_number; - byte rpn_msb; - byte rpn_lsb; - byte nrpn_msb; - byte nrpn_lsb; - byte chanpress; - byte polypress[128]; - bool controller_14bit[128]; - controller_value_t controller_val[128]; - byte controller_msb[128]; - byte controller_lsb[128]; - byte _last_note_on; - byte _last_on_velocity; - byte _last_note_off; - byte _last_off_velocity; - pitchbend_t pitch_bend; - bool _omni; - bool _poly; - bool _mono; - size_t _notes_on; - - void reset (bool notes_off = true); + byte _channel_number; + byte _bank_number; + byte _program_number; + byte _rpn_msb; + byte _rpn_lsb; + byte _nrpn_msb; + byte _nrpn_lsb; + byte _chanpress; + byte _polypress[128]; + bool _controller_14bit[128]; + controller_value_t _controller_val[128]; + byte _controller_msb[128]; + byte _controller_lsb[128]; + byte _last_note_on; + byte _last_on_velocity; + byte _last_note_off; + byte _last_off_velocity; + pitchbend_t _pitch_bend; + bool _omni; + bool _poly; + bool _mono; + size_t _notes_on; + + void reset (timestamp_t timestamp, nframes_t nframes, bool notes_off = true); void process_note_off (Parser &, EventTwoBytes *); void process_note_on (Parser &, EventTwoBytes *); diff --git a/libs/midi++2/midi++/controllable.h b/libs/midi++2/midi++/controllable.h index 3fa108bb46..44249cfa4f 100644 --- a/libs/midi++2/midi++/controllable.h +++ b/libs/midi++2/midi++/controllable.h @@ -60,7 +60,7 @@ class Controllable : public sigc::trackable std::string control_description() const { return _control_description; } - void send_midi_feedback (float); + void send_midi_feedback (float val, timestamp_t timestamp); private: bool bistate; diff --git a/libs/midi++2/midi++/coremidi_midiport.h b/libs/midi++2/midi++/coremidi_midiport.h index e02a225784..046b170bce 100644 --- a/libs/midi++2/midi++/coremidi_midiport.h +++ b/libs/midi++2/midi++/coremidi_midiport.h @@ -32,35 +32,35 @@ namespace MIDI { - class CoreMidi_MidiPort:public Port { - public: - CoreMidi_MidiPort(PortRequest & req); - virtual ~ CoreMidi_MidiPort(); +class CoreMidi_MidiPort:public Port { + public: + CoreMidi_MidiPort(PortRequest & req); + virtual ~ CoreMidi_MidiPort(); - virtual int selectable() const { - return -1; - } - protected: - /* Direct I/O */ - int write(byte * msg, size_t msglen); - int read(byte * buf, size_t max) { - return 0; - } /* CoreMidi callback */ - static void read_proc(const MIDIPacketList * pktlist, - void *refCon, void *connRefCon); + virtual int selectable() const { + return -1; + } + protected: + /* Direct I/O */ + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t max, timestamp_t timestamp); - private: - byte midi_buffer[1024]; - MIDIClientRef midi_client; - MIDIEndpointRef midi_destination; - MIDIEndpointRef midi_source; + /* CoreMidi callback */ + static void read_proc(const MIDIPacketList * pktlist, + void *refCon, void *connRefCon); - int Open(PortRequest & req); - void Close(); - static MIDITimeStamp MIDIGetCurrentHostTime(); + private: + byte midi_buffer[1024]; + MIDIClientRef midi_client; + MIDIEndpointRef midi_destination; + MIDIEndpointRef midi_source; - bool firstrecv; - }; + int Open(PortRequest & req); + void Close(); + static MIDITimeStamp MIDIGetCurrentHostTime(); + + bool firstrecv; +}; }; /* namespace MIDI */ diff --git a/libs/midi++2/midi++/factory.h b/libs/midi++2/midi++/factory.h index 1543f68cdc..3fa57b6676 100644 --- a/libs/midi++2/midi++/factory.h +++ b/libs/midi++2/midi++/factory.h @@ -29,7 +29,7 @@ namespace MIDI { class PortFactory { public: - Port *create_port (PortRequest &req); + Port *create_port (PortRequest &req, void* data); static void add_port_request (std::vector<PortRequest *> &reqs, const std::string &reqstr); diff --git a/libs/midi++2/midi++/fd_midiport.h b/libs/midi++2/midi++/fd_midiport.h index 853af9d7b4..e84dc47794 100644 --- a/libs/midi++2/midi++/fd_midiport.h +++ b/libs/midi++2/midi++/fd_midiport.h @@ -53,7 +53,10 @@ class FD_MidiPort : public Port int _fd; virtual void open (PortRequest &req); - virtual int write (byte *msg, size_t msglen) { + /* Direct I/O */ + + virtual int write (byte *msg, size_t msglen, + timestamp_t timestamp) { int nwritten; if ((_mode & O_ACCMODE) == O_RDONLY) { @@ -80,7 +83,8 @@ class FD_MidiPort : public Port return nwritten; } - virtual int read (byte *buf, size_t max); + virtual int read (byte *buf, size_t max, + timestamp_t timestamp); private: static std::string *midi_dirpath; diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index 4889aad8c9..ddf5c0f8cd 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -29,10 +29,27 @@ namespace MIDI { +/** Creates, stores, and manages system MIDI ports. + */ class Manager { public: ~Manager (); + void set_api_data(void* data) { api_data = data; } + + /** Signal the start of an audio cycle. + * This MUST be called before any reading/writing for this cycle. + * Realtime safe. + */ + void cycle_start(nframes_t nframes); + + /** Signal the end of an audio cycle. + * This signifies that the cycle began with @ref cycle_start has ended. + * This MUST be called at the end of each cycle. + * Realtime safe. + */ + void cycle_end(); + Port *add_port (PortRequest &); int remove_port (std::string port); @@ -41,20 +58,6 @@ class Manager { size_t nports () { return ports_by_device.size(); } - /* defaults for clients who are not picky */ - - Port *inputPort; - Port *outputPort; - channel_t inputChannelNumber; - channel_t outputChannelNumber; - - int set_input_port (size_t port); - int set_input_port (std::string); - int set_output_port (size_t port); - int set_output_port (std::string); - int set_input_channel (channel_t); - int set_output_channel (channel_t); - int foreach_port (int (*func)(const Port &, size_t n, void *), void *arg); @@ -80,6 +83,8 @@ class Manager { PortMap ports_by_device; /* canonical */ PortMap ports_by_tag; /* may contain duplicate Ports */ + void *api_data; + void close_ports (); }; diff --git a/libs/midi++2/midi++/nullmidi.h b/libs/midi++2/midi++/nullmidi.h index a94b1015b0..04c7d438bf 100644 --- a/libs/midi++2/midi++/nullmidi.h +++ b/libs/midi++2/midi++/nullmidi.h @@ -46,11 +46,12 @@ class Null_MidiPort : public Port virtual ~Null_MidiPort () {}; - virtual int write (byte *msg, size_t msglen) { + /* Direct I/O */ + int write (byte *msg, size_t msglen, timestamp_t timestamp) { return msglen; } - virtual int read (byte *buf, size_t max) { + int read (byte *buf, size_t max, timestamp_t timestamp) { return 0; } diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 442cc4e5ed..919afb3755 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -37,6 +37,7 @@ class Port : public sigc::trackable { public: enum Type { Unknown, + JACK_Midi, ALSA_RawMidi, ALSA_Sequencer, CoreMidi_MidiPort, @@ -44,42 +45,64 @@ class Port : public sigc::trackable { FIFO, }; - Port (PortRequest &); virtual ~Port (); - /* Direct I/O */ + // FIXME: make Manager a friend of port so these can be hidden? + + /* Only for use by MidiManager. Don't ever call this. */ + virtual void cycle_start(nframes_t nframes); - /** \return number of bytes successfully written */ - virtual int write (byte *msg, size_t msglen) = 0; + /* Only for use by MidiManager. Don't ever call this. */ + virtual void cycle_end(); - /** \return number of bytes successfully written to \a buf */ - virtual int read (byte *buf, size_t max) = 0; + /* Direct I/O */ + + /** Read a message from port. + * @param buf Raw MIDI message to send + * @param max Max size to write to @a buf + * @param timestamp Time stamp in frames of this message (relative to cycle start) + * @return number of bytes successfully written to \a buf + */ + virtual int read(byte *buf, size_t max, timestamp_t timestamp) = 0; + + /** Write a message to port. + * @param msg Raw MIDI message to send + * @param msglen Size of @a msg + * @param timestamp Time stamp in frames of this message (relative to cycle start) + * @return number of bytes successfully written + */ + virtual int write(byte *msg, size_t msglen, timestamp_t timestamp) = 0; + + /** Write a message to port. + * @return true on success. + * FIXME: describe semantics here + */ + bool midimsg (byte *msg, size_t len, timestamp_t timestamp) { + return !(write (msg, len, timestamp) == (int) len); + } - /** Slow down I/O to a loop of single byte emissions - interspersed with a busy loop of 10000 * this value. + bool clock (timestamp_t timestamp); - This may be ignored by a particular instance of this virtual - class. See FD_MidiPort for an example of where it used. */ + /** Slow down I/O to a loop of single byte emissions + * interspersed with a busy loop of 10000 * this value. + * + * This may be ignored by a particular instance of this virtual + * class. See FD_MidiPort for an example of where it used. */ void set_slowdown (size_t n) { slowdown = n; } /* select(2)/poll(2)-based I/O */ + /** Get the file descriptor for port. + * @return File descriptor, or -1 if not selectable. */ virtual int selectable() const = 0; - void selector_read_callback (Select::Selectable *, Select::Condition); - - static void xforms_read_callback (int cond, int fd, void *ptr); - static void gtk_read_callback (void *ptr, int fd, int cond); - - static void write_callback (byte *msg, unsigned int len, void *); - Channel *channel (channel_t chn) { return _channel[chn&0x7F]; } - Parser *input() { return input_parser; } - Parser *output() { return output_parser; } + Parser *input() { return input_parser; } + Parser *output() { return output_parser; } void iostat (int *written, int *read, const size_t **in_counts, @@ -99,47 +122,31 @@ class Port : public sigc::trackable { } } - /** Write a message. - * \return true on success. */ - bool midimsg (byte *msg, size_t len) { - return !(write (msg, len) == (int) len); - } - - /** Write a 3-byte message. - * \return true on success. */ - bool three_byte_msg (byte a, byte b, byte c) { - byte msg[3]; - - msg[0] = a; - msg[1] = b; - msg[2] = c; - - return !(write (msg, 3) == 3); - } - bool clock (); const char *device () const { return _devname.c_str(); } - const char *name () const { return _tagname.c_str(); } - Type type () const { return _type; } - int mode () const { return _mode; } - bool ok () const { return _ok; } - size_t number () const { return _number; } + const char *name () const { return _tagname.c_str(); } + Type type () const { return _type; } + int mode () const { return _mode; } + bool ok () const { return _ok; } + size_t number () const { return _number; } protected: - bool _ok; - Type _type; - std::string _devname; - std::string _tagname; - int _mode; - size_t _number; - Channel *_channel[16]; + bool _ok; + bool _currently_in_cycle; + nframes_t _nframes_this_cycle; + Type _type; + std::string _devname; + std::string _tagname; + int _mode; + size_t _number; + Channel *_channel[16]; sigc::connection thru_connection; - unsigned int bytes_written; - unsigned int bytes_read; - Parser *input_parser; - Parser *output_parser; - size_t slowdown; + unsigned int bytes_written; + unsigned int bytes_read; + Parser *input_parser; + Parser *output_parser; + size_t slowdown; private: static size_t nports; diff --git a/libs/midi++2/midi++/types.h b/libs/midi++2/midi++/types.h index b9d9bf33e7..dc70381d5b 100644 --- a/libs/midi++2/midi++/types.h +++ b/libs/midi++2/midi++/types.h @@ -4,9 +4,11 @@ namespace MIDI { typedef char channel_t; - typedef float controller_value_t; + typedef float controller_value_t; typedef unsigned char byte; typedef unsigned short pitchbend_t; + typedef unsigned int timestamp_t; + typedef unsigned int nframes_t; enum eventType { none = 0x0, diff --git a/libs/midi++2/midichannel.cc b/libs/midi++2/midichannel.cc index 42949591fe..fe4f4afeb2 100644 --- a/libs/midi++2/midichannel.cc +++ b/libs/midi++2/midichannel.cc @@ -25,61 +25,61 @@ using namespace sigc; using namespace MIDI; -Channel::Channel (byte channelnum, Port &p) : port (p) +Channel::Channel (byte channelnum, Port &p) : _port (p) { - channel_number = channelnum; + _channel_number = channelnum; - reset (false); + reset (0, 1, false); } void Channel::connect_input_signals () { - port.input()->channel_pressure[channel_number].connect + _port.input()->channel_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_chanpress)); - port.input()->channel_note_on[channel_number].connect + _port.input()->channel_note_on[_channel_number].connect (mem_fun (*this, &Channel::process_note_on)); - port.input()->channel_note_off[channel_number].connect + _port.input()->channel_note_off[_channel_number].connect (mem_fun (*this, &Channel::process_note_off)); - port.input()->channel_poly_pressure[channel_number].connect + _port.input()->channel_poly_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_polypress)); - port.input()->channel_program_change[channel_number].connect + _port.input()->channel_program_change[_channel_number].connect (mem_fun (*this, &Channel::process_program_change)); - port.input()->channel_controller[channel_number].connect + _port.input()->channel_controller[_channel_number].connect (mem_fun (*this, &Channel::process_controller)); - port.input()->channel_pitchbend[channel_number].connect + _port.input()->channel_pitchbend[_channel_number].connect (mem_fun (*this, &Channel::process_pitchbend)); - port.input()->reset.connect (mem_fun (*this, &Channel::process_reset)); + _port.input()->reset.connect (mem_fun (*this, &Channel::process_reset)); } void Channel::connect_output_signals () { - port.output()->channel_pressure[channel_number].connect + _port.output()->channel_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_chanpress)); - port.output()->channel_note_on[channel_number].connect + _port.output()->channel_note_on[_channel_number].connect (mem_fun (*this, &Channel::process_note_on)); - port.output()->channel_note_off[channel_number].connect + _port.output()->channel_note_off[_channel_number].connect (mem_fun (*this, &Channel::process_note_off)); - port.output()->channel_poly_pressure[channel_number].connect + _port.output()->channel_poly_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_polypress)); - port.output()->channel_program_change[channel_number].connect + _port.output()->channel_program_change[_channel_number].connect (mem_fun (*this, &Channel::process_program_change)); - port.output()->channel_controller[channel_number].connect + _port.output()->channel_controller[_channel_number].connect (mem_fun (*this, &Channel::process_controller)); - port.output()->channel_pitchbend[channel_number].connect + _port.output()->channel_pitchbend[_channel_number].connect (mem_fun (*this, &Channel::process_pitchbend)); - port.output()->reset.connect (mem_fun (*this, &Channel::process_reset)); + _port.output()->reset.connect (mem_fun (*this, &Channel::process_reset)); } void -Channel::reset (bool notes_off) +Channel::reset (timestamp_t timestamp, nframes_t nframes, bool notes_off) { - program_number = channel_number; - bank_number = 0; - pitch_bend = 0; + _program_number = _channel_number; + _bank_number = 0; + _pitch_bend = 0; _last_note_on = 0; _last_note_off = 0; @@ -87,25 +87,25 @@ Channel::reset (bool notes_off) _last_off_velocity = 0; if (notes_off) { - all_notes_off (); + all_notes_off (timestamp); } - memset (polypress, 0, sizeof (polypress)); - memset (controller_msb, 0, sizeof (controller_msb)); - memset (controller_lsb, 0, sizeof (controller_lsb)); + memset (_polypress, 0, sizeof (_polypress)); + memset (_controller_msb, 0, sizeof (_controller_msb)); + memset (_controller_lsb, 0, sizeof (_controller_lsb)); /* zero all controllers XXX not necessarily the right thing */ - memset (controller_val, 0, sizeof (controller_val)); + memset (_controller_val, 0, sizeof (_controller_val)); for (int n = 0; n < 128; n++) { - controller_14bit[n] = false; + _controller_14bit[n] = false; } - rpn_msb = 0; - rpn_lsb = 0; - nrpn_msb = 0; - nrpn_lsb = 0; + _rpn_msb = 0; + _rpn_lsb = 0; + _nrpn_msb = 0; + _nrpn_lsb = 0; _omni = true; _poly = false; @@ -155,20 +155,20 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) it directly. */ - cv = (unsigned short) controller_val[tb->controller_number]; + cv = (unsigned short) _controller_val[tb->controller_number]; - if (controller_14bit[tb->controller_number]) { + if (_controller_14bit[tb->controller_number]) { cv = ((tb->value << 7) | (cv & 0x7f)); } else { cv = tb->value; } - controller_val[tb->controller_number] = (controller_value_t)cv; + _controller_val[tb->controller_number] = (controller_value_t)cv; } else if ((tb->controller_number >= 32 && tb->controller_number <= 63)) { - cv = (unsigned short) controller_val[tb->controller_number]; + cv = (unsigned short) _controller_val[tb->controller_number]; /* LSB for CC 0-31 arrived. @@ -183,20 +183,20 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) int cn = tb->controller_number - 32; - if (controller_14bit[cn] == false) { - controller_14bit[cn] = true; + if (_controller_14bit[cn] == false) { + _controller_14bit[cn] = true; cv = (cv << 7) | (tb->value & 0x7f); } else { cv = (cv & 0x3f80) | (tb->value & 0x7f); } - controller_val[tb->controller_number] = + _controller_val[tb->controller_number] = (controller_value_t) cv; } else { /* controller can only take 7 bit values */ - controller_val[tb->controller_number] = + _controller_val[tb->controller_number] = (controller_value_t) tb->value; } @@ -204,11 +204,11 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) */ if (tb->controller_number == 0) { - bank_number = (unsigned short) controller_val[0]; - if (port.input()) { - port.input()->bank_change (*port.input(), bank_number); - port.input()->channel_bank_change[channel_number] - (*port.input(), bank_number); + _bank_number = (unsigned short) _controller_val[0]; + if (_port.input()) { + _port.input()->bank_change (*_port.input(), _bank_number); + _port.input()->channel_bank_change[_channel_number] + (*_port.input(), _bank_number); } } @@ -218,47 +218,47 @@ void Channel::process_program_change (Parser &parser, byte val) { - program_number = val; + _program_number = val; } void Channel::process_chanpress (Parser &parser, byte val) { - chanpress = val; + _chanpress = val; } void Channel::process_polypress (Parser &parser, EventTwoBytes *tb) { - polypress[tb->note_number] = tb->value; + _polypress[tb->note_number] = tb->value; } void Channel::process_pitchbend (Parser &parser, pitchbend_t val) { - pitch_bend = val; + _pitch_bend = val; } void Channel::process_reset (Parser &parser) { - reset (); + reset (0, 1); } /** Write a message to a channel. * \return true if success */ bool -Channel::channel_msg (byte id, byte val1, byte val2) +Channel::channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp) { unsigned char msg[3]; int len = 0; - msg[0] = id | (channel_number & 0xf); + msg[0] = id | (_channel_number & 0xf); switch (id) { case off: @@ -302,5 +302,5 @@ Channel::channel_msg (byte id, byte val1, byte val2) break; } - return port.midimsg (msg, len); + return _port.midimsg (msg, len, timestamp); } diff --git a/libs/midi++2/midicontrollable.cc b/libs/midi++2/midicontrollable.cc index f17782f3c4..24bc381255 100644 --- a/libs/midi++2/midicontrollable.cc +++ b/libs/midi++2/midicontrollable.cc @@ -308,7 +308,7 @@ Controllable::get_control_info (channel_t& chn, eventType& ev, byte& additional) void -Controllable::send_midi_feedback (float val) +Controllable::send_midi_feedback (float val, timestamp_t timestamp) { byte msg[3]; @@ -320,6 +320,6 @@ Controllable::send_midi_feedback (float val) msg[1] = control_additional; msg[2] = (byte) (val * 127.0f); - port->write (msg, 3); + port->write (msg, 3, timestamp); } diff --git a/libs/midi++2/midifactory.cc b/libs/midi++2/midifactory.cc index 38baada204..d8119e362e 100644 --- a/libs/midi++2/midifactory.cc +++ b/libs/midi++2/midifactory.cc @@ -17,11 +17,16 @@ $Id$ */ +#include <cassert> #include <midi++/types.h> #include <midi++/factory.h> #include <midi++/nullmidi.h> #include <midi++/fifomidi.h> +#ifdef WITH_JACK_MIDI +#include <midi++/jack.h> +#endif // WITH_JACK_MIDI + #ifdef WITH_ALSA #include <midi++/alsa_sequencer.h> #include <midi++/alsa_rawmidi.h> @@ -35,13 +40,21 @@ using namespace std; using namespace MIDI; +// FIXME: void* data pointer, filthy Port * -PortFactory::create_port (PortRequest &req) +PortFactory::create_port (PortRequest &req, void* data) { Port *port; switch (req.type) { +#ifdef WITH_JACK_MIDI + case Port::JACK_Midi: + assert(data != NULL); + port = new JACK_MidiPort (req, (jack_client_t*)data); + break; +#endif // WITH_JACK_MIDI + #ifdef WITH_ALSA case Port::ALSA_RawMidi: port = new ALSA_RawMidiPort (req); diff --git a/libs/midi++2/midimanager.cc b/libs/midi++2/midimanager.cc index 7b3ed7d336..bcdcddf7a4 100644 --- a/libs/midi++2/midimanager.cc +++ b/libs/midi++2/midimanager.cc @@ -33,12 +33,8 @@ using namespace MIDI; Manager *Manager::theManager = 0; Manager::Manager () - + : api_data(NULL) { - inputPort = 0; - outputPort = 0; - inputChannelNumber = 0; - outputChannelNumber = 0; } Manager::~Manager () @@ -102,8 +98,7 @@ Manager::add_port (PortRequest &req) /* modes must be different or complementary */ } - - port = factory.create_port (req); + port = factory.create_port (req, api_data); if (port == 0) { return 0; @@ -122,18 +117,6 @@ Manager::add_port (PortRequest &req) newpair.second = port; ports_by_device.insert (newpair); - /* first port added becomes the default input - port. - */ - - if (inputPort == 0) { - inputPort = port; - } - - if (outputPort == 0) { - outputPort = port; - } - return port; } @@ -154,92 +137,6 @@ Manager::remove_port (string name) return 0; } -int -Manager::set_input_port (string tag) -{ - PortMap::iterator res; - bool found = false; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if (tag == (*res).first) { - found = true; - break; - } - } - - if (!found) { - return -1; - } - - inputPort = (*res).second; - - return 0; -} - -int -Manager::set_input_port (size_t portnum) - -{ - PortMap::iterator res; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if ((*res).second->number() == portnum) { - inputPort = (*res).second; - return 0; - } - } - - return -1; -} - -int -Manager::set_output_port (string tag) - -{ - PortMap::iterator res; - bool found = false; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if (tag == (*res).first) { - found = true; - break; - } - } - - if (!found) { - return -1; - } - - // XXX send a signal to say we're about to change output ports - - if (outputPort) { - for (channel_t chan = 0; chan < 16; chan++) { - outputPort->channel (chan)->all_notes_off (); - } - } - outputPort = (*res).second; - - // XXX send a signal to say we've changed output ports - - return 0; -} - -int -Manager::set_output_port (size_t portnum) - -{ - PortMap::iterator res; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if ((*res).second->number() == portnum) { - outputPort = (*res).second; - return 0; - } - } - - return -1; -} - Port * Manager::port (string name) { @@ -372,3 +269,20 @@ Manager::parse_port_request (string str, Port::Type type) return 0; } + +void +Manager::cycle_start(nframes_t nframes) +{ + for (PortMap::iterator i = ports_by_device.begin(); + i != ports_by_device.end(); i++) + (*i).second->cycle_start(nframes); +} + +void +Manager::cycle_end() +{ + for (PortMap::iterator i = ports_by_device.begin(); + i != ports_by_device.end(); i++) + (*i).second->cycle_end(); +} + diff --git a/libs/midi++2/midiport.cc b/libs/midi++2/midiport.cc index a7c4ba0940..7f31b909d3 100644 --- a/libs/midi++2/midiport.cc +++ b/libs/midi++2/midiport.cc @@ -32,7 +32,8 @@ using namespace MIDI; size_t Port::nports = 0; Port::Port (PortRequest &req) - + : _currently_in_cycle(false) + , _nframes_this_cycle(0) { _ok = false; /* derived class must set to true if constructor succeeds. @@ -87,48 +88,28 @@ Port::~Port () * \return true on success. */ bool -Port::clock () - +Port::clock (timestamp_t timestamp) { static byte clockmsg = 0xf8; if (_mode != O_RDONLY) { - return midimsg (&clockmsg, 1); + return midimsg (&clockmsg, 1, timestamp); } return false; } void -Port::selector_read_callback (Selectable *s, Select::Condition cond) - -{ - byte buf[64]; - read (buf, sizeof (buf)); -} - -void -Port::xforms_read_callback (int cond, int fd, void *ptr) - -{ - byte buf[64]; - - ((Port *)ptr)->read (buf, sizeof (buf)); -} - -void -Port::gtk_read_callback (void *ptr, int fd, int cond) - +Port::cycle_start (nframes_t nframes) { - byte buf[64]; - - ((Port *)ptr)->read (buf, sizeof (buf)); + _currently_in_cycle = true; + _nframes_this_cycle = nframes; } void -Port::write_callback (byte *msg, unsigned int len, void *ptr) - +Port::cycle_end () { - ((Port *)ptr)->write (msg, len); + _currently_in_cycle = false; + _nframes_this_cycle = 0; } diff --git a/libs/midi++2/port_request.cc b/libs/midi++2/port_request.cc index d081bdb570..d209f02574 100644 --- a/libs/midi++2/port_request.cc +++ b/libs/midi++2/port_request.cc @@ -36,7 +36,7 @@ PortRequest::PortRequest (const string &xdev, devname = strdup (xdev.c_str()); tagname = strdup (xtag.c_str()); - + if (xmode == "output" || xmode == "out" || xmode == "OUTPUT" || @@ -58,7 +58,10 @@ PortRequest::PortRequest (const string &xdev, status = Unknown; } - if (xtype == "ALSA/RAW" || + if (xtype == "JACK" || + xtype == "jack") { + type = Port::JACK_Midi; + } else if (xtype == "ALSA/RAW" || xtype == "alsa/raw") { type = Port::ALSA_RawMidi; } else if (xtype == "ALSA/SEQUENCER" || diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc index 8cf157c26c..27133ba94c 100644 --- a/libs/surfaces/control_protocol/basic_ui.cc +++ b/libs/surfaces/control_protocol/basic_ui.cc @@ -265,17 +265,17 @@ BasicUI::smpte_frames_per_hour () void BasicUI::smpte_time (jack_nframes_t where, SMPTE_t& 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 { - 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 { - 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/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index 95b9d22393..fd669314ab 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -58,7 +58,8 @@ GenericMidiControlProtocol::send_route_feedback (list<Route*>& routes) return; } - _port->write (buf, (int32_t) (end - buf)); + // FIXME + //_port->write (buf, (int32_t) (end - buf)); //cerr << "MIDI feedback: wrote " << (int32_t) (end - buf) << " to midi port\n"; } } |