2 * Copyright (C) 2014 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2013 Paul Davis
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "dummy_audiobackend.h"
22 #include "pbd/error.h"
25 using namespace ARDOUR;
27 static std::string s_instance_name;
28 DummyAudioBackend::DummyAudioBackend (AudioEngine& e)
31 , _freewheeling (false)
33 , _audio_buffersize (1024)
37 , _systemic_input_latency (0)
38 , _systemic_output_latency (0)
39 , _processed_samples (0)
41 _instance_name = s_instance_name;
44 DummyAudioBackend::~DummyAudioBackend ()
48 /* AUDIOBACKEND API */
51 DummyAudioBackend::name () const
57 DummyAudioBackend::is_realtime () const
62 std::vector<AudioBackend::DeviceStatus>
63 DummyAudioBackend::enumerate_devices () const
65 std::vector<AudioBackend::DeviceStatus> s;
66 s.push_back (DeviceStatus (_("Dummy"), true));
71 DummyAudioBackend::available_sample_rates (const std::string&) const
73 std::vector<float> sr;
74 sr.push_back (44100.0);
75 sr.push_back (48000.0);
80 DummyAudioBackend::available_buffer_sizes (const std::string&) const
82 std::vector<uint32_t> bs;
89 DummyAudioBackend::available_input_channel_count (const std::string&) const
95 DummyAudioBackend::available_output_channel_count (const std::string&) const
101 DummyAudioBackend::can_change_sample_rate_when_running () const
107 DummyAudioBackend::can_change_buffer_size_when_running () const
113 DummyAudioBackend::set_device_name (const std::string&)
119 DummyAudioBackend::set_sample_rate (float sr)
121 if (sr <= 0) { return -1; }
123 engine.sample_rate_change (sr);
128 DummyAudioBackend::set_buffer_size (uint32_t bs)
131 _audio_buffersize = bs;
132 engine.buffer_size_change (bs);
137 DummyAudioBackend::set_interleaved (bool yn)
139 if (!yn) { return 0; }
144 DummyAudioBackend::set_input_channels (uint32_t)
150 DummyAudioBackend::set_output_channels (uint32_t)
156 DummyAudioBackend::set_systemic_input_latency (uint32_t)
162 DummyAudioBackend::set_systemic_output_latency (uint32_t)
167 /* Retrieving parameters */
169 DummyAudioBackend::device_name () const
171 return _("Dummy Device");
175 DummyAudioBackend::sample_rate () const
181 DummyAudioBackend::buffer_size () const
183 return _audio_buffersize;
187 DummyAudioBackend::interleaved () const
193 DummyAudioBackend::input_channels () const
199 DummyAudioBackend::output_channels () const
205 DummyAudioBackend::systemic_input_latency () const
211 DummyAudioBackend::systemic_output_latency () const
217 std::vector<std::string>
218 DummyAudioBackend::enumerate_midi_options () const
220 std::vector<std::string> m;
221 m.push_back (_("None"));
226 DummyAudioBackend::set_midi_option (const std::string&)
232 DummyAudioBackend::midi_option () const
239 static void * pthread_process (void *arg)
241 DummyAudioBackend *d = static_cast<DummyAudioBackend *>(arg);
242 d->main_process_thread ();
248 DummyAudioBackend::_start (bool /*for_latency_measurement*/)
251 PBD::error << _("DummyAudioBackend: already active.") << endmsg;
254 if (pthread_create (&_main_thread, NULL, pthread_process, this)) {
255 PBD::error << _("DummyAudioBackend: cannot start.") << endmsg;
259 while (!_running && --timeout > 0) { usleep (1000); }
261 if (timeout == 0 || !_running) {
262 PBD::error << _("DummyAudioBackend: failed to start process thread.") << endmsg;
266 if (engine.reestablish_ports ()) {
267 PBD::error << _("DummyAudioBackend: Could not re-establish ports.") << endmsg;
272 engine.reconnect_ports ();
277 DummyAudioBackend::stop ()
285 if (pthread_join (_main_thread, &status)) {
286 PBD::error << _("DummyAudioBackend: failed to terminate.") << endmsg;
293 DummyAudioBackend::freewheel (bool onoff)
295 if (onoff != _freewheeling) {
298 _freewheeling = onoff;
299 engine.freewheel_callback (onoff);
304 DummyAudioBackend::dsp_load () const
306 return 100.f * _dsp_load;
310 DummyAudioBackend::raw_buffer_size (DataType t)
317 DummyAudioBackend::sample_time ()
319 return _processed_samples;
323 DummyAudioBackend::sample_time_at_cycle_start ()
325 return _processed_samples;
329 DummyAudioBackend::samples_since_cycle_start ()
336 DummyAudioBackend::dummy_process_thread (void *arg)
338 ThreadData* td = reinterpret_cast<ThreadData*> (arg);
339 boost::function<void ()> f = td->f;
346 DummyAudioBackend::create_process_thread (boost::function<void()> func)
350 size_t stacksize = 100000;
352 pthread_attr_init (&attr);
353 pthread_attr_setstacksize (&attr, stacksize);
354 ThreadData* td = new ThreadData (this, func, stacksize);
356 if (pthread_create (&thread_id, &attr, dummy_process_thread, td)) {
357 PBD::error << _("AudioEngine: cannot create process thread.") << endmsg;
361 _threads.push_back (thread_id);
366 DummyAudioBackend::join_process_threads ()
370 for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
373 if (pthread_join (*i, &status)) {
374 PBD::error << _("AudioEngine: cannot terminate process thread.") << endmsg;
383 DummyAudioBackend::in_process_thread ()
385 for (std::vector<pthread_t>::const_iterator i = _threads.begin (); i != _threads.end (); ++i)
387 #ifdef COMPILER_MINGW
388 if (*i == GetCurrentThread ()) {
392 if (pthread_equal (*i, pthread_self ()) != 0) {
401 DummyAudioBackend::process_thread_count ()
403 return _threads.size ();
407 DummyAudioBackend::update_latencies ()
414 DummyAudioBackend::private_handle () const
420 DummyAudioBackend::my_name () const
422 return _instance_name;
426 DummyAudioBackend::available () const
432 DummyAudioBackend::port_name_size () const
438 DummyAudioBackend::set_port_name (PortEngine::PortHandle, const std::string&)
444 DummyAudioBackend::get_port_name (PortEngine::PortHandle) const
449 PortEngine::PortHandle
450 DummyAudioBackend::get_port_by_name (const std::string&) const
452 PortEngine::PortHandle port_handle = 0;
457 DummyAudioBackend::get_ports (
458 const std::string& port_name_pattern,
459 DataType type, PortFlags flags,
460 std::vector<std::string>&) const
466 DummyAudioBackend::port_data_type (PortEngine::PortHandle) const
468 return DataType::AUDIO;
471 PortEngine::PortHandle
472 DummyAudioBackend::register_port (
477 PortEngine::PortHandle port_handle = 0;
482 DummyAudioBackend::unregister_port (PortEngine::PortHandle)
487 DummyAudioBackend::connect (const std::string& src, const std::string& dst)
493 DummyAudioBackend::disconnect (const std::string& src, const std::string& dst)
499 DummyAudioBackend::connect (PortEngine::PortHandle, const std::string&)
505 DummyAudioBackend::disconnect (PortEngine::PortHandle, const std::string&)
511 DummyAudioBackend::disconnect_all (PortEngine::PortHandle)
517 DummyAudioBackend::connected (PortEngine::PortHandle, bool process_callback_safe)
523 DummyAudioBackend::connected_to (PortEngine::PortHandle, const std::string&, bool process_callback_safe)
529 DummyAudioBackend::physically_connected (PortEngine::PortHandle, bool process_callback_safe)
535 DummyAudioBackend::get_connections (PortEngine::PortHandle, std::vector<std::string>&, bool process_callback_safe)
542 DummyAudioBackend::midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index)
548 DummyAudioBackend::midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size)
554 DummyAudioBackend::get_midi_event_count (void* port_buffer)
560 DummyAudioBackend::midi_clear (void* port_buffer)
567 DummyAudioBackend::can_monitor_input () const
573 DummyAudioBackend::request_input_monitoring (PortEngine::PortHandle, bool)
579 DummyAudioBackend::ensure_input_monitoring (PortEngine::PortHandle, bool)
585 DummyAudioBackend::monitoring_input (PortEngine::PortHandle)
590 /* Latency management */
593 DummyAudioBackend::set_latency_range (PortEngine::PortHandle, bool for_playback, LatencyRange)
598 DummyAudioBackend::get_latency_range (PortEngine::PortHandle, bool for_playback)
606 /* Discovering physical ports */
609 DummyAudioBackend::port_is_physical (PortEngine::PortHandle) const
615 DummyAudioBackend::get_physical_outputs (DataType type, std::vector<std::string>&)
620 DummyAudioBackend::get_physical_inputs (DataType type, std::vector<std::string>&)
625 DummyAudioBackend::n_physical_outputs () const
628 cc.set (DataType::AUDIO, 0);
629 cc.set (DataType::MIDI, 0);
634 DummyAudioBackend::n_physical_inputs () const
637 cc.set (DataType::AUDIO, 0);
638 cc.set (DataType::MIDI, 0);
642 /* Getting access to the data buffer for a port */
645 DummyAudioBackend::get_buffer (PortEngine::PortHandle, pframes_t)
651 DummyAudioBackend::main_process_thread ()
653 AudioEngine::thread_init_callback (this);
655 _processed_samples = 0;
657 struct timeval clock1, clock2;
658 ::gettimeofday (&clock1, NULL);
660 if (engine.process_callback (_audio_buffersize)) {
663 _processed_samples += _audio_buffersize;
664 if (!_freewheeling) {
665 ::gettimeofday (&clock2, NULL);
666 const int elapsed_time = (clock2.tv_sec - clock1.tv_sec) * 1000000 + (clock2.tv_usec - clock1.tv_usec);
667 const int nomial_time = 1000000 * _audio_buffersize / _samplerate;
668 _dsp_load = elapsed_time / (float) nomial_time;
669 if (elapsed_time < nomial_time) {
670 ::usleep (nomial_time - elapsed_time);
672 ::usleep (100); // don't hog cpu
676 ::usleep (100); // don't hog cpu
678 ::gettimeofday (&clock1, NULL);
684 /******************************************************************************/
686 static boost::shared_ptr<DummyAudioBackend> _instance;
688 static boost::shared_ptr<AudioBackend>
689 backend_factory (AudioEngine& e)
692 _instance.reset (new DummyAudioBackend (e));
698 instantiate (const std::string& arg1, const std::string& /* arg2 */)
700 s_instance_name = arg1;
712 already_configured ()
717 static ARDOUR::AudioBackendInfo _descriptor = {
725 extern "C" ARDOURBACKEND_API ARDOUR::AudioBackendInfo* descriptor ()