mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 23:05:04 +01:00
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:
parent
0c1b9afc63
commit
74dd5bd706
51 changed files with 829 additions and 1033 deletions
19
SConstruct
19
SConstruct
|
|
@ -11,6 +11,8 @@ import platform
|
|||
from sets import Set
|
||||
import SCons.Node.FS
|
||||
|
||||
#import pickle
|
||||
|
||||
SConsignFile()
|
||||
EnsureSConsVersion(0, 96)
|
||||
|
||||
|
|
@ -459,7 +461,12 @@ libraries['dmalloc'] = conf.Finish ()
|
|||
|
||||
conf = Configure(env)
|
||||
|
||||
if conf.CheckCHeader('alsa/asoundlib.h'):
|
||||
if conf.CheckCHeader('jack/midiport.h'):
|
||||
libraries['sysmidi'] = LibraryInfo (LIBS='jack')
|
||||
env['SYSMIDI'] = 'JACK MIDI'
|
||||
subst_dict['%MIDITAG%'] = "control"
|
||||
subst_dict['%MIDITYPE%'] = "jack"
|
||||
elif conf.CheckCHeader('alsa/asoundlib.h'):
|
||||
libraries['sysmidi'] = LibraryInfo (LIBS='asound')
|
||||
env['SYSMIDI'] = 'ALSA Sequencer'
|
||||
subst_dict['%MIDITAG%'] = "seq"
|
||||
|
|
@ -587,6 +594,12 @@ Help(opts.GenerateHelpText(env))
|
|||
if os.environ.has_key('PATH'):
|
||||
env.Append(PATH = os.environ['PATH'])
|
||||
|
||||
if os.environ.has_key('TERM'):
|
||||
env.Append(PATH = os.environ['TERM'])
|
||||
|
||||
if os.environ.has_key('HOME'):
|
||||
env.Append(HOME = os.environ['HOME'])
|
||||
|
||||
if os.environ.has_key('PKG_CONFIG_PATH'):
|
||||
env.Append(PKG_CONFIG_PATH = os.environ['PKG_CONFIG_PATH'])
|
||||
|
||||
|
|
@ -859,7 +872,9 @@ for subdir in coredirs:
|
|||
for sublistdir in [ subdirs, gtk_subdirs, surface_subdirs ]:
|
||||
for subdir in sublistdir:
|
||||
SConscript (subdir + '/SConscript')
|
||||
|
||||
|
||||
#pickle.dump(env, open('.scons_env', 'w'), pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
# cleanup
|
||||
env.Clean ('scrub', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log'])
|
||||
|
||||
|
|
|
|||
18
ardour.dox
18
ardour.dox
|
|
@ -202,7 +202,7 @@ OPTIMIZE_OUTPUT_JAVA = NO
|
|||
# func(std::string) {}). This also make the inheritance and collaboration
|
||||
# diagrams that involve STL classes more complete and accurate.
|
||||
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
|
||||
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
|
||||
# tag is set to YES, then doxygen will reuse the documentation of the first
|
||||
|
|
@ -233,12 +233,12 @@ EXTRACT_ALL = YES
|
|||
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PRIVATE = YES
|
||||
|
||||
# If the EXTRACT_STATIC tag is set to YES all static members of a file
|
||||
# will be included in the documentation.
|
||||
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_STATIC = YES
|
||||
|
||||
# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
|
||||
# defined locally in source files will be included in the documentation.
|
||||
|
|
@ -295,7 +295,7 @@ INTERNAL_DOCS = NO
|
|||
# in case and if your file system supports case sensitive file names. Windows
|
||||
# and Mac users are advised to set this option to NO.
|
||||
|
||||
CASE_SENSE_NAMES = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
|
||||
# will show members with their full class and namespace scopes in the
|
||||
|
|
@ -342,7 +342,7 @@ SORT_BY_SCOPE_NAME = NO
|
|||
# disable (NO) the todo list. This list is created by putting \todo
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_TODOLIST = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
|
||||
# The GENERATE_TESTLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the test list. This list is created by putting \test
|
||||
|
|
@ -354,13 +354,13 @@ GENERATE_TESTLIST = NO
|
|||
# disable (NO) the bug list. This list is created by putting \bug
|
||||
# commands in the documentation.
|
||||
|
||||
GENERATE_BUGLIST = NO
|
||||
GENERATE_BUGLIST = YES
|
||||
|
||||
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
|
||||
# disable (NO) the deprecated list. This list is created by putting
|
||||
# \deprecated commands in the documentation.
|
||||
|
||||
GENERATE_DEPRECATEDLIST= NO
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
|
||||
# The ENABLED_SECTIONS tag can be used to enable conditional
|
||||
# documentation sections, marked by \if sectionname ... \endif.
|
||||
|
|
@ -459,7 +459,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = libs/pbd3 libs/midi++2 libs/ardour libs/gtkmm2ext gtk2_ardour
|
||||
INPUT = libs/pbd3 libs/midi++2 libs/ardour #libs/gtkmm2ext gtk2_ardour
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
|
@ -1082,7 +1082,7 @@ CLASS_DIAGRAMS = YES
|
|||
# inheritance and usage relations if the target is undocumented
|
||||
# or is not a class.
|
||||
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HIDE_UNDOC_RELATIONS = NO
|
||||
|
||||
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
|
||||
# available from the path. This tool is part of Graphviz, a graph visualization
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
#---------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -409,7 +409,7 @@ If you still wish to quit, please use the\n\n\
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Config->save_state();
|
||||
quit ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ tempo.cc
|
|||
utils.cc
|
||||
version.cc
|
||||
mix.cc
|
||||
smpte.cc
|
||||
""")
|
||||
|
||||
arch_specific_objects = [ ]
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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__
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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" ||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue