summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct19
-rw-r--r--ardour.dox18
-rwxr-xr-xgtk2_ardour/ardev_common.sh2
-rw-r--r--gtk2_ardour/ardour2_ui.rc28
-rw-r--r--gtk2_ardour/ardour_ui.cc2
-rw-r--r--gtk2_ardour/ardour_ui_options.cc52
-rw-r--r--gtk2_ardour/audio_clock.cc42
-rw-r--r--gtk2_ardour/editor.h2
-rw-r--r--gtk2_ardour/editor_actions.cc14
-rw-r--r--gtk2_ardour/editor_mouse.cc4
-rw-r--r--gtk2_ardour/editor_ops.cc68
-rw-r--r--gtk2_ardour/editor_rulers.cc21
-rw-r--r--gtk2_ardour/main.cc4
-rw-r--r--gtk2_ardour/mixer_strip.cc10
-rw-r--r--libs/ardour/SConscript1
-rw-r--r--libs/ardour/ardour/configuration_vars.h18
-rw-r--r--libs/ardour/ardour/session.h71
-rw-r--r--libs/ardour/ardour/types.h30
-rw-r--r--libs/ardour/audioengine.cc2
-rw-r--r--libs/ardour/globals.cc16
-rw-r--r--libs/ardour/mtc_slave.cc2
-rw-r--r--libs/ardour/session.cc16
-rw-r--r--libs/ardour/session_events.cc10
-rw-r--r--libs/ardour/session_midi.cc253
-rw-r--r--libs/ardour/session_process.cc53
-rw-r--r--libs/ardour/session_state.cc11
-rw-r--r--libs/ardour/session_time.cc386
-rw-r--r--libs/ardour/session_transport.cc49
-rw-r--r--libs/midi++2/SConscript14
-rw-r--r--libs/midi++2/alsa_sequencer_midiport.cc4
-rw-r--r--libs/midi++2/coremidi_midiport.cc2
-rw-r--r--libs/midi++2/fd_midiport.cc2
-rw-r--r--libs/midi++2/midi++/alsa_rawmidi.h3
-rw-r--r--libs/midi++2/midi++/alsa_sequencer.h5
-rw-r--r--libs/midi++2/midi++/channel.h111
-rw-r--r--libs/midi++2/midi++/controllable.h2
-rw-r--r--libs/midi++2/midi++/coremidi_midiport.h50
-rw-r--r--libs/midi++2/midi++/factory.h2
-rw-r--r--libs/midi++2/midi++/fd_midiport.h8
-rw-r--r--libs/midi++2/midi++/manager.h33
-rw-r--r--libs/midi++2/midi++/nullmidi.h5
-rw-r--r--libs/midi++2/midi++/port.h115
-rw-r--r--libs/midi++2/midi++/types.h4
-rw-r--r--libs/midi++2/midichannel.cc108
-rw-r--r--libs/midi++2/midicontrollable.cc4
-rw-r--r--libs/midi++2/midifactory.cc15
-rw-r--r--libs/midi++2/midimanager.cc124
-rw-r--r--libs/midi++2/midiport.cc39
-rw-r--r--libs/midi++2/port_request.cc7
-rw-r--r--libs/surfaces/control_protocol/basic_ui.cc6
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.cc3
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";
}
}