git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4120 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.7
| @@ -34,6 +34,10 @@ Valerio Pilo | |||
| Jackdmp changes log | |||
| --------------------------- | |||
| 2011-02-09 Stephane Letz <letz@grame.fr> | |||
| * Remove JackPortIsActive flag. | |||
| 2011-02-07 Stephane Letz <letz@grame.fr> | |||
| * Valerio Pilo second CAS for ARMv7 patch. | |||
| @@ -1,21 +1,21 @@ | |||
| /* | |||
| Copyright (C) 2001 Paul Davis | |||
| Copyright (C) 2004-2008 Grame | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef __JackDriver__ | |||
| @@ -30,27 +30,27 @@ | |||
| namespace Jack | |||
| { | |||
| class JackLockedEngine; | |||
| class JackGraphManager; | |||
| struct JackEngineControl; | |||
| /*! | |||
| \brief The base interface for drivers. | |||
| */ | |||
| class SERVER_EXPORT JackDriverInterface | |||
| { | |||
| public: | |||
| JackDriverInterface() | |||
| {} | |||
| virtual ~JackDriverInterface() | |||
| {} | |||
| virtual int Open() = 0; | |||
| virtual int Open (bool capturing, | |||
| bool playing, | |||
| int inchannels, | |||
| @@ -60,7 +60,7 @@ class SERVER_EXPORT JackDriverInterface | |||
| const char* playback_driver_name, | |||
| jack_nframes_t capture_latency, | |||
| jack_nframes_t playback_latency) = 0; | |||
| virtual int Open(jack_nframes_t buffer_size, | |||
| jack_nframes_t samplerate, | |||
| bool capturing, | |||
| @@ -72,30 +72,30 @@ class SERVER_EXPORT JackDriverInterface | |||
| const char* playback_driver_name, | |||
| jack_nframes_t capture_latency, | |||
| jack_nframes_t playback_latency) = 0; | |||
| virtual int Attach() = 0; | |||
| virtual int Detach() = 0; | |||
| virtual int Read() = 0; | |||
| virtual int Write() = 0; | |||
| virtual int Start() = 0; | |||
| virtual int Stop() = 0; | |||
| virtual bool IsFixedBufferSize() = 0; | |||
| virtual int SetBufferSize(jack_nframes_t buffer_size) = 0; | |||
| virtual int SetSampleRate(jack_nframes_t sample_rate) = 0; | |||
| virtual int Process() = 0; | |||
| virtual int ProcessNull() = 0; | |||
| virtual void SetMaster(bool onoff) = 0; | |||
| virtual bool GetMaster() = 0; | |||
| virtual void AddSlave(JackDriverInterface* slave) = 0; | |||
| virtual void RemoveSlave(JackDriverInterface* slave) = 0; | |||
| virtual std::list<JackDriverInterface*> GetSlaves() = 0; | |||
| virtual int ProcessSlaves() = 0; | |||
| virtual bool IsRealTime() const = 0; | |||
| }; | |||
| @@ -109,16 +109,16 @@ class SERVER_EXPORT JackDriverClientInterface : public JackDriverInterface, publ | |||
| /*! | |||
| \brief The base class for drivers. | |||
| */ | |||
| #define CaptureDriverFlags static_cast<JackPortFlags>(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive) | |||
| #define PlaybackDriverFlags static_cast<JackPortFlags>(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive) | |||
| #define MonitorDriverFlags static_cast<JackPortFlags>(JackPortIsOutput | JackPortIsActive) | |||
| #define CaptureDriverFlags static_cast<JackPortFlags>(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal) | |||
| #define PlaybackDriverFlags static_cast<JackPortFlags>(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal) | |||
| #define MonitorDriverFlags static_cast<JackPortFlags>(JackPortIsOutput) | |||
| class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| { | |||
| protected: | |||
| char fCaptureDriverName[JACK_CLIENT_NAME_SIZE + 1]; | |||
| char fPlaybackDriverName[JACK_CLIENT_NAME_SIZE + 1]; | |||
| char fAliasName[JACK_CLIENT_NAME_SIZE + 1]; | |||
| @@ -134,27 +134,27 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| JackClientControl fClientControl; | |||
| std::list<JackDriverInterface*> fSlaveList; | |||
| bool fIsMaster; | |||
| void CycleIncTime(); | |||
| void CycleTakeBeginTime(); | |||
| void CycleTakeEndTime(); | |||
| void SetupDriverSync(int ref, bool freewheel); | |||
| void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver | |||
| void NotifyBufferSize(jack_nframes_t buffer_size); // BufferSize notification sent by the driver | |||
| void NotifySampleRate(jack_nframes_t sample_rate); // SampleRate notification sent by the driver | |||
| void NotifyFailure(int code, const char* reason); // Failure notification sent by the driver | |||
| public: | |||
| JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | |||
| JackDriver(); | |||
| virtual ~JackDriver(); | |||
| void SetMaster(bool onoff); | |||
| bool GetMaster(); | |||
| void AddSlave(JackDriverInterface* slave); | |||
| void RemoveSlave(JackDriverInterface* slave); | |||
| std::list<JackDriverInterface*> GetSlaves() | |||
| @@ -162,9 +162,9 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| return fSlaveList; | |||
| } | |||
| int ProcessSlaves(); | |||
| virtual int Open(); | |||
| virtual int Open (bool capturing, | |||
| bool playing, | |||
| int inchannels, | |||
| @@ -174,7 +174,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| const char* playback_driver_name, | |||
| jack_nframes_t capture_latency, | |||
| jack_nframes_t playback_latency); | |||
| virtual int Open(jack_nframes_t buffer_size, | |||
| jack_nframes_t samplerate, | |||
| bool capturing, | |||
| @@ -187,31 +187,31 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||
| jack_nframes_t capture_latency, | |||
| jack_nframes_t playback_latency); | |||
| virtual int Close(); | |||
| virtual int Process(); | |||
| virtual int ProcessNull(); | |||
| virtual int Attach(); | |||
| virtual int Detach(); | |||
| virtual int Read(); | |||
| virtual int Write(); | |||
| virtual int Start(); | |||
| virtual int Stop(); | |||
| virtual bool IsFixedBufferSize(); | |||
| virtual int SetBufferSize(jack_nframes_t buffer_size); | |||
| virtual int SetSampleRate(jack_nframes_t sample_rate); | |||
| virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | |||
| virtual JackClientControl* GetClientControl() const; | |||
| virtual bool IsRealTime() const; | |||
| virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one | |||
| virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one | |||
| }; | |||
| } // end of namespace | |||
| #endif | |||
| @@ -708,14 +708,6 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time) | |||
| fGraphManager->GetInputPorts(refnum, input_ports); | |||
| fGraphManager->GetOutputPorts(refnum, output_ports); | |||
| // First add port state to JackPortIsActive | |||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | |||
| fGraphManager->ActivatePort(input_ports[i]); | |||
| } | |||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { | |||
| fGraphManager->ActivatePort(output_ports[i]); | |||
| } | |||
| // Notify client | |||
| NotifyActivate(refnum); | |||
| @@ -745,11 +737,9 @@ int JackEngine::ClientDeactivate(int refnum) | |||
| // First disconnect all ports and remove their JackPortIsActive state | |||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | |||
| PortDisconnect(refnum, input_ports[i], ALL_PORTS); | |||
| fGraphManager->DeactivatePort(input_ports[i]); | |||
| } | |||
| for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (output_ports[i] != EMPTY); i++) { | |||
| PortDisconnect(refnum, output_ports[i], ALL_PORTS); | |||
| fGraphManager->DeactivatePort(output_ports[i]); | |||
| } | |||
| // Then issue port registration notification | |||
| @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public License | |||
| along with this program; if not, write to the Free Software | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| @@ -37,7 +37,7 @@ static void AssertBufferSize(jack_nframes_t buffer_size) | |||
| assert(buffer_size <= BUFFER_SIZE_MAX); | |||
| } | |||
| } | |||
| void JackGraphManager::AssertPort(jack_port_id_t port_index) | |||
| { | |||
| if (port_index >= fPortMax) { | |||
| @@ -45,7 +45,7 @@ void JackGraphManager::AssertPort(jack_port_id_t port_index) | |||
| assert(port_index < fPortMax); | |||
| } | |||
| } | |||
| JackGraphManager* JackGraphManager::Allocate(int port_max) | |||
| { | |||
| // Using "Placement" new | |||
| @@ -59,18 +59,18 @@ void JackGraphManager::Destroy(JackGraphManager* manager) | |||
| manager->~JackGraphManager(); | |||
| JackShmMem::operator delete(manager); | |||
| } | |||
| JackGraphManager::JackGraphManager(int port_max) | |||
| JackGraphManager::JackGraphManager(int port_max) | |||
| { | |||
| assert(port_max <= PORT_NUM_MAX); | |||
| for (int i = 0; i < port_max; i++) { | |||
| fPortArray[i].Release(); | |||
| } | |||
| fPortMax = port_max; | |||
| } | |||
| JackPort* JackGraphManager::GetPort(jack_port_id_t port_index) | |||
| { | |||
| AssertPort(port_index); | |||
| @@ -176,14 +176,14 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff | |||
| jack_int_t len = manager->Connections(port_index); | |||
| // No connections : return a zero-filled buffer | |||
| if (len == 0) { | |||
| if (len == 0) { | |||
| port->ClearBuffer(buffer_size); | |||
| return port->GetBuffer(); | |||
| // One connection | |||
| } else if (len == 1) { | |||
| } else if (len == 1) { | |||
| jack_port_id_t src_index = manager->GetPort(port_index, 0); | |||
| // Ports in same client : copy the buffer | |||
| if (GetPort(src_index)->GetRefNum() == port->GetRefNum()) { | |||
| void* buffers[1]; | |||
| @@ -194,10 +194,10 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff | |||
| } else { | |||
| return GetBuffer(src_index, buffer_size); | |||
| } | |||
| // Multiple connections : mix all buffers | |||
| } else { | |||
| } else { | |||
| const jack_int_t* connections = manager->GetConnections(port_index); | |||
| void* buffers[CONNECTION_NUM_FOR_PORT]; | |||
| jack_port_id_t src_index; | |||
| @@ -220,10 +220,10 @@ int JackGraphManager::RequestMonitor(jack_port_id_t port_index, bool onoff) // C | |||
| JackPort* port = GetPort(port_index); | |||
| /** | |||
| jackd.h | |||
| jackd.h | |||
| * If @ref JackPortCanMonitor is set for this @a port, turn input | |||
| * monitoring on or off. Otherwise, do nothing. | |||
| if (!(fFlags & JackPortCanMonitor)) | |||
| return -1; | |||
| */ | |||
| @@ -376,18 +376,6 @@ int JackGraphManager::ReleasePort(int refnum, jack_port_id_t port_index) | |||
| return res; | |||
| } | |||
| void JackGraphManager::ActivatePort(jack_port_id_t port_index) | |||
| { | |||
| JackPort* port = GetPort(port_index); | |||
| port->fFlags = (JackPortFlags)(port->fFlags | JackPortIsActive); | |||
| } | |||
| void JackGraphManager::DeactivatePort(jack_port_id_t port_index) | |||
| { | |||
| JackPort* port = GetPort(port_index); | |||
| port->fFlags = (JackPortFlags)(port->fFlags & ~JackPortIsActive); | |||
| } | |||
| void JackGraphManager::GetInputPorts(int refnum, jack_int_t* res) | |||
| { | |||
| JackConnectionManager* manager = WriteNextStateStart(); | |||
| @@ -430,7 +418,7 @@ void JackGraphManager::RemoveAllPorts(int refnum) | |||
| jack_error("JackGraphManager::RemoveAllPorts failure ref = %ld port_index = %ld", refnum, port_index); | |||
| assert(true); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| WriteNextStateStop(); | |||
| @@ -717,7 +705,7 @@ void JackGraphManager::GetConnectionsAux(JackConnectionManager* manager, const c | |||
| const jack_int_t* connections = manager->GetConnections(port_index); | |||
| jack_int_t index; | |||
| int i; | |||
| // Cleanup connection array | |||
| memset(res, 0, sizeof(char*) * CONNECTION_NUM_FOR_PORT); | |||
| @@ -740,7 +728,7 @@ const char** JackGraphManager::GetConnections(jack_port_id_t port_index) | |||
| { | |||
| const char** res = (const char**)malloc(sizeof(char*) * CONNECTION_NUM_FOR_PORT); | |||
| UInt16 cur_index, next_index; | |||
| if (!res) | |||
| return NULL; | |||
| @@ -763,7 +751,7 @@ void JackGraphManager::GetPortsAux(const char** matching_ports, const char* port | |||
| { | |||
| int match_cnt = 0; | |||
| regex_t port_regex, type_regex; | |||
| if (port_name_pattern && port_name_pattern[0]) { | |||
| regcomp(&port_regex, port_name_pattern, REG_EXTENDED | REG_NOSUB); | |||
| } | |||
| @@ -823,15 +811,15 @@ const char** JackGraphManager::GetPorts(const char* port_name_pattern, const cha | |||
| { | |||
| const char** res = (const char**)malloc(sizeof(char*) * fPortMax); | |||
| UInt16 cur_index, next_index; | |||
| if (!res) | |||
| return NULL; | |||
| do { | |||
| cur_index = GetCurrentIndex(); | |||
| GetPortsAux(res, port_name_pattern, type_name_pattern, flags); | |||
| next_index = GetCurrentIndex(); | |||
| } while (cur_index != next_index); // Until a coherent state has been read | |||
| } while (cur_index != next_index); // Until a coherent state has been read | |||
| if (res[0]) { // at least one port | |||
| return res; | |||
| @@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU Lesser General Public License for more details. | |||
| You should have received a copy of the GNU Lesser General Public License | |||
| along with this program; if not, write to the Free Software | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| */ | |||
| @@ -36,7 +36,7 @@ namespace Jack | |||
| /*! | |||
| \brief Graph manager: contains the connection manager and the port array. | |||
| */ | |||
| class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState<JackConnectionManager> | |||
| { | |||
| @@ -65,8 +65,6 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||
| // Ports management | |||
| jack_port_id_t AllocatePort(int refnum, const char* port_name, const char* port_type, JackPortFlags flags, jack_nframes_t buffer_size); | |||
| int ReleasePort(int refnum, jack_port_id_t port_index); | |||
| void ActivatePort(jack_port_id_t port_index); | |||
| void DeactivatePort(jack_port_id_t port_index); | |||
| void GetInputPorts(int refnum, jack_int_t* res); | |||
| void GetOutputPorts(int refnum, jack_int_t* res); | |||
| void RemoveAllPorts(int refnum); | |||
| @@ -77,7 +75,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||
| int ComputeTotalLatency(jack_port_id_t port_index); | |||
| int ComputeTotalLatencies(); | |||
| int RequestMonitor(jack_port_id_t port_index, bool onoff); | |||
| // Connections management | |||
| int Connect(jack_port_id_t src_index, jack_port_id_t dst_index); | |||
| int Disconnect(jack_port_id_t src_index, jack_port_id_t dst_index); | |||
| @@ -130,7 +128,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||
| void Save(JackConnectionManager* dst); | |||
| void Restore(JackConnectionManager* src); | |||
| static JackGraphManager* Allocate(int port_max); | |||
| static void Destroy(JackGraphManager* manager); | |||
| @@ -214,7 +214,7 @@ typedef void (*JackFreewheelCallback)(int starting, void *arg); | |||
| /** | |||
| * Prototype for the client supplied function that is called | |||
| * whenever jackd is shutdown. Note that after server shutdown, | |||
| * whenever jackd is shutdown. Note that after server shutdown, | |||
| * the client pointer is *not* deallocated by libjack, | |||
| * the application is responsible to properly use jack_client_close() | |||
| * to release client ressources. Warning: jack_client_close() cannot be | |||
| @@ -295,14 +295,7 @@ enum JackPortFlags { | |||
| * their ports. | |||
| */ | |||
| JackPortIsTerminal = 0x10, | |||
| /** | |||
| * JackPortIsActive means the port has been registered and the | |||
| * client is "active", that is jack_activate has been called | |||
| * | |||
| * JackPortIsActive is on between jack_activate and jack_deactivate. | |||
| */ | |||
| JackPortIsActive = 0x20 | |||
| }; | |||
| /** | |||
| @@ -432,12 +425,12 @@ enum JackStatus { | |||
| * Client's protocol version does not match | |||
| */ | |||
| JackVersionError = 0x400, | |||
| /** | |||
| * Backend error | |||
| */ | |||
| JackBackendError = 0x800, | |||
| /** | |||
| * Client zombified failure | |||
| */ | |||
| @@ -476,7 +469,7 @@ typedef enum { | |||
| JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ | |||
| JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ | |||
| JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ | |||
| } jack_position_bits_t; | |||
| /** all valid position bits */ | |||
| @@ -668,13 +661,13 @@ typedef struct { | |||
| /** | |||
| * Prototype for the client supplied function that is called | |||
| * whenever jackd is shutdown. Note that after server shutdown, | |||
| * whenever jackd is shutdown. Note that after server shutdown, | |||
| * the client pointer is *not* deallocated by libjack, | |||
| * the application is responsible to properly use jack_client_close() | |||
| * to release client ressources. Warning: jack_client_close() cannot be | |||
| * safely used inside the shutdown callback and has to be called outside of | |||
| * the callback context. | |||
| * @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits. | |||
| * @param reason a string describing the shutdown reason (backend failure, server crash... etc...) | |||
| * @param arg pointer to a client supplied structure | |||
| @@ -72,7 +72,7 @@ main (int argc, char *argv[]) | |||
| char* aliases[2]; | |||
| char *server_name = NULL; | |||
| jack_port_t *port; | |||
| struct option long_options[] = { | |||
| { "server", 1, 0, 's' }, | |||
| { "aliases", 0, 0, 'A' }, | |||
| @@ -152,7 +152,7 @@ main (int argc, char *argv[]) | |||
| } | |||
| ports = jack_get_ports (client, NULL, NULL, 0); | |||
| if (!ports) | |||
| if (!ports) | |||
| goto error; | |||
| for (i = 0; ports && ports[i]; ++i) { | |||
| @@ -177,14 +177,14 @@ main (int argc, char *argv[]) | |||
| printf (" %s\n", aliases[i]); | |||
| } | |||
| } | |||
| if (show_con) { | |||
| if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) { | |||
| for (j = 0; connections[j]; j++) { | |||
| printf (" %s\n", connections[j]); | |||
| } | |||
| free (connections); | |||
| } | |||
| } | |||
| } | |||
| if (show_port_latency) { | |||
| if (port) { | |||
| @@ -217,12 +217,7 @@ main (int argc, char *argv[]) | |||
| if (flags & JackPortIsTerminal) { | |||
| fputs ("terminal,", stdout); | |||
| } | |||
| if (flags & JackPortIsActive) { | |||
| fputs ("active,", stdout); | |||
| } else { | |||
| fputs ("non-active,", stdout); | |||
| } | |||
| putc ('\n', stdout); | |||
| } | |||
| } | |||
| @@ -234,7 +229,7 @@ main (int argc, char *argv[]) | |||
| } | |||
| } | |||
| } | |||
| error: | |||
| if (ports) | |||
| jack_free (ports); | |||
| @@ -104,7 +104,7 @@ typedef struct input_port_t { | |||
| // jack | |||
| midi_unpack_t unpack; | |||
| // midi | |||
| int overruns; | |||
| } input_port_t; | |||
| @@ -114,7 +114,7 @@ typedef struct output_port_t { | |||
| // jack | |||
| midi_pack_t packer; | |||
| // midi | |||
| event_head_t next_event; | |||
| int todo; | |||
| @@ -425,16 +425,16 @@ static | |||
| inline int midi_port_open_jack(alsa_rawmidi_t *midi, midi_port_t *port, int type, const char *alias) | |||
| { | |||
| char name[128]; | |||
| if (type & JackPortIsOutput) | |||
| snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++midi->midi_in_cnt); | |||
| else | |||
| else | |||
| snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++midi->midi_out_cnt); | |||
| port->jack = jack_port_register(midi->client, name, JACK_DEFAULT_MIDI_TYPE, | |||
| type | JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive, 0); | |||
| if (port->jack) | |||
| type | JackPortIsPhysical | JackPortIsTerminal, 0); | |||
| if (port->jack) | |||
| jack_port_set_alias(port->jack, alias); | |||
| return port->jack == NULL; | |||
| } | |||
| @@ -455,7 +455,7 @@ int midi_port_open(alsa_rawmidi_t *midi, midi_port_t *port) | |||
| out = &port->rawmidi; | |||
| type = JackPortIsInput; | |||
| } | |||
| if ((err = snd_rawmidi_open(in, out, port->dev, SND_RAWMIDI_NONBLOCK))<0) | |||
| return err; | |||
| @@ -749,7 +749,7 @@ void* scan_thread(void *arg) | |||
| return NULL; | |||
| } | |||
| /* | |||
| /* | |||
| * ------------------------------- Input/Output ------------------------------ | |||
| */ | |||
| @@ -836,7 +836,7 @@ void *midi_thread(void *arg) | |||
| npfds = 1; | |||
| if (jack_is_realtime(midi->client)) | |||
| set_threaded_log_function(); | |||
| set_threaded_log_function(); | |||
| //debug_log("midi_thread(%s): enter", str->name); | |||
| @@ -978,7 +978,7 @@ int midi_update_pfds(process_midi_t *proc) | |||
| return 1; | |||
| } | |||
| /* | |||
| /* | |||
| * ------------------------------------ Input ------------------------------ | |||
| */ | |||
| @@ -1083,7 +1083,7 @@ int do_midi_input(process_midi_t *proc) | |||
| return 1; | |||
| } | |||
| /* | |||
| /* | |||
| * ------------------------------------ Output ------------------------------ | |||
| */ | |||
| @@ -1149,7 +1149,7 @@ int do_midi_output(process_midi_t *proc) | |||
| } else | |||
| debug_log("midi_out: at %ld got %d bytes for %ld", (long)proc->cur_time, (int)port->next_event.size, (long)port->next_event.time); | |||
| } | |||
| if (port->todo) | |||
| debug_log("midi_out: todo = %d at %ld", (int)port->todo, (long)proc->cur_time); | |||
| @@ -285,7 +285,7 @@ int alsa_seqmidi_attach(alsa_midi_t *m) | |||
| self->client_id = snd_seq_client_id(self->seq); | |||
| self->queue = snd_seq_alloc_queue(self->seq); | |||
| snd_seq_start_queue(self->seq, self->queue, 0); | |||
| snd_seq_start_queue(self->seq, self->queue, 0); | |||
| stream_attach(self, PORT_INPUT); | |||
| stream_attach(self, PORT_OUTPUT); | |||
| @@ -488,14 +488,14 @@ port_t* port_create(alsa_seqmidi_t *self, int type, snd_seq_addr_t addr, const s | |||
| /* mark anything that looks like a hardware port as physical&terminal */ | |||
| if (snd_seq_port_info_get_type (info) & (SND_SEQ_PORT_TYPE_HARDWARE|SND_SEQ_PORT_TYPE_PORT|SND_SEQ_PORT_TYPE_SPECIFIC)) { | |||
| jack_caps |= (JackPortIsPhysical | JackPortIsTerminal | JackPortIsActive); | |||
| jack_caps |= (JackPortIsPhysical | JackPortIsTerminal); | |||
| } | |||
| if (jack_caps & JackPortIsOutput) | |||
| snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++self->midi_in_cnt); | |||
| else | |||
| else | |||
| snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++self->midi_out_cnt); | |||
| port->jack_port = jack_port_register(self->jack, | |||
| name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0); | |||
| if (!port->jack_port) | |||
| @@ -588,7 +588,7 @@ void update_ports(alsa_seqmidi_t *self) | |||
| snd_seq_port_info_alloca(&info); | |||
| while ((size = jack_ringbuffer_read(self->port_add, (char*)&addr, sizeof(addr)))) { | |||
| int err; | |||
| assert (size == sizeof(addr)); | |||
| @@ -666,7 +666,7 @@ void set_process_info(struct process_info *info, alsa_seqmidi_t *self, int dir, | |||
| info->alsa_time = alsa_time->tv_sec * NSEC_PER_SEC + alsa_time->tv_nsec; | |||
| if (info->period_start + info->nframes < info->cur_frames) { | |||
| int periods_lost = (info->cur_frames - info->period_start) / info->nframes; | |||
| int periods_lost = (info->cur_frames - info->period_start) / info->nframes; | |||
| info->period_start += periods_lost * info->nframes; | |||
| debug_log("xrun detected: %d periods lost\n", periods_lost); | |||
| } | |||
| @@ -805,7 +805,7 @@ void input_event(alsa_seqmidi_t *self, snd_seq_event_t *alsa_event, struct proce | |||
| ev.size = size; | |||
| jack_ringbuffer_write(port->early_events, (char*)&ev, sizeof(ev)); | |||
| jack_ringbuffer_write(port->early_events, (char*)data, size); | |||
| debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes)); | |||
| debug_log("postponed to next frame +%d", (int) (event_frame - info->nframes)); | |||
| return; | |||
| } | |||
| @@ -829,7 +829,7 @@ void alsa_seqmidi_read(alsa_midi_t *m, jack_nframes_t nframes) | |||
| return; | |||
| set_process_info(&info, self, PORT_INPUT, nframes); | |||
| jack_process(self, &info); | |||
| jack_process(self, &info); | |||
| while ((res = snd_seq_event_input(self->seq, &event))>0) { | |||
| if (event->source.client == SND_SEQ_CLIENT_SYSTEM) | |||
| @@ -184,9 +184,9 @@ OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice | |||
| AudioDevicePropertyID inPropertyID, | |||
| void* inClientData) | |||
| { | |||
| switch (inPropertyID) { | |||
| case kAudioDeviceProcessorOverload: { | |||
| jack_error("JackCoreAudioAdapter::DeviceNotificationCallback kAudioDeviceProcessorOverload"); | |||
| break; | |||
| @@ -196,12 +196,12 @@ OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice | |||
| jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration"); | |||
| return kAudioHardwareUnsupportedOperationError; | |||
| } | |||
| case kAudioDevicePropertyNominalSampleRate: { | |||
| jack_error("Cannot handle kAudioDevicePropertyNominalSampleRate"); | |||
| return kAudioHardwareUnsupportedOperationError; | |||
| } | |||
| } | |||
| return noErr; | |||
| } | |||
| @@ -217,7 +217,7 @@ int JackCoreAudioAdapter::AddListeners() | |||
| printError(err); | |||
| return -1; | |||
| } | |||
| err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this); | |||
| if (err != noErr) { | |||
| jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices"); | |||
| @@ -275,17 +275,17 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||
| { | |||
| JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | |||
| AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | |||
| float* inputBuffer[adapter->fCaptureChannels]; | |||
| float* outputBuffer[adapter->fPlaybackChannels]; | |||
| for (int i = 0; i < adapter->fCaptureChannels; i++) { | |||
| inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData; | |||
| } | |||
| for (int i = 0; i < adapter->fPlaybackChannels; i++) { | |||
| outputBuffer[i] = (float*)ioData->mBuffers[i].mData; | |||
| } | |||
| adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames); | |||
| return noErr; | |||
| } | |||
| @@ -302,16 +302,16 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||
| fCaptureUID[0] = 0; | |||
| fPlaybackUID[0] = 0; | |||
| fClockDriftCompensate = false; | |||
| // Default values | |||
| fCaptureChannels = -1; | |||
| fPlaybackChannels = -1; | |||
| SInt32 major; | |||
| SInt32 minor; | |||
| Gestalt(gestaltSystemVersionMajor, &major); | |||
| Gestalt(gestaltSystemVersionMinor, &minor); | |||
| // Starting with 10.6 systems, the HAL notification thread is created internally | |||
| if (major == 10 && minor >= 6) { | |||
| CFRunLoopRef theRunLoop = NULL; | |||
| @@ -321,7 +321,7 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||
| jack_error("JackCoreAudioAdapter::Open kAudioHardwarePropertyRunLoop error"); | |||
| } | |||
| } | |||
| for (node = params; node; node = jack_slist_next(node)) { | |||
| param = (const jack_driver_param_t*) node->data; | |||
| @@ -348,7 +348,7 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||
| fPlaying = true; | |||
| strncpy(fPlaybackUID, param->value.str, 256); | |||
| break; | |||
| case 'd': | |||
| strncpy(fCaptureUID, param->value.str, 256); | |||
| strncpy(fPlaybackUID, param->value.str, 256); | |||
| @@ -365,51 +365,51 @@ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nfra | |||
| case 'p': | |||
| SetAdaptedBufferSize(param->value.ui); | |||
| break; | |||
| case 'l': | |||
| DisplayDeviceNames(); | |||
| break; | |||
| case 'q': | |||
| fQuality = param->value.ui; | |||
| break; | |||
| case 'g': | |||
| fRingbufferCurSize = param->value.ui; | |||
| fAdaptative = false; | |||
| break; | |||
| case 's': | |||
| fClockDriftCompensate = true; | |||
| break; | |||
| } | |||
| } | |||
| /* duplex is the default */ | |||
| if (!fCapturing && !fPlaying) { | |||
| fCapturing = true; | |||
| fPlaying = true; | |||
| } | |||
| if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) | |||
| throw -1; | |||
| if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) | |||
| throw -1; | |||
| if (SetupBufferSize(fAdaptedBufferSize) < 0) | |||
| throw -1; | |||
| if (SetupSampleRate(fAdaptedSampleRate) < 0) | |||
| throw -1; | |||
| if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) | |||
| if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) | |||
| throw -1; | |||
| if (fCapturing && fCaptureChannels > 0) | |||
| if (SetupBuffers(fCaptureChannels) < 0) | |||
| throw -1; | |||
| if (AddListeners() < 0) | |||
| throw -1; | |||
| } | |||
| @@ -488,6 +488,10 @@ OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id) | |||
| if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) | |||
| return res; | |||
| if (inDefault == 0) { | |||
| jack_error("Error : input device is 0, please select a correct one !!"); | |||
| return -1; | |||
| } | |||
| jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | |||
| *id = inDefault; | |||
| return noErr; | |||
| @@ -502,6 +506,10 @@ OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id) | |||
| if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) | |||
| return res; | |||
| if (outDefault == 0) { | |||
| jack_error("Error : output device is 0, please select a correct one !!"); | |||
| return -1; | |||
| } | |||
| jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | |||
| *id = outDefault; | |||
| return noErr; | |||
| @@ -525,10 +533,10 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| // Duplex | |||
| if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { | |||
| // Same device for capture and playback... | |||
| if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { | |||
| if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) { | |||
| jack_log("Will take default in/out"); | |||
| if (GetDefaultDevice(&fDeviceID) != noErr) { | |||
| @@ -540,12 +548,12 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| jack_error("Cannot get device name from device ID"); | |||
| return -1; | |||
| } | |||
| } else { | |||
| // Creates aggregate device | |||
| AudioDeviceID captureID, playbackID; | |||
| if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | |||
| jack_log("Will take default input"); | |||
| if (GetDefaultInputDevice(&captureID) != noErr) { | |||
| @@ -553,7 +561,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { | |||
| jack_log("Will take default output"); | |||
| if (GetDefaultOutputDevice(&playbackID) != noErr) { | |||
| @@ -561,7 +569,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) | |||
| return -1; | |||
| } | |||
| @@ -599,10 +607,10 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| jack_log("JackCoreAudioDriver::Open default driver"); | |||
| if (GetDefaultDevice(&fDeviceID) != noErr) { | |||
| jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); | |||
| // Creates aggregate device | |||
| AudioDeviceID captureID, playbackID; | |||
| if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | |||
| jack_log("Will take default input"); | |||
| if (GetDefaultInputDevice(&captureID) != noErr) { | |||
| @@ -610,7 +618,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { | |||
| jack_log("Will take default output"); | |||
| if (GetDefaultOutputDevice(&playbackID) != noErr) { | |||
| @@ -618,7 +626,7 @@ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) | |||
| return -1; | |||
| } | |||
| @@ -680,7 +688,7 @@ int JackCoreAudioAdapter::SetupChannels(bool capturing, | |||
| jack_log("Setup max out channels = %ld", out_nChannels); | |||
| outchannels = out_nChannels; | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -694,7 +702,7 @@ int JackCoreAudioAdapter::SetupBufferSize(jack_nframes_t buffer_size) | |||
| printError(err); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -708,7 +716,7 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe | |||
| OSStatus err = noErr; | |||
| UInt32 outSize; | |||
| Float64 sampleRate; | |||
| // Get sample rate | |||
| outSize = sizeof(Float64); | |||
| err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); | |||
| @@ -716,12 +724,14 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe | |||
| jack_error("Cannot get current sample rate"); | |||
| printError(err); | |||
| return -1; | |||
| } else { | |||
| jack_log("Current sample rate = %f", sampleRate); | |||
| } | |||
| // If needed, set new sample rate | |||
| if (samplerate != (jack_nframes_t)sampleRate) { | |||
| sampleRate = (Float64)samplerate; | |||
| // To get SR change notification | |||
| err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this); | |||
| if (err != noErr) { | |||
| @@ -735,18 +745,18 @@ int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframe | |||
| printError(err); | |||
| return -1; | |||
| } | |||
| // Waiting for SR change notification | |||
| int count = 0; | |||
| while (!fState && count++ < WAIT_COUNTER) { | |||
| usleep(100000); | |||
| jack_log("Wait count = %d", count); | |||
| } | |||
| // Remove SR change notification | |||
| AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -796,7 +806,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| jack_error("No input and output channels..."); | |||
| return -1; | |||
| } | |||
| // AUHAL | |||
| ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
| Component HALOutput = FindNextComponent(NULL, &cd); | |||
| @@ -823,7 +833,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| enableIO = 0; | |||
| jack_log("Setup AUHAL input off"); | |||
| } | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); | |||
| @@ -838,14 +848,14 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| enableIO = 0; | |||
| jack_log("Setup AUHAL output off"); | |||
| } | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); | |||
| printError(err1); | |||
| goto error; | |||
| } | |||
| size = sizeof(AudioDeviceID); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); | |||
| if (err1 != noErr) { | |||
| @@ -863,7 +873,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| printError(err1); | |||
| goto error; | |||
| } | |||
| // Set buffer size | |||
| if (capturing && inchannels > 0) { | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32)); | |||
| @@ -918,7 +928,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| // Setup stream converters | |||
| if (capturing && inchannels > 0) { | |||
| size = sizeof(AudioStreamBasicDescription); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size); | |||
| if (err1 != noErr) { | |||
| @@ -927,7 +937,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| goto error; | |||
| } | |||
| PrintStreamDesc(&srcFormat); | |||
| jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); | |||
| srcFormat.mSampleRate = samplerate; | |||
| srcFormat.mFormatID = kAudioFormatLinearPCM; | |||
| @@ -938,9 +948,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| srcFormat.mChannelsPerFrame = inchannels; | |||
| srcFormat.mBitsPerChannel = 32; | |||
| PrintStreamDesc(&srcFormat); | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); | |||
| printError(err1); | |||
| @@ -949,7 +959,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| } | |||
| if (playing && outchannels > 0) { | |||
| size = sizeof(AudioStreamBasicDescription); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size); | |||
| if (err1 != noErr) { | |||
| @@ -958,7 +968,7 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| goto error; | |||
| } | |||
| PrintStreamDesc(&dstFormat); | |||
| jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); | |||
| dstFormat.mSampleRate = samplerate; | |||
| dstFormat.mFormatID = kAudioFormatLinearPCM; | |||
| @@ -969,9 +979,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| dstFormat.mChannelsPerFrame = outchannels; | |||
| dstFormat.mBitsPerChannel = 32; | |||
| PrintStreamDesc(&dstFormat); | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); | |||
| printError(err1); | |||
| @@ -1003,13 +1013,13 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||
| } | |||
| return 0; | |||
| error: | |||
| CloseAUHAL(); | |||
| return -1; | |||
| } | |||
| OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() | |||
| OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() | |||
| { | |||
| OSStatus osErr = noErr; | |||
| AudioObjectPropertyAddress pluginAOPA; | |||
| @@ -1017,21 +1027,21 @@ OSStatus JackCoreAudioAdapter::DestroyAggregateDevice() | |||
| pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; | |||
| pluginAOPA.mElement = kAudioObjectPropertyElementMaster; | |||
| UInt32 outDataSize; | |||
| osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| return noErr; | |||
| } | |||
| @@ -1043,15 +1053,15 @@ static CFStringRef GetDeviceName(AudioDeviceID id) | |||
| return (err == noErr) ? UIname : NULL; | |||
| } | |||
| OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| { | |||
| OSStatus err = noErr; | |||
| AudioObjectID sub_device[32]; | |||
| UInt32 outSize = sizeof(sub_device); | |||
| err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| vector<AudioDeviceID> captureDeviceIDArray; | |||
| if (err != noErr) { | |||
| jack_log("Input device does not have subdevices"); | |||
| captureDeviceIDArray.push_back(captureDeviceID); | |||
| @@ -1062,10 +1072,10 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDevice | |||
| captureDeviceIDArray.push_back(sub_device[i]); | |||
| } | |||
| } | |||
| err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| vector<AudioDeviceID> playbackDeviceIDArray; | |||
| if (err != noErr) { | |||
| jack_log("Output device does not have subdevices"); | |||
| playbackDeviceIDArray.push_back(playbackDeviceID); | |||
| @@ -1076,16 +1086,16 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDevice | |||
| playbackDeviceIDArray.push_back(sub_device[i]); | |||
| } | |||
| } | |||
| return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice); | |||
| } | |||
| OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| { | |||
| OSStatus osErr = noErr; | |||
| UInt32 outSize; | |||
| Boolean outWritable; | |||
| // Prepare sub-devices for clock drift compensation | |||
| // Workaround for bug in the HAL : until 10.6.2 | |||
| AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; | |||
| @@ -1094,7 +1104,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| AudioClassID inClass = kAudioSubDeviceClassID; | |||
| void* theQualifierData = &inClass; | |||
| UInt32 subDevicesNum = 0; | |||
| //--------------------------------------------------------------------------- | |||
| // Setup SR of both devices otherwise creating AD may fail... | |||
| //--------------------------------------------------------------------------- | |||
| @@ -1102,18 +1112,18 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| UInt32 clockdomain = 0; | |||
| outSize = sizeof(UInt32); | |||
| bool need_clock_drift_compensation = false; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device"); | |||
| } else { | |||
| // Check clock domain | |||
| osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| if (osErr != 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); | |||
| printError(osErr); | |||
| } else { | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain); | |||
| if (clockdomain != 0 && clockdomain != keptclockdomain) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); | |||
| @@ -1122,18 +1132,18 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| } | |||
| } | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device"); | |||
| } else { | |||
| // Check clock domain | |||
| osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| if (osErr != 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); | |||
| printError(osErr); | |||
| } else { | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain); | |||
| if (clockdomain != 0 && clockdomain != keptclockdomain) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); | |||
| @@ -1142,74 +1152,74 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| } | |||
| } | |||
| } | |||
| // If no valid clock domain was found, then assume we have to compensate... | |||
| if (keptclockdomain == 0) { | |||
| need_clock_drift_compensation = true; | |||
| } | |||
| //--------------------------------------------------------------------------- | |||
| // Start to create a new aggregate by getting the base audio hardware plugin | |||
| //--------------------------------------------------------------------------- | |||
| char device_name[256]; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| GetDeviceNameFromID(captureDeviceID[i], device_name); | |||
| jack_info("Separated input = '%s' ", device_name); | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| GetDeviceNameFromID(playbackDeviceID[i], device_name); | |||
| jack_info("Separated output = '%s' ", device_name); | |||
| } | |||
| osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| AudioValueTranslation pluginAVT; | |||
| CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio"); | |||
| pluginAVT.mInputData = &inBundleRef; | |||
| pluginAVT.mInputDataSize = sizeof(inBundleRef); | |||
| pluginAVT.mOutputData = &fPluginID; | |||
| pluginAVT.mOutputDataSize = sizeof(fPluginID); | |||
| osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| //------------------------------------------------- | |||
| // Create a CFDictionary for our aggregate device | |||
| //------------------------------------------------- | |||
| CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |||
| CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex"); | |||
| CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex"); | |||
| // add the name of the device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef); | |||
| // add our choice of UID for the aggregate device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef); | |||
| // add a "private aggregate key" to the dictionary | |||
| int value = 1; | |||
| CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value); | |||
| SInt32 system; | |||
| Gestalt(gestaltSystemVersion, &system); | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054); | |||
| // Starting with 10.5.4 systems, the AD can be internal... (better) | |||
| if (system < 0x00001054) { | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device...."); | |||
| @@ -1217,16 +1227,16 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device...."); | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef); | |||
| } | |||
| // Prepare sub-devices for clock drift compensation | |||
| CFMutableArrayRef subDevicesArrayClock = NULL; | |||
| /* | |||
| if (fClockDriftCompensate) { | |||
| if (need_clock_drift_compensation) { | |||
| jack_info("Clock drift compensation activated..."); | |||
| subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| CFStringRef UID = GetDeviceName(captureDeviceID[i]); | |||
| if (UID) { | |||
| @@ -1237,7 +1247,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); | |||
| } | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| CFStringRef UID = GetDeviceName(playbackDeviceID[i]); | |||
| if (UID) { | |||
| @@ -1248,7 +1258,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); | |||
| } | |||
| } | |||
| // add sub-device clock array for the aggregate device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock); | |||
| } else { | |||
| @@ -1256,14 +1266,14 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| } | |||
| } | |||
| */ | |||
| //------------------------------------------------- | |||
| // Create a CFMutableArray for our sub-device list | |||
| //------------------------------------------------- | |||
| // we need to append the UID for each device to a CFMutableArray, so create one here | |||
| CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |||
| vector<CFStringRef> captureDeviceUID; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| CFStringRef ref = GetDeviceName(captureDeviceID[i]); | |||
| @@ -1273,7 +1283,7 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| // input sub-devices in this example, so append the sub-device's UID to the CFArray | |||
| CFArrayAppendValue(subDevicesArray, ref); | |||
| } | |||
| vector<CFStringRef> playbackDeviceUID; | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| CFStringRef ref = GetDeviceName(playbackDeviceID[i]); | |||
| @@ -1283,39 +1293,39 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| // output sub-devices in this example, so append the sub-device's UID to the CFArray | |||
| CFArrayAppendValue(subDevicesArray, ref); | |||
| } | |||
| //----------------------------------------------------------------------- | |||
| // Feed the dictionary to the plugin, to create a blank aggregate device | |||
| //----------------------------------------------------------------------- | |||
| AudioObjectPropertyAddress pluginAOPA; | |||
| pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice; | |||
| pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; | |||
| pluginAOPA.mElement = kAudioObjectPropertyElementMaster; | |||
| UInt32 outDataSize; | |||
| osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error"); | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error"); | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| // pause for a bit to make sure that everything completed correctly | |||
| // this is to work around a bug in the HAL where a new aggregate device seems to disappear briefly after it is created | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| //------------------------- | |||
| // Set the sub-device list | |||
| //------------------------- | |||
| pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList; | |||
| pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; | |||
| pluginAOPA.mElement = kAudioObjectPropertyElementMaster; | |||
| @@ -1326,14 +1336,14 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| //----------------------- | |||
| // Set the master device | |||
| //----------------------- | |||
| // set the master device manually (this is the device which will act as the master clock for the aggregate device) | |||
| // pass in the UID of the device you want to use | |||
| pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice; | |||
| @@ -1346,36 +1356,36 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| // Prepare sub-devices for clock drift compensation | |||
| // Workaround for bug in the HAL : until 10.6.2 | |||
| if (fClockDriftCompensate) { | |||
| if (need_clock_drift_compensation) { | |||
| jack_info("Clock drift compensation activated..."); | |||
| // Get the property data size | |||
| osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); | |||
| printError(osErr); | |||
| } | |||
| // Calculate the number of object IDs | |||
| subDevicesNum = outSize / sizeof(AudioObjectID); | |||
| jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum); | |||
| AudioObjectID subDevices[subDevicesNum]; | |||
| outSize = sizeof(subDevices); | |||
| osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); | |||
| printError(osErr); | |||
| } | |||
| // Set kAudioSubDevicePropertyDriftCompensation property... | |||
| for (UInt32 index = 0; index < subDevicesNum; ++index) { | |||
| UInt32 theDriftCompensationValue = 1; | |||
| @@ -1388,50 +1398,50 @@ OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> ca | |||
| } else { | |||
| jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)"); | |||
| } | |||
| } | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| //---------- | |||
| // Clean up | |||
| //---------- | |||
| // release the private AD key | |||
| CFRelease(AggregateDeviceNumberRef); | |||
| // release the CF objects we have created - we don't need them any more | |||
| CFRelease(aggDeviceDict); | |||
| CFRelease(subDevicesArray); | |||
| if (subDevicesArrayClock) | |||
| CFRelease(subDevicesArrayClock); | |||
| // release the device UID | |||
| for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { | |||
| CFRelease(captureDeviceUID[i]); | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) { | |||
| CFRelease(playbackDeviceUID[i]); | |||
| } | |||
| jack_log("New aggregate device %ld", *outAggregateDevice); | |||
| return noErr; | |||
| error: | |||
| DestroyAggregateDevice(); | |||
| return -1; | |||
| } | |||
| bool JackCoreAudioAdapter::IsAggregateDevice(AudioDeviceID device) | |||
| { | |||
| OSStatus err = noErr; | |||
| AudioObjectID sub_device[32]; | |||
| UInt32 outSize = sizeof(sub_device); | |||
| err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| if (err != noErr) { | |||
| jack_log("Device does not have subdevices"); | |||
| return false; | |||
| @@ -1494,7 +1504,7 @@ extern "C" | |||
| strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | |||
| strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | |||
| desc->nparams = 13; | |||
| desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | |||
| @@ -1574,7 +1584,7 @@ extern "C" | |||
| desc->params[i].value.i = TRUE; | |||
| strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "quality"); | |||
| desc->params[i].character = 'q'; | |||
| @@ -1582,7 +1592,7 @@ extern "C" | |||
| desc->params[i].value.ui = 0; | |||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "ring-buffer"); | |||
| desc->params[i].character = 'g'; | |||
| @@ -1590,7 +1600,7 @@ extern "C" | |||
| desc->params[i].value.ui = 32768; | |||
| strcpy(desc->params[i].short_desc, "Fixed ringbuffer size"); | |||
| strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)"); | |||
| i++; | |||
| strcpy(desc->params[i].name, "clock-drift"); | |||
| desc->params[i].character = 's'; | |||
| @@ -1598,7 +1608,7 @@ extern "C" | |||
| desc->params[i].value.i = FALSE; | |||
| strcpy(desc->params[i].short_desc, "Clock drift compensation"); | |||
| strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device"); | |||
| return desc; | |||
| } | |||
| @@ -39,7 +39,7 @@ static void Print4CharCode(const char* msg, long c) | |||
| { | |||
| UInt32 __4CC_number = (c); | |||
| char __4CC_string[5]; | |||
| *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); | |||
| *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number); | |||
| __4CC_string[4] = 0; | |||
| jack_log("%s'%s'", (msg), __4CC_string); | |||
| } | |||
| @@ -194,22 +194,22 @@ OSStatus JackCoreAudioDriver::Render(void *inRefCon, | |||
| driver->fActionFags = ioActionFlags; | |||
| driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp; | |||
| driver->fDriverOutputData = ioData; | |||
| // Setup threadded based log function once... | |||
| if (set_threaded_log_function()) { | |||
| jack_log("set_threaded_log_function"); | |||
| JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint); | |||
| if (driver->fComputationGrain > 0) { | |||
| jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100)); | |||
| driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain; | |||
| } | |||
| // Signal waiting start function... | |||
| driver->fState = true; | |||
| } | |||
| driver->CycleTakeBeginTime(); | |||
| return driver->Process(); | |||
| } | |||
| @@ -276,9 +276,9 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| void* inClientData) | |||
| { | |||
| JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData; | |||
| switch (inPropertyID) { | |||
| case kAudioDevicePropertyDeviceIsRunning: { | |||
| UInt32 isrunning = 0; | |||
| UInt32 outsize = sizeof(UInt32); | |||
| @@ -287,14 +287,14 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| } | |||
| break; | |||
| } | |||
| case kAudioDeviceProcessorOverload: { | |||
| jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload"); | |||
| jack_time_t cur_time = GetMicroSeconds(); | |||
| driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... | |||
| driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing... | |||
| break; | |||
| } | |||
| case kAudioDevicePropertyStreamConfiguration: { | |||
| jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit..."); | |||
| driver->NotifyFailure(JackBackendError, "Another application has changed the device configuration."); // Message length limited to JACK_MESSAGE_SIZE | |||
| @@ -302,25 +302,25 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| kill(JackTools::GetPID(), SIGINT); | |||
| return kAudioHardwareUnsupportedOperationError; | |||
| } | |||
| case kAudioDevicePropertyNominalSampleRate: { | |||
| Float64 sampleRate = 0; | |||
| UInt32 outsize = sizeof(Float64); | |||
| OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate); | |||
| if (err != noErr) | |||
| return kAudioHardwareUnsupportedOperationError; | |||
| char device_name[256]; | |||
| const char* digidesign_name = "Digidesign"; | |||
| driver->GetDeviceNameFromID(driver->fDeviceID, device_name); | |||
| if (sampleRate != driver->fEngineControl->fSampleRate) { | |||
| // Digidesign hardware, so "special" code : change the SR again here | |||
| if (strncmp(device_name, digidesign_name, sizeof(digidesign_name)) == 0) { | |||
| jack_log("Digidesign HW = %s", device_name); | |||
| // Set sample rate again... | |||
| sampleRate = driver->fEngineControl->fSampleRate; | |||
| err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sampleRate); | |||
| @@ -330,7 +330,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| } else { | |||
| jack_log("Set sample rate = %f", sampleRate); | |||
| } | |||
| // Check new sample rate again... | |||
| outsize = sizeof(Float64); | |||
| err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate); | |||
| @@ -341,7 +341,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| jack_log("Checked sample rate = %f", sampleRate); | |||
| } | |||
| return noErr; | |||
| } else { | |||
| driver->NotifyFailure(JackBackendError, "Another application has changed the sample rate."); // Message length limited to JACK_MESSAGE_SIZE | |||
| driver->CloseAUHAL(); | |||
| @@ -350,7 +350,7 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, | |||
| } | |||
| } | |||
| } | |||
| } | |||
| return noErr; | |||
| } | |||
| @@ -405,6 +405,10 @@ OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id) | |||
| if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) | |||
| return res; | |||
| if (inDefault == 0) { | |||
| jack_error("Error : input device is 0, please select a correct one !!"); | |||
| return -1; | |||
| } | |||
| jack_log("GetDefaultInputDevice: input = %ld ", inDefault); | |||
| *id = inDefault; | |||
| return noErr; | |||
| @@ -419,6 +423,10 @@ OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id) | |||
| if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) | |||
| return res; | |||
| if (outDefault == 0) { | |||
| jack_error("Error : output device is 0, please select a correct one !!"); | |||
| return -1; | |||
| } | |||
| jack_log("GetDefaultOutputDevice: output = %ld", outDefault); | |||
| *id = outDefault; | |||
| return noErr; | |||
| @@ -435,7 +443,7 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe | |||
| OSStatus err = noErr; | |||
| UInt32 outSize; | |||
| Boolean outWritable; | |||
| channelCount = 0; | |||
| err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable); | |||
| if (err == noErr) { | |||
| @@ -450,11 +458,11 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channe | |||
| } | |||
| JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | |||
| : JackAudioDriver(name, alias, engine, table), | |||
| fJackInputData(NULL), | |||
| fDriverOutputData(NULL), | |||
| fPluginID(0), | |||
| fState(false), | |||
| : JackAudioDriver(name, alias, engine, table), | |||
| fJackInputData(NULL), | |||
| fDriverOutputData(NULL), | |||
| fPluginID(0), | |||
| fState(false), | |||
| fHogged(false), | |||
| fIOUsage(1.f), | |||
| fComputationGrain(-1.f), | |||
| @@ -464,7 +472,7 @@ JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, Ja | |||
| JackCoreAudioDriver::~JackCoreAudioDriver() | |||
| {} | |||
| OSStatus JackCoreAudioDriver::DestroyAggregateDevice() | |||
| OSStatus JackCoreAudioDriver::DestroyAggregateDevice() | |||
| { | |||
| OSStatus osErr = noErr; | |||
| AudioObjectPropertyAddress pluginAOPA; | |||
| @@ -472,37 +480,37 @@ OSStatus JackCoreAudioDriver::DestroyAggregateDevice() | |||
| pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; | |||
| pluginAOPA.mElement = kAudioObjectPropertyElementMaster; | |||
| UInt32 outDataSize; | |||
| if (fPluginID > 0) { | |||
| osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error"); | |||
| printError(osErr); | |||
| return osErr; | |||
| } | |||
| } | |||
| return noErr; | |||
| } | |||
| OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| { | |||
| OSStatus err = noErr; | |||
| AudioObjectID sub_device[32]; | |||
| UInt32 outSize = sizeof(sub_device); | |||
| err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| vector<AudioDeviceID> captureDeviceIDArray; | |||
| if (err != noErr) { | |||
| jack_log("Input device does not have subdevices"); | |||
| captureDeviceIDArray.push_back(captureDeviceID); | |||
| @@ -513,10 +521,10 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI | |||
| captureDeviceIDArray.push_back(sub_device[i]); | |||
| } | |||
| } | |||
| err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| vector<AudioDeviceID> playbackDeviceIDArray; | |||
| if (err != noErr) { | |||
| jack_log("Output device does not have subdevices"); | |||
| playbackDeviceIDArray.push_back(playbackDeviceID); | |||
| @@ -527,16 +535,16 @@ OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceI | |||
| playbackDeviceIDArray.push_back(sub_device[i]); | |||
| } | |||
| } | |||
| return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice); | |||
| } | |||
| OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice) | |||
| { | |||
| OSStatus osErr = noErr; | |||
| UInt32 outSize; | |||
| Boolean outWritable; | |||
| // Prepare sub-devices for clock drift compensation | |||
| // Workaround for bug in the HAL : until 10.6.2 | |||
| AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; | |||
| @@ -545,7 +553,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| AudioClassID inClass = kAudioSubDeviceClassID; | |||
| void* theQualifierData = &inClass; | |||
| UInt32 subDevicesNum = 0; | |||
| //--------------------------------------------------------------------------- | |||
| // Setup SR of both devices otherwise creating AD may fail... | |||
| //--------------------------------------------------------------------------- | |||
| @@ -553,18 +561,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| UInt32 clockdomain = 0; | |||
| outSize = sizeof(UInt32); | |||
| bool need_clock_drift_compensation = false; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device"); | |||
| } else { | |||
| // Check clock domain | |||
| osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| if (osErr != 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); | |||
| printError(osErr); | |||
| } else { | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain); | |||
| if (clockdomain != 0 && clockdomain != keptclockdomain) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); | |||
| @@ -573,18 +581,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| } | |||
| } | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device"); | |||
| } else { | |||
| // Check clock domain | |||
| osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain); | |||
| if (osErr != 0) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error"); | |||
| printError(osErr); | |||
| } else { | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain; | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain); | |||
| if (clockdomain != 0 && clockdomain != keptclockdomain) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed..."); | |||
| @@ -593,7 +601,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| } | |||
| } | |||
| } | |||
| // If no valid clock domain was found, then assume we have to compensate... | |||
| if (keptclockdomain == 0) { | |||
| need_clock_drift_compensation = true; | |||
| @@ -602,18 +610,18 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| //--------------------------------------------------------------------------- | |||
| // Start to create a new aggregate by getting the base audio hardware plugin | |||
| //--------------------------------------------------------------------------- | |||
| char device_name[256]; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| GetDeviceNameFromID(captureDeviceID[i], device_name); | |||
| jack_info("Separated input = '%s' ", device_name); | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| GetDeviceNameFromID(playbackDeviceID[i], device_name); | |||
| jack_info("Separated output = '%s' ", device_name); | |||
| } | |||
| osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error"); | |||
| @@ -624,7 +632,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| AudioValueTranslation pluginAVT; | |||
| CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio"); | |||
| pluginAVT.mInputData = &inBundleRef; | |||
| pluginAVT.mInputDataSize = sizeof(inBundleRef); | |||
| pluginAVT.mOutputData = &fPluginID; | |||
| @@ -645,22 +653,22 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex"); | |||
| CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex"); | |||
| // add the name of the device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef); | |||
| // add our choice of UID for the aggregate device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef); | |||
| // add a "private aggregate key" to the dictionary | |||
| int value = 1; | |||
| CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value); | |||
| SInt32 system; | |||
| Gestalt(gestaltSystemVersion, &system); | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054); | |||
| // Starting with 10.5.4 systems, the AD can be internal... (better) | |||
| if (system < 0x00001054) { | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device...."); | |||
| @@ -668,16 +676,16 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device...."); | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef); | |||
| } | |||
| // Prepare sub-devices for clock drift compensation | |||
| CFMutableArrayRef subDevicesArrayClock = NULL; | |||
| /* | |||
| if (fClockDriftCompensate) { | |||
| if (need_clock_drift_compensation) { | |||
| jack_info("Clock drift compensation activated..."); | |||
| subDevicesArrayClock = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| CFStringRef UID = GetDeviceName(captureDeviceID[i]); | |||
| if (UID) { | |||
| @@ -688,7 +696,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); | |||
| } | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| CFStringRef UID = GetDeviceName(playbackDeviceID[i]); | |||
| if (UID) { | |||
| @@ -699,7 +707,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| CFArrayAppendValue(subDevicesArrayClock, subdeviceAggDeviceDict); | |||
| } | |||
| } | |||
| // add sub-device clock array for the aggregate device to the dictionary | |||
| CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceSubDeviceListKey), subDevicesArrayClock); | |||
| } else { | |||
| @@ -707,14 +715,14 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| } | |||
| } | |||
| */ | |||
| //------------------------------------------------- | |||
| // Create a CFMutableArray for our sub-device list | |||
| //------------------------------------------------- | |||
| // we need to append the UID for each device to a CFMutableArray, so create one here | |||
| CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |||
| vector<CFStringRef> captureDeviceUID; | |||
| for (UInt32 i = 0; i < captureDeviceID.size(); i++) { | |||
| CFStringRef ref = GetDeviceName(captureDeviceID[i]); | |||
| @@ -724,7 +732,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| // input sub-devices in this example, so append the sub-device's UID to the CFArray | |||
| CFArrayAppendValue(subDevicesArray, ref); | |||
| } | |||
| vector<CFStringRef> playbackDeviceUID; | |||
| for (UInt32 i = 0; i < playbackDeviceID.size(); i++) { | |||
| CFStringRef ref = GetDeviceName(playbackDeviceID[i]); | |||
| @@ -734,11 +742,11 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| // output sub-devices in this example, so append the sub-device's UID to the CFArray | |||
| CFArrayAppendValue(subDevicesArray, ref); | |||
| } | |||
| //----------------------------------------------------------------------- | |||
| // Feed the dictionary to the plugin, to create a blank aggregate device | |||
| //----------------------------------------------------------------------- | |||
| AudioObjectPropertyAddress pluginAOPA; | |||
| pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice; | |||
| pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal; | |||
| @@ -751,7 +759,7 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error"); | |||
| @@ -777,10 +785,10 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| //----------------------- | |||
| // Set the master device | |||
| //----------------------- | |||
| @@ -797,36 +805,36 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| printError(osErr); | |||
| goto error; | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| // Prepare sub-devices for clock drift compensation | |||
| // Workaround for bug in the HAL : until 10.6.2 | |||
| if (fClockDriftCompensate) { | |||
| if (need_clock_drift_compensation) { | |||
| jack_info("Clock drift compensation activated..."); | |||
| // Get the property data size | |||
| osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); | |||
| printError(osErr); | |||
| } | |||
| // Calculate the number of object IDs | |||
| subDevicesNum = outSize / sizeof(AudioObjectID); | |||
| jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum); | |||
| AudioObjectID subDevices[subDevicesNum]; | |||
| outSize = sizeof(subDevices); | |||
| osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices); | |||
| if (osErr != noErr) { | |||
| jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error"); | |||
| printError(osErr); | |||
| } | |||
| // Set kAudioSubDevicePropertyDriftCompensation property... | |||
| for (UInt32 index = 0; index < subDevicesNum; ++index) { | |||
| UInt32 theDriftCompensationValue = 1; | |||
| @@ -839,22 +847,22 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| } else { | |||
| jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)"); | |||
| } | |||
| } | |||
| } | |||
| // pause again to give the changes time to take effect | |||
| CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false); | |||
| //---------- | |||
| // Clean up | |||
| //---------- | |||
| // release the private AD key | |||
| CFRelease(AggregateDeviceNumberRef); | |||
| // release the CF objects we have created - we don't need them any more | |||
| CFRelease(aggDeviceDict); | |||
| CFRelease(subDevicesArray); | |||
| if (subDevicesArrayClock) | |||
| CFRelease(subDevicesArrayClock); | |||
| @@ -862,35 +870,35 @@ OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> cap | |||
| for (UInt32 i = 0; i < captureDeviceUID.size(); i++) { | |||
| CFRelease(captureDeviceUID[i]); | |||
| } | |||
| for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) { | |||
| CFRelease(playbackDeviceUID[i]); | |||
| } | |||
| jack_log("New aggregate device %ld", *outAggregateDevice); | |||
| return noErr; | |||
| error: | |||
| DestroyAggregateDevice(); | |||
| return -1; | |||
| } | |||
| int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| const char* playback_driver_uid, | |||
| char* capture_driver_name, | |||
| char* playback_driver_name, | |||
| int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| const char* playback_driver_uid, | |||
| char* capture_driver_name, | |||
| char* playback_driver_name, | |||
| jack_nframes_t samplerate) | |||
| { | |||
| capture_driver_name[0] = 0; | |||
| playback_driver_name[0] = 0; | |||
| // Duplex | |||
| if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { | |||
| jack_log("JackCoreAudioDriver::Open duplex"); | |||
| // Same device for capture and playback... | |||
| if (strcmp(capture_driver_uid, playback_driver_uid) == 0) { | |||
| if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) { | |||
| jack_log("Will take default in/out"); | |||
| if (GetDefaultDevice(&fDeviceID) != noErr) { | |||
| @@ -902,12 +910,12 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| jack_error("Cannot get device name from device ID"); | |||
| return -1; | |||
| } | |||
| } else { | |||
| // Creates aggregate device | |||
| AudioDeviceID captureID, playbackID; | |||
| if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | |||
| jack_log("Will take default input"); | |||
| if (GetDefaultInputDevice(&captureID) != noErr) { | |||
| @@ -963,10 +971,10 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| jack_log("JackCoreAudioDriver::Open default driver"); | |||
| if (GetDefaultDevice(&fDeviceID) != noErr) { | |||
| jack_error("Cannot open default device in duplex mode, so aggregate default input and default output"); | |||
| // Creates aggregate device | |||
| AudioDeviceID captureID, playbackID; | |||
| if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) { | |||
| jack_log("Will take default input"); | |||
| if (GetDefaultInputDevice(&captureID) != noErr) { | |||
| @@ -974,7 +982,7 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) { | |||
| jack_log("Will take default output"); | |||
| if (GetDefaultOutputDevice(&playbackID) != noErr) { | |||
| @@ -982,12 +990,12 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, | |||
| return -1; | |||
| } | |||
| } | |||
| if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) | |||
| return -1; | |||
| } | |||
| } | |||
| if (fHogged) { | |||
| if (TakeHog()) { | |||
| jack_info("Device = %ld has been hogged", fDeviceID); | |||
| @@ -1111,7 +1119,7 @@ int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes | |||
| usleep(100000); | |||
| jack_log("Wait count = %d", count); | |||
| } | |||
| // Check new sample rate | |||
| outSize = sizeof(Float64); | |||
| err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); | |||
| @@ -1150,7 +1158,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| jack_error("No input and output channels..."); | |||
| return -1; | |||
| } | |||
| // AUHAL | |||
| ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; | |||
| Component HALOutput = FindNextComponent(NULL, &cd); | |||
| @@ -1177,7 +1185,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| enableIO = 0; | |||
| jack_log("Setup AUHAL input off"); | |||
| } | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); | |||
| @@ -1192,14 +1200,14 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| enableIO = 0; | |||
| jack_log("Setup AUHAL output off"); | |||
| } | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); | |||
| printError(err1); | |||
| goto error; | |||
| } | |||
| size = sizeof(AudioDeviceID); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size); | |||
| if (err1 != noErr) { | |||
| @@ -1217,7 +1225,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| printError(err1); | |||
| goto error; | |||
| } | |||
| // Set buffer size | |||
| if (capturing && inchannels > 0) { | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32)); | |||
| @@ -1272,7 +1280,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| // Setup stream converters | |||
| if (capturing && inchannels > 0) { | |||
| size = sizeof(AudioStreamBasicDescription); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size); | |||
| if (err1 != noErr) { | |||
| @@ -1281,7 +1289,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| goto error; | |||
| } | |||
| PrintStreamDesc(&srcFormat); | |||
| jack_log("Setup AUHAL input stream converter SR = %ld", samplerate); | |||
| srcFormat.mSampleRate = samplerate; | |||
| srcFormat.mFormatID = kAudioFormatLinearPCM; | |||
| @@ -1292,7 +1300,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| srcFormat.mChannelsPerFrame = inchannels; | |||
| srcFormat.mBitsPerChannel = 32; | |||
| PrintStreamDesc(&srcFormat); | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); | |||
| @@ -1302,7 +1310,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| } | |||
| if (playing && outchannels > 0) { | |||
| size = sizeof(AudioStreamBasicDescription); | |||
| err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size); | |||
| if (err1 != noErr) { | |||
| @@ -1311,7 +1319,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| goto error; | |||
| } | |||
| PrintStreamDesc(&dstFormat); | |||
| jack_log("Setup AUHAL output stream converter SR = %ld", samplerate); | |||
| dstFormat.mSampleRate = samplerate; | |||
| dstFormat.mFormatID = kAudioFormatLinearPCM; | |||
| @@ -1322,7 +1330,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| dstFormat.mChannelsPerFrame = outchannels; | |||
| dstFormat.mBitsPerChannel = 32; | |||
| PrintStreamDesc(&dstFormat); | |||
| err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription)); | |||
| if (err1 != noErr) { | |||
| jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); | |||
| @@ -1355,7 +1363,7 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||
| } | |||
| return 0; | |||
| error: | |||
| CloseAUHAL(); | |||
| return -1; | |||
| @@ -1486,12 +1494,12 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
| fComputationGrain = float(computation_grain) / 100.f; | |||
| fHogged = hogged; | |||
| fClockDriftCompensate = clock_drift; | |||
| SInt32 major; | |||
| SInt32 minor; | |||
| Gestalt(gestaltSystemVersionMajor, &major); | |||
| Gestalt(gestaltSystemVersionMinor, &minor); | |||
| // Starting with 10.6 systems, the HAL notification thread is created internally | |||
| if (major == 10 && minor >= 6) { | |||
| CFRunLoopRef theRunLoop = NULL; | |||
| @@ -1515,10 +1523,10 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
| if (SetupBufferSize(buffer_size) < 0) | |||
| goto error; | |||
| if (SetupSampleRate(samplerate) < 0) | |||
| goto error; | |||
| if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0) | |||
| goto error; | |||
| @@ -1528,7 +1536,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size, | |||
| if (AddListeners() < 0) | |||
| goto error; | |||
| // Core driver may have changed the in/out values | |||
| fCaptureChannels = inchannels; | |||
| fPlaybackChannels = outchannels; | |||
| @@ -1561,7 +1569,7 @@ int JackCoreAudioDriver::Attach() | |||
| char channel_name[64]; | |||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||
| char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||
| jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | |||
| for (int i = 0; i < fCaptureChannels; i++) { | |||
| @@ -1670,7 +1678,7 @@ int JackCoreAudioDriver::Start() | |||
| OSStatus err = AudioOutputUnitStart(fAUHAL); | |||
| if (err != noErr) | |||
| return -1; | |||
| // Waiting for Measure callback to be called (= driver has started) | |||
| fState = false; | |||
| int count = 0; | |||
| @@ -1678,7 +1686,7 @@ int JackCoreAudioDriver::Start() | |||
| usleep(100000); | |||
| jack_log("JackCoreAudioDriver::Start wait count = %d", count); | |||
| } | |||
| if (count < WAIT_COUNTER) { | |||
| jack_info("CoreAudio driver is running..."); | |||
| return 0; | |||
| @@ -1738,17 +1746,17 @@ bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput) | |||
| return false; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| bool JackCoreAudioDriver::TakeHog() | |||
| { | |||
| OSStatus err = noErr; | |||
| AudioObjectID sub_device[32]; | |||
| UInt32 outSize = sizeof(sub_device); | |||
| err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device); | |||
| if (err != noErr) { | |||
| jack_log("Device does not have subdevices"); | |||
| return TakeHogAux(fDeviceID, true); | |||
| @@ -1763,12 +1771,12 @@ bool JackCoreAudioDriver::TakeHog() | |||
| return true; | |||
| } | |||
| } | |||
| bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device) | |||
| { | |||
| UInt32 deviceType, outSize = sizeof(UInt32); | |||
| OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType); | |||
| if (err != noErr) { | |||
| jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error"); | |||
| return false; | |||
| @@ -1786,7 +1794,7 @@ extern "C" | |||
| { | |||
| #endif | |||
| SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() | |||
| SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() | |||
| { | |||
| jack_driver_desc_t *desc; | |||
| unsigned int i; | |||
| @@ -1794,7 +1802,7 @@ extern "C" | |||
| strcpy(desc->name, "coreaudio"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | |||
| strcpy(desc->desc, "Apple CoreAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | |||
| desc->nparams = 17; | |||
| desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); | |||
| @@ -1898,7 +1906,7 @@ extern "C" | |||
| desc->params[i].value.i = FALSE; | |||
| strcpy(desc->params[i].short_desc, "Display available CoreAudio devices"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "hog"); | |||
| desc->params[i].character = 'H'; | |||
| @@ -1906,7 +1914,7 @@ extern "C" | |||
| desc->params[i].value.i = FALSE; | |||
| strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "async-latency"); | |||
| desc->params[i].character = 'L'; | |||
| @@ -1914,7 +1922,7 @@ extern "C" | |||
| desc->params[i].value.i = 100; | |||
| strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "grain"); | |||
| desc->params[i].character = 'G'; | |||
| @@ -1922,7 +1930,7 @@ extern "C" | |||
| desc->params[i].value.i = 100; | |||
| strcpy(desc->params[i].short_desc, "Computation grain in RT thread (percent)"); | |||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | |||
| i++; | |||
| strcpy(desc->params[i].name, "clock-drift"); | |||
| desc->params[i].character = 's'; | |||
| @@ -1934,7 +1942,7 @@ extern "C" | |||
| return desc; | |||
| } | |||
| SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||
| SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||
| { | |||
| jack_nframes_t srate = 44100; | |||
| jack_nframes_t frames_per_interrupt = 128; | |||
| @@ -1953,10 +1961,10 @@ extern "C" | |||
| int computation_grain = -1; | |||
| bool hogged = false; | |||
| bool clock_drift = false; | |||
| for (node = params; node; node = jack_slist_next(node)) { | |||
| param = (const jack_driver_param_t *) node->data; | |||
| switch (param->character) { | |||
| case 'd': | |||
| @@ -2018,19 +2026,19 @@ extern "C" | |||
| case 'l': | |||
| Jack::DisplayDeviceNames(); | |||
| break; | |||
| case 'H': | |||
| hogged = true; | |||
| break; | |||
| case 'L': | |||
| async_output_latency = param->value.ui; | |||
| break; | |||
| case 'G': | |||
| computation_grain = param->value.ui; | |||
| break; | |||
| case 's': | |||
| clock_drift = true; | |||
| break; | |||
| @@ -2044,7 +2052,7 @@ extern "C" | |||
| } | |||
| Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table); | |||
| if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid, | |||
| if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid, | |||
| playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) { | |||
| return driver; | |||
| } else { | |||
| @@ -33,47 +33,47 @@ namespace Jack | |||
| \brief Mutex abstraction. | |||
| */ | |||
| class JackBasePosixMutex | |||
| { | |||
| protected: | |||
| pthread_mutex_t fMutex; | |||
| public: | |||
| JackBasePosixMutex() | |||
| { | |||
| pthread_mutex_init(&fMutex, NULL); | |||
| pthread_mutex_init(&fMutex, NULL); | |||
| } | |||
| virtual ~JackBasePosixMutex() | |||
| { | |||
| pthread_mutex_destroy(&fMutex); | |||
| } | |||
| void Lock() | |||
| { | |||
| int res = pthread_mutex_lock(&fMutex); | |||
| if (res != 0) | |||
| jack_error("JackBasePosixMutex::Lock res = %d", res); | |||
| jack_log("JackBasePosixMutex::Lock res = %d", res); | |||
| } | |||
| bool Trylock() | |||
| { | |||
| return (pthread_mutex_trylock(&fMutex) == 0); | |||
| } | |||
| void Unlock() | |||
| { | |||
| int res = pthread_mutex_unlock(&fMutex); | |||
| if (res != 0) | |||
| jack_error("JackBasePosixMutex::Unlock res = %d", res); | |||
| jack_log("JackBasePosixMutex::Unlock res = %d", res); | |||
| } | |||
| }; | |||
| class JackPosixMutex | |||
| { | |||
| @@ -97,7 +97,7 @@ class JackPosixMutex | |||
| res = pthread_mutexattr_destroy(&mutex_attr); | |||
| assert(res == 0); | |||
| } | |||
| virtual ~JackPosixMutex() | |||
| { | |||
| pthread_mutex_destroy(&fMutex); | |||
| @@ -107,7 +107,7 @@ class JackPosixMutex | |||
| { | |||
| int res = pthread_mutex_lock(&fMutex); | |||
| if (res != 0) | |||
| jack_error("JackPosixMutex::Lock res = %d", res); | |||
| jack_log("JackPosixMutex::Lock res = %d", res); | |||
| return (res == 0); | |||
| } | |||
| @@ -120,7 +120,7 @@ class JackPosixMutex | |||
| { | |||
| int res = pthread_mutex_unlock(&fMutex); | |||
| if (res != 0) | |||
| jack_error("JackPosixMutex::Unlock res = %d", res); | |||
| jack_log("JackPosixMutex::Unlock res = %d", res); | |||
| return (res == 0); | |||
| } | |||