X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Faudioengine.cc;h=3aa68478aad978ed930148a0fe0a07ee89fc2da6;hb=204baa31d842d4c2f833d319b6fa55e402a1bfb8;hp=6420b9247df8b5f1e8c36321550e55848da37bb2;hpb=4da9b2caac6855e2abcb46e992c823dbb8ec8a19;p=ardour.git diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 6420b9247d..3aa68478aa 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -25,15 +25,14 @@ #include #include -#include -#include -#include #include "pbd/pthread_utils.h" #include "pbd/stacktrace.h" #include "pbd/unknown_type.h" #include "pbd/epa.h" +#include + #include "midi++/port.h" #include "midi++/mmc.h" #include "midi++/manager.h" @@ -44,9 +43,9 @@ #include "ardour/buffer.h" #include "ardour/buffer_set.h" #include "ardour/cycle_timer.h" -#include "ardour/delivery.h" #include "ardour/event_type_map.h" #include "ardour/internal_return.h" +#include "ardour/internal_send.h" #include "ardour/io.h" #include "ardour/meter.h" #include "ardour/midi_port.h" @@ -85,6 +84,7 @@ AudioEngine::AudioEngine (string client_name, string session_uuid) _frame_rate = 0; _buffer_size = 0; _freewheeling = false; + _pre_freewheel_mmc_enabled = false; _main_thread = 0; port_remove_in_progress = false; @@ -317,13 +317,13 @@ AudioEngine::_xrun_callback (void *arg) void AudioEngine::_session_callback (jack_session_event_t *event, void *arg) { - printf( "helo.... " ); AudioEngine* ae = static_cast (arg); if (ae->connected()) { ae->JackSessionEvent ( event ); /* EMIT SIGNAL */ } } #endif + int AudioEngine::_graph_order_callback (void *arg) { @@ -332,20 +332,10 @@ AudioEngine::_graph_order_callback (void *arg) if (ae->connected() && !ae->port_remove_in_progress) { ae->GraphReordered (); /* EMIT SIGNAL */ } + return 0; } -/** Wrapped which is called by JACK as its process callback. It is just - * here to get us back into C++ land by calling AudioEngine::process_callback() - * @param nframes Number of frames passed by JACK. - * @param arg User argument passed by JACK, which will be the AudioEngine*. - */ -int -AudioEngine::_process_callback (pframes_t nframes, void *arg) -{ - return static_cast (arg)->process_callback (nframes); -} - void* AudioEngine::_process_thread (void *arg) { @@ -355,7 +345,20 @@ AudioEngine::_process_thread (void *arg) void AudioEngine::_freewheel_callback (int onoff, void *arg) { - static_cast(arg)->_freewheeling = onoff; + static_cast(arg)->freewheel_callback (onoff); +} + +void +AudioEngine::freewheel_callback (int onoff) +{ + _freewheeling = onoff; + + if (onoff) { + _pre_freewheel_mmc_enabled = MIDI::Manager::instance()->mmc()->send_enabled (); + MIDI::Manager::instance()->mmc()->enable_send (false); + } else { + MIDI::Manager::instance()->mmc()->enable_send (_pre_freewheel_mmc_enabled); + } } void @@ -388,21 +391,25 @@ AudioEngine::_connect_callback (jack_port_id_t id_a, jack_port_id_t id_b, int co jack_port_t* jack_port_a = jack_port_by_id (_priv_jack, id_a); jack_port_t* jack_port_b = jack_port_by_id (_priv_jack, id_b); - Port* port_a = 0; - Port* port_b = 0; + boost::shared_ptr port_a; + boost::shared_ptr port_b; boost::shared_ptr pr = ae->ports.reader (); Ports::iterator i = pr->begin (); while (i != pr->end() && (port_a == 0 || port_b == 0)) { - if (jack_port_a == (*i)->jack_port()) { - port_a = *i; - } else if (jack_port_b == (*i)->jack_port()) { - port_b = *i; + if (jack_port_a == i->second->jack_port()) { + port_a = i->second; + } else if (jack_port_b == i->second->jack_port()) { + port_b = i->second; } ++i; } - ae->PortConnectedOrDisconnected (port_a, port_b, conn == 0 ? false : true); /* EMIT SIGNAL */ + ae->PortConnectedOrDisconnected ( + port_a, jack_port_name (jack_port_a), + port_b, jack_port_name (jack_port_b), + conn == 0 ? false : true + ); /* EMIT SIGNAL */ } void @@ -417,7 +424,7 @@ AudioEngine::split_cycle (pframes_t offset) boost::shared_ptr p = ports.reader(); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_split (); + i->second->cycle_split (); } } @@ -446,17 +453,18 @@ AudioEngine::process_thread () return 0; } -/** Method called by JACK (via _process_callback) which says that there - * is work to be done. - * @param nframes Number of frames to process. +/** Method called by our ::process_thread when there is work to be done. + * @param nframes Number of frames to process. */ int AudioEngine::process_callback (pframes_t nframes) { GET_PRIVATE_JACK_POINTER_RET(_jack,0); - // CycleTimer ct ("AudioEngine::process"); Glib::Mutex::Lock tm (_process_lock, Glib::TRY_LOCK); + PT_TIMING_REF; + PT_TIMING_CHECK (1); + /// The number of frames that will have been processed when we've finished pframes_t next_processed_frames; @@ -485,17 +493,16 @@ AudioEngine::process_callback (pframes_t nframes) /* tell all relevant objects that we're starting a new cycle */ - Delivery::CycleStart (nframes); + InternalSend::CycleStart (nframes); Port::set_global_port_buffer_offset (0); Port::set_cycle_framecnt (nframes); - InternalReturn::CycleStart (nframes); /* tell all Ports that we're starting a new cycle */ boost::shared_ptr p = ports.reader(); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_start (nframes); + i->second->cycle_start (nframes); } /* test if we are freewheeling and there are freewheel signals connected. @@ -513,7 +520,6 @@ AudioEngine::process_callback (pframes_t nframes) } else { if (_session) { _session->process (nframes); - } } @@ -532,15 +538,14 @@ AudioEngine::process_callback (pframes_t nframes) for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - Port *port = (*i); bool x; - if (port->last_monitor() != (x = port->monitoring_input ())) { - port->set_last_monitor (x); + if (i->second->last_monitor() != (x = i->second->jack_monitoring_input ())) { + i->second->set_last_monitor (x); /* XXX I think this is dangerous, due to a likely mutex in the signal handlers ... */ - port->MonitorInputChanged (x); /* EMIT SIGNAL */ + i->second->MonitorInputChanged (x); /* EMIT SIGNAL */ } } last_monitor_check = next_processed_frames; @@ -552,10 +557,8 @@ AudioEngine::process_callback (pframes_t nframes) for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - Port *port = (*i); - - if (port->sends_output()) { - port->get_buffer(nframes).silence(nframes); + if (i->second->sends_output()) { + i->second->get_buffer(nframes).silence(nframes); } } } @@ -563,10 +566,13 @@ AudioEngine::process_callback (pframes_t nframes) // Finalize ports for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_end (nframes); + i->second->cycle_end (nframes); } _processed_frames = next_processed_frames; + + PT_TIMING_CHECK (2); + return 0; } @@ -651,7 +657,7 @@ AudioEngine::jack_bufsize_callback (pframes_t nframes) boost::shared_ptr p = ports.reader(); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->reset(); + i->second->reset(); } } @@ -716,7 +722,7 @@ AudioEngine::set_session (Session *s) boost::shared_ptr p = ports.reader(); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_start (blocksize); + i->second->cycle_start (blocksize); } _session->process (blocksize); @@ -729,7 +735,7 @@ AudioEngine::set_session (Session *s) _session->process (blocksize); for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - (*i)->cycle_end (blocksize); + i->second->cycle_end (blocksize); } } } @@ -770,29 +776,29 @@ AudioEngine::port_registration_failure (const std::string& portname) if (p) { reason = string_compose (_("a port with the name \"%1\" already exists: check for duplicated track/bus names"), portname); } else { - reason = string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with ports if you need this many tracks."), PROGRAM_NAME); + reason = string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with more ports if you need this many tracks."), PROGRAM_NAME); } throw PortRegistrationFailure (string_compose (_("AudioEngine: cannot register port \"%1\": %2"), portname, reason).c_str()); } -Port* +boost::shared_ptr AudioEngine::register_port (DataType dtype, const string& portname, bool input) { - Port* newport; + boost::shared_ptr newport; try { if (dtype == DataType::AUDIO) { - newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput)); + newport.reset (new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput))); } else if (dtype == DataType::MIDI) { - newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput)); + newport.reset (new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput))); } else { throw PortRegistrationFailure("unable to create port (unknown type)"); } RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); - ps->insert (ps->begin(), newport); + ps->insert (make_pair (make_port_name_relative (portname), newport)); /* writer goes out of scope, forces update */ @@ -809,20 +815,20 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input) } } -Port * +boost::shared_ptr AudioEngine::register_input_port (DataType type, const string& portname) { return register_port (type, portname, true); } -Port * +boost::shared_ptr AudioEngine::register_output_port (DataType type, const string& portname) { return register_port (type, portname, false); } int -AudioEngine::unregister_port (Port& port) +AudioEngine::unregister_port (boost::shared_ptr port) { /* caller must hold process lock */ @@ -836,18 +842,17 @@ AudioEngine::unregister_port (Port& port) { RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); + Ports::iterator x = ps->find (make_port_name_relative (port->name())); - for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) { - if ((*i) == &port) { - delete *i; - ps->erase (i); - break; - } + if (x != ps->end()) { + ps->erase (x); } /* writer goes out of scope, forces update */ } + ports.flush (); + return 0; } @@ -869,8 +874,8 @@ AudioEngine::connect (const string& source, const string& destination) string d = make_port_name_non_relative (destination); - Port* src = get_port_by_name (s); - Port* dst = get_port_by_name (d); + boost::shared_ptr src = get_port_by_name (s); + boost::shared_ptr dst = get_port_by_name (d); if (src) { ret = src->connect (d); @@ -909,8 +914,8 @@ AudioEngine::disconnect (const string& source, const string& destination) string s = make_port_name_non_relative (source); string d = make_port_name_non_relative (destination); - Port* src = get_port_by_name (s); - Port* dst = get_port_by_name (d); + boost::shared_ptr src = get_port_by_name (s); + boost::shared_ptr dst = get_port_by_name (d); if (src) { ret = src->disconnect (d); @@ -924,7 +929,7 @@ AudioEngine::disconnect (const string& source, const string& destination) } int -AudioEngine::disconnect (Port& port) +AudioEngine::disconnect (boost::shared_ptr port) { GET_PRIVATE_JACK_POINTER_RET (_jack,-1); @@ -937,7 +942,7 @@ AudioEngine::disconnect (Port& port) } } - return port.disconnect_all (); + return port->disconnect_all (); } ARDOUR::framecnt_t @@ -970,10 +975,10 @@ AudioEngine::frames_per_cycle () const } /** @param name Full or short name of port - * @return Corresponding Port* or 0. This object remains the property of the AudioEngine - * so must not be deleted. + * @return Corresponding Port or 0. */ -Port* + +boost::shared_ptr AudioEngine::get_port_by_name (const string& portname) { if (!_running) { @@ -981,26 +986,47 @@ AudioEngine::get_port_by_name (const string& portname) fatal << _("get_port_by_name() called before engine was started") << endmsg; /*NOTREACHED*/ } else { - return 0; + boost::shared_ptr (); } } if (!port_is_mine (portname)) { /* not an ardour port */ - return 0; + return boost::shared_ptr (); } - std::string const rel = make_port_name_relative (portname); - boost::shared_ptr pr = ports.reader(); - - for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) { - if (rel == (*i)->name()) { - return *i; + std::string rel = make_port_name_relative (portname); + Ports::iterator x = pr->find (rel); + + if (x != pr->end()) { + /* its possible that the port was renamed by some 3rd party and + we don't know about it. check for this (the check is quick + and cheap), and if so, rename the port (which will alter + the port map as a side effect). + */ + const std::string check = make_port_name_relative (jack_port_name (x->second->jack_port())); + if (check != rel) { + x->second->set_name (check); } + return x->second; } - return 0; + return boost::shared_ptr (); +} + +void +AudioEngine::port_renamed (const std::string& old_relative_name, const std::string& new_relative_name) +{ + RCUWriter writer (ports); + boost::shared_ptr p = writer.get_copy(); + Ports::iterator x = p->find (old_relative_name); + + if (x != p->end()) { + boost::shared_ptr port = x->second; + p->erase (x); + p->insert (make_pair (new_relative_name, port)); + } } const char ** @@ -1243,14 +1269,9 @@ AudioEngine::remove_all_ports () /* process lock MUST be held by caller */ - vector to_be_deleted; - { RCUWriter writer (ports); boost::shared_ptr ps = writer.get_copy (); - for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) { - to_be_deleted.push_back (*i); - } ps->clear (); } @@ -1258,14 +1279,6 @@ AudioEngine::remove_all_ports () ports.flush (); - /* now do the actual deletion, given that "ports" is now empty, thus - preventing anyone else from getting a handle on a Port - */ - - for (vector::iterator p = to_be_deleted.begin(); p != to_be_deleted.end(); ++p) { - delete *p; - } - port_remove_in_progress = false; } @@ -1355,7 +1368,7 @@ AudioEngine::reconnect_to_jack () boost::shared_ptr p = ports.reader (); for (i = p->begin(); i != p->end(); ++i) { - if ((*i)->reestablish ()) { + if (i->second->reestablish ()) { break; } } @@ -1390,7 +1403,7 @@ AudioEngine::reconnect_to_jack () /* re-establish connections */ for (i = p->begin(); i != p->end(); ++i) { - (*i)->reconnect (); + i->second->reconnect (); } MIDI::Manager::instance()->reconnect (); @@ -1510,7 +1523,7 @@ AudioEngine::port_is_physical (const std::string& portname) const } void -AudioEngine::ensure_monitor_input (const std::string& portname, bool yn) const +AudioEngine::request_jack_monitors_input (const std::string& portname, bool yn) const { GET_PRIVATE_JACK_POINTER(_jack); @@ -1531,3 +1544,10 @@ AudioEngine::update_latencies () jack_recompute_total_latencies (_priv_jack); } } + +void +AudioEngine::destroy () +{ + delete _instance; + _instance = 0; +}