Committed filthy mess of a working copy solely for moving between machines.

Nothing to see here, move along now...


git-svn-id: svn://localhost/trunk/ardour2midi@575 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2006-06-08 23:46:42 +00:00
parent 0c1b9afc63
commit 74dd5bd706
51 changed files with 829 additions and 1033 deletions

View file

@ -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'])

View file

@ -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

View file

@ -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

View file

@ -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
}
#---------------------------------------------------------------

View file

@ -409,7 +409,7 @@ If you still wish to quit, please use the\n\n\
break;
}
}
Config->save_state();
quit ();
}

View file

@ -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();
}

View file

@ -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;

View file

@ -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 */

View file

@ -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));

View file

@ -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;

View file

@ -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);
}

View file

@ -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 );
}
}

View file

@ -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;
}

View file

@ -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()));

View file

@ -93,6 +93,7 @@ tempo.cc
utils.cc
version.cc
mix.cc
smpte.cc
""")
arch_specific_objects = [ ]

View file

@ -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 */

View file

@ -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_to_sample( SMPTE::Time& smpte, jack_nframes_t& sample, bool use_offset, bool use_subframes ) const;
void sample_to_smpte( jack_nframes_t sample, SMPTE::Time& smpte, bool use_offset, bool use_subframes ) const;
void smpte_time (SMPTE::Time &);
void smpte_time (jack_nframes_t when, SMPTE::Time&);
void smpte_time_subframes (jack_nframes_t when, SMPTE::Time&);
void smpte_duration (jack_nframes_t, SMPTE_Time&) const;
void smpte_duration (jack_nframes_t, SMPTE::Time&) const;
void smpte_duration_string (char *, jack_nframes_t) const;
void set_smpte_offset (jack_nframes_t);
@ -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)
*/
/* 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
bool last_smpte_valid;
jack_nframes_t last_smpte_when;
SMPTE_Time last_smpte;
int send_full_time_code(jack_nframes_t nframes);
int send_midi_time_code_for_cycle(jack_nframes_t nframes);
int send_full_time_code ();
int send_midi_time_code ();
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 ();

View file

@ -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 {

View file

@ -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)
{

View file

@ -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;
}

View file

@ -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];

View file

@ -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 */
}

View file

@ -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:

View file

@ -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) ) {
Session::send_midi_time_code_for_cycle(jack_nframes_t nframes)
{
//cerr << "----------------------" << endl;
// FIXME: remove, just for debug print statement
static jack_nframes_t last_time = 0;
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;
}
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;
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
// Send quarter frames up to current time
{
LockMonitor lm (midi_lock, __LINE__, __FILE__);
//cerr << "A - " << _transport_frame << " - " << outbound_mtc_smpte_frame
//<< " - " << next_quarter_frame_to_send << " - " << quarter_frame_duration << endl;
switch(next_quarter_frame_to_send) {
// 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))) {
//cerr << "B: Next frame to send: " << next_quarter_frame_to_send << endl;
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;
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);
// 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 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

View file

@ -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)

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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")

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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__

View file

@ -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;

View file

@ -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;
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);
void reset (timestamp_t timestamp, nframes_t nframes, bool notes_off = true);
void process_note_off (Parser &, EventTwoBytes *);
void process_note_on (Parser &, EventTwoBytes *);

View file

@ -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;

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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 ();
};

View file

@ -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;
}

View file

@ -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 ();
// 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);
/* Only for use by MidiManager. Don't ever call this. */
virtual void cycle_end();
/* 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;
/** \return number of bytes successfully written */
virtual int write (byte *msg, size_t msglen) = 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);
}
/** \return number of bytes successfully written to \a buf */
virtual int read (byte *buf, size_t max) = 0;
bool clock (timestamp_t timestamp);
/** 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. */
* 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;

View file

@ -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,

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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();
}

View file

@ -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)
Port::cycle_start (nframes_t nframes)
{
byte buf[64];
read (buf, sizeof (buf));
_currently_in_cycle = true;
_nframes_this_cycle = nframes;
}
void
Port::xforms_read_callback (int cond, int fd, void *ptr)
Port::cycle_end ()
{
byte buf[64];
((Port *)ptr)->read (buf, sizeof (buf));
}
void
Port::gtk_read_callback (void *ptr, int fd, int cond)
{
byte buf[64];
((Port *)ptr)->read (buf, sizeof (buf));
}
void
Port::write_callback (byte *msg, unsigned int len, void *ptr)
{
((Port *)ptr)->write (msg, len);
_currently_in_cycle = false;
_nframes_this_cycle = 0;
}

View file

@ -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" ||

View file

@ -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);
}

View file

@ -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";
}
}