Browse Source

rebase from trunk 3502:3528

git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3529 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/1.9.8
sletz 15 years ago
parent
commit
b4f737eb1b
46 changed files with 888 additions and 198 deletions
  1. +45
    -24
      ChangeLog
  2. +1
    -1
      common/JackAPI.cpp
  3. +37
    -16
      common/JackClient.cpp
  4. +1
    -0
      common/JackClient.h
  5. +5
    -8
      common/JackConnectionManager.cpp
  6. +0
    -2
      common/JackConstants.h
  7. +31
    -2
      common/JackControlAPI.cpp
  8. +5
    -2
      common/JackControlAPI.h
  9. +5
    -2
      common/JackDriver.cpp
  10. +6
    -0
      common/JackDriver.h
  11. +5
    -3
      common/JackEngine.cpp
  12. +1
    -1
      common/JackEngineControl.cpp
  13. +6
    -2
      common/JackEngineControl.h
  14. +3
    -1
      common/JackEngineProfiling.cpp
  15. +1
    -0
      common/JackLibClient.cpp
  16. +61
    -14
      common/JackServer.cpp
  17. +5
    -3
      common/JackServer.h
  18. +19
    -4
      common/JackServerGlobals.cpp
  19. +4
    -3
      common/JackServerGlobals.h
  20. +5
    -0
      common/JackThreadedDriver.cpp
  21. +1
    -0
      common/JackThreadedDriver.h
  22. +6
    -3
      common/JackTime.h
  23. +6
    -4
      common/JackTransportEngine.cpp
  24. +7
    -4
      common/JackTypes.h
  25. +35
    -2
      common/Jackdmp.cpp
  26. +31
    -2
      common/jack/control.h
  27. +1
    -0
      common/wscript
  28. +3
    -1
      dbus/audio_reserve.c
  29. +16
    -0
      dbus/controller.c
  30. +15
    -0
      dbus/controller_iface_control.c
  31. +5
    -0
      dbus/controller_internal.h
  32. +4
    -0
      example-clients/jack_control
  33. +46
    -1
      example-clients/server_control.cpp
  34. +227
    -62
      linux/JackLinuxTime.c
  35. +12
    -10
      linux/alsa/JackAlsaDriver.cpp
  36. +14
    -0
      linux/cycles.h
  37. +1
    -1
      macosx/JackMacEngineRPC.cpp
  38. +9
    -0
      macosx/JackMachTime.c
  39. +4
    -0
      macosx/Jackdmp.xcodeproj/project.pbxproj
  40. +172
    -8
      macosx/coreaudio/JackCoreAudioDriver.cpp
  41. +1
    -0
      macosx/coreaudio/JackCoreAudioDriver.h
  42. +8
    -0
      solaris/JackSolarisTime.c
  43. +3
    -3
      windows/JackTypes_os.h
  44. +1
    -1
      windows/JackWinNamedPipe.cpp
  45. +12
    -6
      windows/JackWinTime.c
  46. +2
    -2
      windows/jackd.workspace

+ 45
- 24
ChangeLog View File

@@ -18,50 +18,71 @@ Fernando Lopez-Lezcano
Romain Moret
Florian Faber
Michael Voigt
Torben Hohn
Torben Hohn
Paul Davis
---------------------------
Jackdmp changes log
---------------------------

2009-04-08 Stephane Letz <letz@grame.fr>
---------------------------

* Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver) in progress.
2009-05-06 Stephane Letz <letz@grame.fr>
* Fix transport callback (timebase master, sync) issue when used after jack_activate (RT thread was not running).

2009-04-03 Stephane Letz <letz@grame.fr>
2009-05-05 Stephane Letz <letz@grame.fr>
* First working version of native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver).

* Simplify JackClient RT code, jack_thread_wait API marked deprecated."
2009-04-22 Stephane Letz <letz@grame.fr>
* jackctl_server_load_master renamed to jackctl_server_switch_master, jackctl_server_unload_master is removed.

2009-04-21 Stephane Letz <letz@grame.fr>
* Add jackctl_server_load_master/jackctl_server_unload_master API.
2009-04-20 Stephane Letz <letz@grame.fr>
* In ALSA audio card reservation code, tries to open the card even if reservation fails.
* Clock source setting on Linux.
2009-04-08 Stephane Letz <letz@grame.fr>
* Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver) in progress.
2009-04-03 Stephane Letz <letz@grame.fr>
* Simplify JackClient RT code, jack_thread_wait API marked deprecated."
2009-03-29 Stephane Letz <letz@grame.fr>

* Cleanup JackInternalClient code.

* Cleanup JackInternalClient code.
2009-03-27 Stephane Letz <letz@grame.fr>

* Add a buffer size callback for netmaster that just remove the client (it will be recreated with the new parameters).

* Add a buffer size callback for netmaster that just remove the client (it will be recreated with the new parameters).
2009-03-26 Stephane Letz <letz@grame.fr>

* First working JackBoomerDriver two threads version.

* First working JackBoomerDriver two threads version.
2009-03-24 Stephane Letz <letz@grame.fr>

* New JackBoomerDriver class for Boomer driver on Solaris.
* New JackBoomerDriver class for Boomer driver on Solaris.
* Add mixed 32/64 bits mode (off by default).

2009-03-23 Stephane Letz <letz@grame.fr>
* Version 1.9.3 started.
2009-03-19 Stephane Letz <letz@grame.fr>
* Tim Blechmann optimization patch (inlining some heavy used methods).
2009-03-12 Stephane Letz <letz@grame.fr>
* Virtualize and allow overriding of thread creation function, to allow Wine support (from JACK1).
2009-03-12 Stephane Letz <letz@grame.fr>
* Try automatic adaptative mode in adapters.


+ 1
- 1
common/JackAPI.cpp View File

@@ -843,7 +843,7 @@ EXPORT jack_nframes_t jack_thread_wait(jack_client_t* ext_client, int status)
return 0;
} else {
jack_error("jack_thread_wait: deprecated, use jack_cycle_wait/jack_cycle_signal");
return -1;
return 0;
}
}



+ 37
- 16
common/JackClient.cpp View File

@@ -118,14 +118,13 @@ void JackClient::SetupDriverSync(bool freewheel)
{
if (!freewheel && !GetEngineControl()->fSyncMode) {
jack_log("JackClient::SetupDriverSync driver sem in flush mode");
fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(true);
fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(true);
fSynchroTable[MIDI_DRIVER_REFNUM].SetFlush(true);
for (int i = 0; i < GetEngineControl()->fDriverNum; i++) {
fSynchroTable[i].SetFlush(true);
}
} else {
jack_log("JackClient::SetupDriverSync driver sem in normal mode");
fSynchroTable[AUDIO_DRIVER_REFNUM].SetFlush(false);
fSynchroTable[FREEWHEEL_DRIVER_REFNUM].SetFlush(false);
fSynchroTable[MIDI_DRIVER_REFNUM].SetFlush(false);
for (int i = 0; i < GetEngineControl()->fDriverNum; i++)
fSynchroTable[i].SetFlush(false);
}
}

@@ -338,7 +337,7 @@ int JackClient::StartThread()
// Will do "something" on OSX only...
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);

if (fThread.Start() < 0) {
if (fThread.StartSync() < 0) {
jack_error("Start thread error");
return -1;
}
@@ -593,6 +592,27 @@ void JackClient::ShutDown()
// Transport management
//----------------------

inline int JackClient::ActivateAux()
{
// If activated without RT thread...
if (IsActive() && fThread.GetStatus() != JackThread::kRunning) {
jack_log("ActivateAux");
// RT thread is started
if (StartThread() < 0)
return -1;
int result = -1;
GetClientControl()->fCallback[kRealTimeCallback] = IsRealTime();
fChannel->ClientActivate(GetClientControl()->fRefNum, IsRealTime(), &result);
return result;
} else {
return 0;
}
}

int JackClient::ReleaseTimebase()
{
int result = -1;
@@ -611,29 +631,30 @@ int JackClient::SetSyncCallback(JackSyncCallback sync_callback, void* arg)
GetClientControl()->fTransportSync = (fSync != NULL);
fSyncArg = arg;
fSync = sync_callback;
return 0;
}

int JackClient::SetSyncTimeout(jack_time_t timeout)
{
GetEngineControl()->fTransport.SetSyncTimeout(timeout);
return 0;
return ActivateAux();
}

int JackClient::SetTimebaseCallback(int conditional, JackTimebaseCallback timebase_callback, void* arg)
{
int result = -1;
fChannel->SetTimebaseCallback(GetClientControl()->fRefNum, conditional, &result);
jack_log("SetTimebaseCallback result = %ld", result);
if (result == 0) {
GetClientControl()->fTransportTimebase = true;
fTimebase = timebase_callback;
fTimebaseArg = arg;
return ActivateAux();
} else {
fTimebase = NULL;
fTimebaseArg = NULL;
return -1;
}
return result;
}

int JackClient::SetSyncTimeout(jack_time_t timeout)
{
GetEngineControl()->fTransport.SetSyncTimeout(timeout);
return 0;
}

// Must be RT safe


+ 1
- 0
common/JackClient.h View File

@@ -108,6 +108,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
inline void CycleSignalAux(int status);
inline void CallSyncCallbackAux();
inline void CallTimebaseCallbackAux();
inline int ActivateAux();
public:



+ 5
- 8
common/JackConnectionManager.cpp View File

@@ -17,11 +17,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include <iostream>
#include <assert.h>
#include "JackConnectionManager.h"
#include "JackClientControl.h"
#include "JackEngineControl.h"
#include "JackGlobals.h"
#include "JackError.h"
#include <iostream>
#include <assert.h>

namespace Jack
{
@@ -54,12 +56,7 @@ bool JackConnectionManager::IsLoopPathAux(int ref1, int ref2) const
{
jack_log("JackConnectionManager::IsLoopPathAux ref1 = %ld ref2 = %ld", ref1, ref2);

if (ref1 == AUDIO_DRIVER_REFNUM // Driver is reached
|| ref2 == AUDIO_DRIVER_REFNUM
|| ref1 == FREEWHEEL_DRIVER_REFNUM
|| ref2 == FREEWHEEL_DRIVER_REFNUM
|| ref1 == MIDI_DRIVER_REFNUM
|| ref2 == MIDI_DRIVER_REFNUM) {
if (ref1 < GetEngineControl()->fDriverNum || ref2 < GetEngineControl()->fDriverNum) {
return false;
} else if (ref1 == ref2) { // Same refnum
return true;


+ 0
- 2
common/JackConstants.h View File

@@ -49,8 +49,6 @@

#define AUDIO_DRIVER_REFNUM 0 // Audio driver is initialized first, it will get the refnum 0
#define FREEWHEEL_DRIVER_REFNUM 1 // Freewheel driver is initialized second, it will get the refnum 1
#define MIDI_DRIVER_REFNUM 2 // Loopback driver is initialized third, it will get the refnum 2
#define REAL_REFNUM MIDI_DRIVER_REFNUM + 1 // Real clients start at MIDI_DRIVER_REFNUM + 1

#define JACK_DEFAULT_SERVER_NAME "default"



+ 31
- 2
common/JackControlAPI.cpp View File

@@ -81,6 +81,10 @@ struct jackctl_server
/* uint32_t, ports of the loopback driver */
union jackctl_parameter_value loopback_ports;
union jackctl_parameter_value default_loopback_ports;
/* uint32_t, clock source type */
union jackctl_parameter_value clock_source;
union jackctl_parameter_value default_clock_source;

/* bool */
union jackctl_parameter_value replace_registry;
@@ -733,6 +737,20 @@ EXPORT jackctl_server_t * jackctl_server_create()
{
goto fail_free_parameters;
}
value.ui = 0;
if (jackctl_add_parameter(
&server_ptr->parameters,
"clock-source",
"Clocksource type : c(ycle) | h(pet) | s(ystem)",
"",
JackParamUInt,
&server_ptr->clock_source,
&server_ptr->default_clock_source,
value) == NULL)
{
goto fail_free_parameters;
}

value.b = false;
if (jackctl_add_parameter(
@@ -864,6 +882,7 @@ jackctl_server_start(
server_ptr->realtime_priority.i,
server_ptr->loopback_ports.ui,
server_ptr->verbose.b,
(jack_timer_type_t)server_ptr->clock_source.ui,
server_ptr->name.str);
if (server_ptr->engine == NULL)
{
@@ -1163,7 +1182,7 @@ EXPORT bool jackctl_server_unload_internal(
}
}

EXPORT bool jackctl_server_load_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
{
if (server_ptr->engine != NULL) {
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
@@ -1173,13 +1192,23 @@ EXPORT bool jackctl_server_load_slave(jackctl_server * server_ptr, jackctl_drive
}
}

EXPORT bool jackctl_server_unload_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
{
if (server_ptr->engine != NULL) {
server_ptr->engine->RemoveSlave(driver_ptr->info);
delete driver_ptr->info;
return true;
} else {
return false;
}
}

EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
{
if (server_ptr->engine != NULL) {
return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0);
} else {
return false;
}
}


+ 5
- 2
common/JackControlAPI.h View File

@@ -220,12 +220,15 @@ EXPORT bool jackctl_server_unload_internal(
jackctl_server * server,
jackctl_internal * internal);
EXPORT bool jackctl_server_load_slave(jackctl_server_t * server,
EXPORT bool jackctl_server_add_slave(jackctl_server_t * server,
jackctl_driver_t * driver);

EXPORT bool jackctl_server_unload_slave(jackctl_server_t * server,
EXPORT bool jackctl_server_remove_slave(jackctl_server_t * server,
jackctl_driver_t * driver);

EXPORT bool
jackctl_server_switch_master(jackctl_server_t * server,
jackctl_driver_t * driver);

#if 0
{ /* Adjust editor indent */


+ 5
- 2
common/JackDriver.cpp View File

@@ -47,7 +47,7 @@ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* en
fBeginDateUst = 0;
fDelayedUsecs = 0.f;
fIsMaster = true;
}
}

JackDriver::JackDriver()
{
@@ -74,6 +74,7 @@ int JackDriver::Open()

fClientControl.fRefNum = refnum;
fClientControl.fActive = true;
fEngineControl->fDriverNum++;
fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
SetupDriverSync(fClientControl.fRefNum, false);
return 0;
@@ -100,6 +101,7 @@ int JackDriver::Open (bool capturing,

fClientControl.fRefNum = refnum;
fClientControl.fActive = true;
fEngineControl->fDriverNum++;
fCaptureLatency = capture_latency;
fPlaybackLatency = playback_latency;

@@ -113,7 +115,6 @@ int JackDriver::Open (bool capturing,
if (!fEngineControl->fTimeOut)
fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);

//fGraphManager->SetBufferSize(fEngineControl->fBufferSize);
fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
SetupDriverSync(fClientControl.fRefNum, false);
return 0;
@@ -142,6 +143,7 @@ int JackDriver::Open(jack_nframes_t buffer_size,

fClientControl.fRefNum = refnum;
fClientControl.fActive = true;
fEngineControl->fDriverNum++;
fEngineControl->fBufferSize = buffer_size;
fEngineControl->fSampleRate = samplerate;
fCaptureLatency = capture_latency;
@@ -168,6 +170,7 @@ int JackDriver::Close()
jack_log("JackDriver::Close");
fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
fClientControl.fActive = false;
fEngineControl->fDriverNum--;
return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
}



+ 6
- 0
common/JackDriver.h View File

@@ -93,6 +93,7 @@ class SERVER_EXPORT JackDriverInterface
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;
@@ -148,8 +149,13 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
void SetMaster(bool onoff);
bool GetMaster();
void AddSlave(JackDriverInterface* slave);
void RemoveSlave(JackDriverInterface* slave);
std::list<JackDriverInterface*> GetSlaves()
{
return fSlaveList;
}
int ProcessSlaves();
virtual int Open();


+ 5
- 3
common/JackEngine.cpp View File

@@ -27,6 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackInternalClient.h"
#include "JackEngineControl.h"
#include "JackClientControl.h"
#include "JackServerGlobals.h"
#include "JackGlobals.h"
#include "JackChannel.h"
#include "JackError.h"
@@ -71,7 +72,7 @@ int JackEngine::Close()
fChannel.Close();

// Close remaining clients (RT is stopped)
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
if (JackLoadableInternalClient* loadable_client = dynamic_cast<JackLoadableInternalClient*>(fClientTable[i])) {
jack_log("JackEngine::Close loadable client = %s", loadable_client->GetClientControl()->fName);
loadable_client->Close();
@@ -110,7 +111,7 @@ void JackEngine::ReleaseRefnum(int ref)

if (fEngineControl->fTemporary) {
int i;
for (i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
if (fClientTable[i])
break;
}
@@ -180,7 +181,7 @@ correctly mixed in the time window: callbackUsecs <==> Read <==> Write.

void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions de fin
{
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = fEngineControl->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client && client->GetClientControl()->fActive) {
JackClientTiming* timing = fGraphManager->GetClientTiming(i);
@@ -236,6 +237,7 @@ void JackEngine::NotifyClients(int event, int sync, int value1, int value2)

int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* name, int refnum)
{
jack_log("JackEngine::NotifyAddClient: name = %s", name);
// Notify existing clients of the new client and new client of existing clients.
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* old_client = fClientTable[i];


+ 1
- 1
common/JackEngineControl.cpp View File

@@ -44,7 +44,7 @@ void JackEngineControl::CalcCPULoad(JackClientInterface** table,
// In Asynchronous mode, last cycle end is the max of client end dates
if (!fSyncMode) {
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
JackClientTiming* timing = manager->GetClientTiming(i);
if (client && client->GetClientControl()->fActive && timing->fStatus == Finished)


+ 6
- 2
common/JackEngineControl.h View File

@@ -63,6 +63,8 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
int fMaxClientPriority;
char fServerName[64];
JackTransportEngine fTransport;
jack_timer_type_t fClockSource;
int fDriverNum;
bool fVerbose;

// CPU Load
@@ -88,7 +90,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
JackEngineProfiling fProfiler;
#endif

JackEngineControl(bool sync, bool temporary, long timeout, bool rt, long priority, bool verbose, const char* server_name)
JackEngineControl(bool sync, bool temporary, long timeout, bool rt, long priority, bool verbose, jack_timer_type_t clock, const char* server_name)
{
fBufferSize = 512;
fSampleRate = 48000;
@@ -113,7 +115,9 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
fConstraint = 0;
fMaxDelayedUsecs = 0.f;
fXrunDelayedUsecs = 0.f;
}
fClockSource = clock;
fDriverNum = 0;
}
~JackEngineControl()
{}


+ 3
- 1
common/JackEngineProfiling.cpp View File

@@ -20,7 +20,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackEngineProfiling.h"
#include "JackGraphManager.h"
#include "JackClientControl.h"
#include "JackEngineControl.h"
#include "JackClientInterface.h"
#include "JackGlobals.h"
#include "JackTime.h"

namespace Jack
@@ -312,7 +314,7 @@ void JackEngineProfiling::Profile(JackClientInterface** table,
fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end;
fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle;

for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
JackClientTiming* timing = manager->GetClientTiming(i);
if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {


+ 1
- 0
common/JackLibClient.cpp View File

@@ -115,6 +115,7 @@ int JackLibClient::Open(const char* server_name, const char* name, jack_options_
JackGlobals::fClientTable[GetClientControl()->fRefNum] = this;
JackGlobals::fServerRunning = true;
SetClockSource(GetEngineControl()->fClockSource);
jack_log("JackLibClient::Open name = %s refnum = %ld", name_res, GetClientControl()->fRefNum);
return 0;



+ 61
- 14
common/JackServer.cpp View File

@@ -22,6 +22,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackServerGlobals.h"
#include "JackTime.h"
#include "JackFreewheelDriver.h"
#include "JackLoopbackDriver.h"
#include "JackDummyDriver.h"
#include "JackThreadedDriver.h"
#include "JackGlobals.h"
#include "JackLockedEngine.h"
@@ -37,7 +39,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{

JackServer::JackServer(bool sync, bool temporary, long timeout, bool rt, long priority, long loopback, bool verbose, const char* server_name)
JackServer::JackServer(bool sync, bool temporary, long timeout, bool rt, long priority, long loopback, bool verbose, jack_timer_type_t clock, const char* server_name)
{
if (rt) {
jack_info("JACK server starting in realtime mode with priority %ld", priority);
@@ -46,11 +48,13 @@ JackServer::JackServer(bool sync, bool temporary, long timeout, bool rt, long pr
}

fGraphManager = new JackGraphManager();
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, server_name);
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name);
fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl);
fFreewheelDriver = new JackThreadedDriver(new JackFreewheelDriver(fEngine, GetSynchroTable()));
fDriverInfo = new JackDriverInfo();
fAudioDriver = NULL;
fFreewheel = false;
fLoopback = loopback;
JackServerGlobals::fInstance = this; // Unique instance
JackServerGlobals::fUserCount = 1; // One user
jack_verbose = verbose;
@@ -60,6 +64,7 @@ JackServer::~JackServer()
{
delete fGraphManager;
delete fAudioDriver;
delete fDriverInfo;
delete fFreewheelDriver;
delete fEngine;
delete fEngineControl;
@@ -80,7 +85,7 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
goto fail_close2;
}

if ((fAudioDriver = fDriverInfo.Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) {
if ((fAudioDriver = fDriverInfo->Open(driver_desc, fEngine, GetSynchroTable(), driver_params)) == NULL) {
jack_error("Cannot initialize driver");
goto fail_close3;
}
@@ -89,18 +94,19 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
jack_error("Cannot open driver");
goto fail_close4;
}
if (fAudioDriver->Attach() != 0) {
jack_error("Cannot attach audio driver");
goto fail_close5;
}
fFreewheelDriver->SetMaster(false);
fAudioDriver->SetMaster(true);
fAudioDriver->AddSlave(fFreewheelDriver); // After ???
InitTime();
SetClockSource(fEngineControl->fClockSource);
return 0;
fail_close5:
fFreewheelDriver->Close();

@@ -287,23 +293,64 @@ void JackServer::ClientKill(int refnum)
JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params)
{
JackDriverInfo* info = new JackDriverInfo();
JackDriverClientInterface* backend = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
if (backend == NULL) {
JackDriverClientInterface* slave = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
if (slave == NULL) {
delete info;
return NULL;
} else {
backend->Attach();
fAudioDriver->AddSlave(backend);
slave->Attach();
fAudioDriver->AddSlave(slave);
return info;
}
}

void JackServer::RemoveSlave(JackDriverInfo* info)
{
JackDriverClientInterface* backend = info->GetBackend();
fAudioDriver->RemoveSlave(info->GetBackend());
backend->Detach();
backend->Close();
JackDriverClientInterface* slave = info->GetBackend();
fAudioDriver->RemoveSlave(slave);
slave->Detach();
slave->Close();
}

int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params)
{
/// Remove current master
fAudioDriver->Stop();
fAudioDriver->Detach();
fAudioDriver->Close();
// Open new master
JackDriverInfo* info = new JackDriverInfo();
JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params);
if (master == NULL || info == NULL) {
delete info;
delete master;
return -1;
} else {
// Get slaves list
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves();
std::list<JackDriverInterface*>::const_iterator it;
// Move slaves in new master
for (it = slave_list.begin(); it != slave_list.end(); it++) {
JackDriverInterface* slave = *it;
master->AddSlave(slave);
}
// Delete old master
delete fAudioDriver;
delete fDriverInfo;
// Activate master
fAudioDriver = master;
fDriverInfo = info;
fEngineControl->InitFrameTime();
fAudioDriver->Attach();
fAudioDriver->SetMaster(true);
return fAudioDriver->Start();
}
}

//----------------------


+ 5
- 3
common/JackServer.h View File

@@ -47,7 +47,7 @@ class SERVER_EXPORT JackServer

private:

JackDriverInfo fDriverInfo;
JackDriverInfo* fDriverInfo;
JackDriverClientInterface* fAudioDriver;
JackDriverClientInterface* fFreewheelDriver;
JackLockedEngine* fEngine;
@@ -57,12 +57,13 @@ class SERVER_EXPORT JackServer
JackConnectionManager fConnectionState;
JackSynchro fSynchroTable[CLIENT_NUM];
bool fFreewheel;
long fLoopback;
int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int* status);

public:

JackServer(bool sync, bool temporary, long timeout, bool rt, long priority, long loopback, bool verbose, const char* server_name);
JackServer(bool sync, bool temporary, long timeout, bool rt, long priority, long loopback, bool verbose, jack_timer_type_t clock, const char* server_name);
~JackServer();

int Open(jack_driver_desc_t* driver_desc, JSList* driver_params);
@@ -88,7 +89,8 @@ class SERVER_EXPORT JackServer
// Backend management
JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params);
void RemoveSlave(JackDriverInfo* info);

int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params);
// Object access
JackLockedEngine* GetEngine();
JackEngineControl* GetEngineControl();


+ 19
- 4
common/JackServerGlobals.cpp View File

@@ -40,10 +40,11 @@ int JackServerGlobals::Start(const char* server_name,
int rt,
int priority,
int loopback,
int verbose)
int verbose,
jack_timer_type_t clock)
{
jack_log("Jackdmp: sync = %ld timeout = %ld rt = %ld priority = %ld verbose = %ld ", sync, time_out_ms, rt, priority, verbose);
new JackServer(sync, temporary, time_out_ms, rt, priority, loopback, verbose, server_name); // Will setup fInstance and fUserCount globals
new JackServer(sync, temporary, time_out_ms, rt, priority, loopback, verbose, clock, server_name); // Will setup fInstance and fUserCount globals
int res = fInstance->Open(driver_desc, driver_params);
return (res < 0) ? res : fInstance->Start();
}
@@ -92,6 +93,7 @@ bool JackServerGlobals::Init()
char buffer[255];
int argc = 0;
char* argv[32];
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK;
// First user starts the server
if (fUserCount++ == 0) {
@@ -99,8 +101,9 @@ bool JackServerGlobals::Init()
jack_log("JackServerGlobals Init");

jack_driver_desc_t* driver_desc;
const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:";
const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:c:";
static struct option long_options[] = {
{ "clock-source", 1, 0, 'c' },
{ "driver", 1, 0, 'd' },
{ "verbose", 0, 0, 'v' },
{ "help", 0, 0, 'h' },
@@ -155,6 +158,18 @@ bool JackServerGlobals::Init()
(opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) {

switch (opt) {
case 'c':
if (tolower (optarg[0]) == 'h') {
clock_source = JACK_TIMER_HPET;
} else if (tolower (optarg[0]) == 'c') {
clock_source = JACK_TIMER_CYCLE_COUNTER;
} else if (tolower (optarg[0]) == 's') {
clock_source = JACK_TIMER_SYSTEM_CLOCK;
} else {
jack_error("unknown option character %c", optopt);
}
break;

case 'd':
seen_driver = 1;
@@ -281,7 +296,7 @@ bool JackServerGlobals::Init()
free(argv[i]);
}

int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, loopback, verbose_aux);
int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, loopback, verbose_aux, clock_source);
if (res < 0) {
jack_error("Cannot start server... exit");
Delete();


+ 4
- 3
common/JackServerGlobals.h View File

@@ -22,8 +22,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "driver_interface.h"
#include "JackDriverLoader.h"
#include "JackCompilerDeps.h"
#include "JackServer.h"
#include <assert.h>

namespace Jack
{
@@ -44,7 +44,7 @@ struct SERVER_EXPORT JackServerGlobals

static bool Init();
static void Destroy();
static int Start(const char* server_name,
static int Start (const char* server_name,
jack_driver_desc_t* driver_desc,
JSList* driver_params,
int sync,
@@ -53,7 +53,8 @@ struct SERVER_EXPORT JackServerGlobals
int rt,
int priority,
int loopback,
int verbose);
int verbose,
jack_timer_type_t clock);
static void Stop();
static void Delete();
};


+ 5
- 0
common/JackThreadedDriver.cpp View File

@@ -132,6 +132,11 @@ int JackThreadedDriver::ProcessSlaves()
return fDriver->ProcessSlaves();
}

std::list<JackDriverInterface*> JackThreadedDriver::GetSlaves()
{
return fDriver->GetSlaves();
}

int JackThreadedDriver::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
{
return fDriver->ClientNotify(refnum, name, notify, sync, value1, value2);


+ 1
- 0
common/JackThreadedDriver.h View File

@@ -91,6 +91,7 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi
virtual bool GetMaster();
virtual void AddSlave(JackDriverInterface* slave);
virtual void RemoveSlave(JackDriverInterface* slave);
virtual std::list<JackDriverInterface*> GetSlaves();
virtual int ProcessSlaves();
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);


+ 6
- 3
common/JackTime.h View File

@@ -23,15 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "types.h"
#include "JackCompilerDeps.h"
#include "JackTypes.h"

#ifdef __cplusplus
extern "C"
{
#endif

SERVER_EXPORT void InitTime();
SERVER_EXPORT jack_time_t GetMicroSeconds();
SERVER_EXPORT void JackSleep(long usec);
SERVER_EXPORT void InitTime();
SERVER_EXPORT jack_time_t GetMicroSeconds(void);
SERVER_EXPORT void JackSleep(long usec);
SERVER_EXPORT void SetClockSource(jack_timer_type_t source);
SERVER_EXPORT const char* ClockSourceName(jack_timer_type_t source);

#ifdef __cplusplus
}


+ 6
- 4
common/JackTransportEngine.cpp View File

@@ -21,6 +21,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackTransportEngine.h"
#include "JackClientInterface.h"
#include "JackClientControl.h"
#include "JackEngineControl.h"
#include "JackGlobals.h"
#include "JackError.h"
#include "JackTime.h"
#include <assert.h>
@@ -89,7 +91,7 @@ int JackTransportEngine::SetTimebaseMaster(int refnum, bool conditionnal)
// RT
bool JackTransportEngine::CheckAllRolling(JackClientInterface** table)
{
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
if (client && client->GetClientControl()->fTransportState != JackTransportRolling) {
jack_log("CheckAllRolling ref = %ld is not rolling", i);
@@ -103,7 +105,7 @@ bool JackTransportEngine::CheckAllRolling(JackClientInterface** table)
// RT
void JackTransportEngine::MakeAllStartingLocating(JackClientInterface** table)
{
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
if (client) {
JackClientControl* control = client->GetClientControl();
@@ -119,7 +121,7 @@ void JackTransportEngine::MakeAllStartingLocating(JackClientInterface** table)
// RT
void JackTransportEngine::MakeAllStopping(JackClientInterface** table)
{
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
if (client) {
JackClientControl* control = client->GetClientControl();
@@ -134,7 +136,7 @@ void JackTransportEngine::MakeAllStopping(JackClientInterface** table)
// RT
void JackTransportEngine::MakeAllLocating(JackClientInterface** table)
{
for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) {
for (int i = GetEngineControl()->fDriverNum; i < CLIENT_NUM; i++) {
JackClientInterface* client = table[i];
if (client) {
JackClientControl* control = client->GetClientControl();


+ 7
- 4
common/JackTypes.h View File

@@ -21,6 +21,8 @@
#ifndef __JackTypes__
#define __JackTypes__

#include "JackCompilerDeps.h"

typedef unsigned short UInt16;
#if __LP64__
typedef unsigned int UInt32;
@@ -34,8 +36,11 @@ typedef signed long SInt32;

typedef uint16_t jack_int_t; // Internal type for ports and refnum

namespace Jack
{
typedef enum {
JACK_TIMER_SYSTEM_CLOCK,
JACK_TIMER_CYCLE_COUNTER,
JACK_TIMER_HPET,
} jack_timer_type_t;

typedef enum {
NotTriggered,
@@ -44,6 +49,4 @@ typedef enum {
Finished,
} jack_client_state_t;

}

#endif

+ 35
- 2
common/Jackdmp.cpp View File

@@ -97,6 +97,9 @@ static void usage(FILE* file)
" [ --timeout OR -t client-timeout-in-msecs ]\n"
" [ --midi OR -X midi-driver ]\n"
" [ --verbose OR -v ]\n"
#ifdef __linux__
" [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
#endif
" [ --replace-registry OR -r ]\n"
" [ --silent OR -s ]\n"
" [ --sync OR -S ]\n"
@@ -156,8 +159,17 @@ int main(int argc, char* argv[])
const char* server_name = "default";
jackctl_driver_t * audio_driver_ctl;
jackctl_driver_t * midi_driver_ctl;
#ifdef __linux__
const char *options = "-ad:X:P:uvrshVRL:STFl:t:mn:p:c:";
#else
const char *options = "-ad:X:P:uvrshVRL:STFl:t:mn:p:";
#endif
struct option long_options[] = {
#ifdef __linux__
{ "clock-source", 1, 0, 'c' },
#endif
{ "audio-driver", 1, 0, 'd' },
{ "midi-driver", 1, 0, 'X' },
{ "verbose", 0, 0, 'v' },
@@ -177,6 +189,7 @@ int main(int argc, char* argv[])
{ "sync", 0, 0, 'S' },
{ 0, 0, 0, 0 }
};

int i,opt = 0;
int option_index = 0;
bool seen_audio_driver = false;
@@ -204,13 +217,33 @@ int main(int argc, char* argv[])
}

server_parameters = jackctl_server_get_parameters(server_ctl);

opterr = 0;
while (!seen_audio_driver &&
(opt = getopt_long(argc, argv, options,
long_options, &option_index)) != EOF) {
switch (opt) {

#ifdef __linux__
case 'c':
param = jackctl_get_parameter(server_parameters, "clock-source");
if (param != NULL) {
if (tolower (optarg[0]) == 'h') {
value.ui = JACK_TIMER_HPET;
jackctl_parameter_set_value(param, &value);
} else if (tolower (optarg[0]) == 'c') {
value.ui = JACK_TIMER_CYCLE_COUNTER;
jackctl_parameter_set_value(param, &value);
} else if (tolower (optarg[0]) == 's') {
value.ui = JACK_TIMER_SYSTEM_CLOCK;
jackctl_parameter_set_value(param, &value);
} else {
usage(stdout);
goto fail_free;
}
}
break;
#endif

case 'd':
seen_audio_driver = true;
audio_driver_name = optarg;
@@ -382,7 +415,7 @@ int main(int argc, char* argv[])
goto fail_free;
}

jackctl_server_load_slave(server_ctl, midi_driver_ctl);
jackctl_server_add_slave(server_ctl, midi_driver_ctl);
}

notify_server_start(server_name);


+ 31
- 2
common/jack/control.h View File

@@ -510,13 +510,42 @@ jack_log(

/* @} */

/**
* Call this function to add a slave in the driver slave list.
*
* @param server server object handle
* @param driver driver to add in the driver slave list.
*
* @return success status: true - success, false - fail
*/
bool
jackctl_server_add_slave(jackctl_server_t * server,
jackctl_driver_t * driver);

/**
* Call this function to remove a slave from the driver slave list.
*
* @param server server object handle
* @param driver driver to remove from the driver slave list.
*
* @return success status: true - success, false - fail
*/
bool
jackctl_server_load_slave(jackctl_server_t * server,
jackctl_server_remove_slave(jackctl_server_t * server,
jackctl_driver_t * driver);

/**
* Call this function to switch master driver.
*
* @param server server object handle
* @param driver driver to switch to
*
* @return success status: true - success, false - fail
*/
bool
jackctl_server_unload_slave(jackctl_server_t * server,
jackctl_server_switch_master(jackctl_server_t * server,
jackctl_driver_t * driver);

#if 0
{ /* Adjust editor indent */


+ 1
- 0
common/wscript View File

@@ -131,6 +131,7 @@ def build(bld):
'JackNetTool.cpp',
'JackNetInterface.cpp',
'JackArgParser.cpp',
'JackDummyDriver.cpp',
]

if bld.env['IS_LINUX']:


+ 3
- 1
dbus/audio_reserve.c View File

@@ -67,7 +67,7 @@ SERVER_EXPORT void* audio_acquire(int num)
NULL,
&error)) < 0) {

jack_error ("Failed to acquire device: %s\n", error.message ? error.message : strerror(-e));
jack_error("Failed to acquire device name : %s error : %s", audio_name, (error.message ? error.message : strerror(-e)));
return NULL;
}

@@ -89,5 +89,7 @@ SERVER_EXPORT void audio_release(void* dev)
if (device) {
jack_info("Release audio card");
rd_release(device);
} else {
jack_info("No audio card to release...");
}
}

+ 16
- 0
dbus/controller.c View File

@@ -263,6 +263,22 @@ jack_controller_stop_server(
return TRUE;
}

bool
jack_controller_switch_master(
struct jack_controller * controller_ptr,
void *dbus_call_context_ptr)
{
if (!jackctl_server_switch_master(
controller_ptr->server,
controller_ptr->driver))
{
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
return FALSE;
}

return TRUE;
}

void *
jack_controller_create(
DBusConnection *connection)


+ 15
- 0
dbus/controller_iface_control.c View File

@@ -105,6 +105,17 @@ jack_control_run_method(
jack_controller_control_send_signal_server_stopped();
}
}
else if (strcmp (call->method_name, "SwitchMaster") == 0)
{
if (!jack_controller_switch_master(controller_ptr, call))
{
jack_error ("Failed to switch master");
}
else
{
jack_controller_control_send_signal_server_stopped();
}
}
else if (strcmp (call->method_name, "GetLoad") == 0)
{
if (!controller_ptr->started)
@@ -252,6 +263,9 @@ JACK_DBUS_METHOD_ARGUMENTS_END
JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer)
JACK_DBUS_METHOD_ARGUMENTS_END

JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SwitchMaster)
JACK_DBUS_METHOD_ARGUMENTS_END

JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad)
JACK_DBUS_METHOD_ARGUMENT("load", "d", true)
JACK_DBUS_METHOD_ARGUMENTS_END
@@ -295,6 +309,7 @@ JACK_DBUS_METHODS_BEGIN
JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL)
JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL)
JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL)
JACK_DBUS_METHOD_DESCRIBE(SwitchMaster, NULL)
JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL)
JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL)
JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL)


+ 5
- 0
dbus/controller_internal.h View File

@@ -81,6 +81,11 @@ jack_controller_stop_server(
struct jack_controller *controller_ptr,
void *dbus_call_context_ptr);

bool
jack_controller_switch_master(
struct jack_controller *controller_ptr,
void *dbus_call_context_ptr);

bool
jack_controller_select_driver(
struct jack_controller *controller_ptr,


+ 4
- 0
example-clients/jack_control View File

@@ -109,6 +109,7 @@ def main():
print " status - check whether jack server is started, return value is 0 if runing and 1 otherwise"
print " start - start jack server if not currently started"
print " stop - stop jack server if currenly started"
print " sm - switch master to currently selected driver"
print " dl - get list of available drivers"
print " dg - get currently selected driver"
print " ds <driver> - select driver"
@@ -155,6 +156,9 @@ def main():
elif arg == 'stop':
print "--- stop"
control_iface.StopServer()
elif arg == 'sm':
print "--- switch master driver"
control_iface.SwitchMaster()
elif arg == 'ism':
if control_iface.IsManuallyActivated():
print "Manually activated"


+ 46
- 1
example-clients/server_control.cpp View File

@@ -53,6 +53,24 @@ static jackctl_internal_t * jackctl_server_get_internal(jackctl_server_t *server
return NULL;
}

static jackctl_parameter_t *
jackctl_get_parameter(
const JSList * parameters_list,
const char * parameter_name)
{
while (parameters_list)
{
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
{
return (jackctl_parameter_t *)parameters_list->data;
}

parameters_list = jack_slist_next(parameters_list);
}

return NULL;
}

static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type)
{
switch (type) {
@@ -152,6 +170,16 @@ int main(int argc, char *argv[])
server = jackctl_server_create();
parameters = jackctl_server_get_parameters(server);
/*
jackctl_parameter_t* param;
union jackctl_parameter_value value;
param = jackctl_get_parameter(parameters, "verbose");
if (param != NULL) {
value.b = true;
jackctl_parameter_set_value(param, &value);
}
*/
printf("\n========================== \n");
printf("List of server parameters \n");
printf("========================== \n");
@@ -182,7 +210,24 @@ int main(int argc, char *argv[])
jackctl_server_start(server, jackctl_server_get_driver(server, driver_name));
jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name));
/*
// Switch master test
jackctl_driver_t* master;
usleep(5000000);
printf("jackctl_server_load_master\n");
master = jackctl_server_get_driver(server, "coreaudio");
jackctl_server_switch_master(server, master);
usleep(5000000);
printf("jackctl_server_load_master\n");
master = jackctl_server_get_driver(server, "dummy");
jackctl_server_switch_master(server, master);
*/
signals = jackctl_setup_signals(0);
jackctl_wait_signals(signals);


+ 227
- 62
linux/JackLinuxTime.c View File

@@ -18,84 +18,249 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#include "JackConstants.h"
#include "JackTime.h"
#include "JackTypes.h"
#include "JackError.h"
#include "cycles.h"

#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

SERVER_EXPORT void JackSleep(long usec)
static jack_time_t __jack_cpu_mhz = 0;
jack_time_t (*_jack_get_microseconds)(void) = 0;

#if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__))
#define HPET_SUPPORT
#define HPET_MMAP_SIZE 1024
#define HPET_CAPS 0x000
#define HPET_PERIOD 0x004
#define HPET_COUNTER 0x0f0
#define HPET_CAPS_COUNTER_64BIT (1 << 13)
#if defined(__x86_64__)
typedef uint64_t hpet_counter_t;
#else
typedef uint32_t hpet_counter_t;
#endif
static int hpet_fd;
static unsigned char *hpet_ptr;
static uint32_t hpet_period; /* period length in femto secs */
static uint64_t hpet_offset = 0;
static uint64_t hpet_wrap;
static hpet_counter_t hpet_previous = 0;
#endif /* defined(__gnu_linux__) && (__i386__ || __x86_64__) */

#ifdef HPET_SUPPORT

static int jack_hpet_init ()
{
usleep(usec);
uint32_t hpet_caps;

hpet_fd = open("/dev/hpet", O_RDONLY);
if (hpet_fd < 0) {
jack_error ("This system has no accessible HPET device (%s)", strerror (errno));
return -1;
}

hpet_ptr = (unsigned char *) mmap(NULL, HPET_MMAP_SIZE,
PROT_READ, MAP_SHARED, hpet_fd, 0);
if (hpet_ptr == MAP_FAILED) {
jack_error ("This system has no mappable HPET device (%s)", strerror (errno));
close (hpet_fd);
return -1;
}

/* this assumes period to be constant. if needed,
it can be moved to the clock access function
*/
hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD));
hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS));
hpet_wrap = ((hpet_caps & HPET_CAPS_COUNTER_64BIT) &&
(sizeof(hpet_counter_t) == sizeof(uint64_t))) ?
0 : ((uint64_t) 1 << 32);

return 0;
}

static jack_time_t jack_get_microseconds_from_hpet (void)
{
hpet_counter_t hpet_counter;
long double hpet_time;

hpet_counter = *((hpet_counter_t *) (hpet_ptr + HPET_COUNTER));
if (hpet_counter < hpet_previous)
hpet_offset += hpet_wrap;
hpet_previous = hpet_counter;
hpet_time = (long double) (hpet_offset + hpet_counter) *
(long double) hpet_period * (long double) 1e-9;
return ((jack_time_t) (hpet_time + 0.5));
}

#ifdef GETCYCLE_TIME
#else

static int jack_hpet_init ()
{
jack_error ("This version of JACK or this computer does not have HPET support.\n"
"Please choose a different clock source.");
return -1;
}

static jack_time_t jack_get_microseconds_from_hpet (void)
{
/* never called */
return 0;
}

#endif /* HPET_SUPPORT */

static jack_time_t jack_get_microseconds_from_cycles (void) {
return get_cycles() / __jack_cpu_mhz;
}

#include <stdio.h>
#include "cycles.h"
/*
* This is another kludge. It looks CPU-dependent, but actually it
* reflects the lack of standards for the Linux kernel formatting of
* /proc/cpuinfo.
*/

static jack_time_t __jack_cpu_mhz;
static jack_time_t jack_get_mhz (void)
{
FILE *f = fopen("/proc/cpuinfo", "r");
if (f == 0)
{
perror("can't open /proc/cpuinfo\n");
exit(1);
}

static inline jack_time_t GetMhz(void)
for ( ; ; )
{
FILE *f = fopen("/proc/cpuinfo", "r");
if (f == 0) {
perror("can't open /proc/cpuinfo\n");
jack_time_t mhz;
int ret;
char buf[1000];

if (fgets(buf, sizeof(buf), f) == NULL) {
jack_error ("FATAL: cannot locate cpu MHz in "
"/proc/cpuinfo\n");
exit(1);
}
for (;;) {
jack_time_t mhz;
int ret;
char buf[1000];
if (fgets(buf, sizeof(buf), f) == NULL) {
jack_error("FATAL: cannot locate cpu MHz in /proc/cpuinfo\n");
exit(1);
}
#if defined(__powerpc__)
ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz);
#elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \
defined(__x86_64__)
ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz);
#elif defined( __sparc__ )
ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz);
#elif defined( __mc68000__ )
ret = sscanf(buf, "Clocking: %" SCNu64, &mhz);
#elif defined( __s390__ )
ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz);
#else /* MIPS, ARM, alpha */
ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz);
#endif
if (ret == 1) {
fclose(f);
return (jack_time_t)mhz;
}

#if defined(__powerpc__)
ret = sscanf(buf, "clock\t: %" SCNu64 "MHz", &mhz);
#elif defined( __i386__ ) || defined (__hppa__) || defined (__ia64__) || \
defined(__x86_64__)
ret = sscanf(buf, "cpu MHz : %" SCNu64, &mhz);
#elif defined( __sparc__ )
ret = sscanf(buf, "Cpu0Bogo : %" SCNu64, &mhz);
#elif defined( __mc68000__ )
ret = sscanf(buf, "Clocking: %" SCNu64, &mhz);
#elif defined( __s390__ )
ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz);
#else /* MIPS, ARM, alpha */
ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz);
#endif

if (ret == 1)
{
fclose(f);
return (jack_time_t)mhz;
}
}
}

#define HAVE_CLOCK_GETTIME 1

#ifndef HAVE_CLOCK_GETTIME

static jack_time_t jack_get_microseconds_from_system (void)
{
jack_time_t jackTime;
struct timeval tv;

gettimeofday (&tv, NULL);
jackTime = (jack_time_t) tv.tv_sec * 1000000 + (jack_time_t) tv.tv_usec;
return jackTime;
}

SERVER_EXPORT void InitTime()
{
__jack_cpu_mhz = GetMhz();
}
SERVER_EXPORT jack_time_t GetMicroSeconds(void)
{
return get_cycles() / __jack_cpu_mhz;
}
#else

#include <time.h>
SERVER_EXPORT void InitTime()
{}
SERVER_EXPORT jack_time_t GetMicroSeconds(void)
static jack_time_t jack_get_microseconds_from_system (void)
{
jack_time_t jackTime;
struct timespec time;

clock_gettime(CLOCK_MONOTONIC, &time);
jackTime = (jack_time_t) time.tv_sec * 1e6 +
(jack_time_t) time.tv_nsec / 1e3;
return jackTime;
}

#endif /* HAVE_CLOCK_GETTIME */


SERVER_EXPORT void JackSleep(long usec)
{
usleep(usec);
}

SERVER_EXPORT void InitTime()
{
__jack_cpu_mhz = jack_get_mhz ();
}

SERVER_EXPORT void SetClockSource(jack_timer_type_t source)
{
jack_log("Clock source : %s", ClockSourceName(source));

switch (source)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (jack_time_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
case JACK_TIMER_CYCLE_COUNTER:
_jack_get_microseconds = jack_get_microseconds_from_cycles;
break;

case JACK_TIMER_HPET:
if (jack_hpet_init () == 0) {
_jack_get_microseconds = jack_get_microseconds_from_hpet;
} else {
_jack_get_microseconds = jack_get_microseconds_from_system;
}
break;

case JACK_TIMER_SYSTEM_CLOCK:
default:
_jack_get_microseconds = jack_get_microseconds_from_system;
break;
}
#endif
}

SERVER_EXPORT const char* ClockSourceName(jack_timer_type_t source)
{
switch (source) {
case JACK_TIMER_CYCLE_COUNTER:
return "cycle counter";
case JACK_TIMER_HPET:
return "hpet";
case JACK_TIMER_SYSTEM_CLOCK:
#ifdef HAVE_CLOCK_GETTIME
return "system clock via clock_gettime";
#else
return "system clock via gettimeofday";
#endif
}

/* what is wrong with gcc ? */
return "unknown";
}

SERVER_EXPORT jack_time_t GetMicroSeconds()
{
return _jack_get_microseconds();
}

+ 12
- 10
linux/alsa/JackAlsaDriver.cpp View File

@@ -51,6 +51,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "audio_reserve.h"

//#define DEBUG_WAKEUP 1

namespace Jack
{

@@ -1346,6 +1348,9 @@ JackAlsaDriver::alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *stat
/* if POLLIN was the only bit set, we're OK */

*status = 0;
if (driver->pfd[nfds-1].revents == POLLIN) {
jack_error("driver->pfd[nfds-1].revents == POLLIN");
}
return (driver->pfd[nfds-1].revents == POLLIN) ? 0 : -1;
}

@@ -2191,21 +2196,18 @@ int JackAlsaDriver::Open(jack_nframes_t nframes,
if (audio_reservation_init() < 0) {
jack_error("Audio device reservation service not available....");
} else if (strcmp(capture_driver_name, playback_driver_name) == 0) { // Same device for input and output
fReservedCaptureDevice = audio_acquire(card_to_num(capture_driver_name));
if (fReservedCaptureDevice == NULL) {
jack_error("Error audio device %s not available...", capture_driver_name);
return -1;
fReservedCaptureDevice = audio_acquire(card_to_num(capture_driver_name));
if (fReservedCaptureDevice == NULL) {
jack_error("Error audio device %s cannot be acquired, trying to open it anyway...", capture_driver_name);
}
} else {
fReservedCaptureDevice = audio_acquire(card_to_num(capture_driver_name));
if (fReservedCaptureDevice == NULL) {
jack_error("Error capture audio device %s not available...", capture_driver_name);
return -1;
}
jack_error("Error capture audio device %s cannot be acquired, trying to open it anyway...", capture_driver_name);
}
fReservedPlaybackDevice = audio_acquire(card_to_num(playback_driver_name));
if (fReservedPlaybackDevice == NULL) {
jack_error("Error playback audio device %s not available...", playback_driver_name);
return -1;
jack_error("Error playback audio device %s cannot be acquired, trying to open it anyway...", playback_driver_name);
}
}
#endif
@@ -2277,7 +2279,7 @@ int JackAlsaDriver::Read()
/* we detected an xrun and restarted: notify
* clients about the delay.
*/
jack_log("ALSA XRun");
jack_log("ALSA XRun wait_status = %d", wait_status);
NotifyXRun(fBeginDateUst, fDelayedUsecs);
return -1;
}


+ 14
- 0
linux/cycles.h View File

@@ -39,6 +39,20 @@

#ifdef __linux__

#ifdef __x86_64__

typedef unsigned long cycles_t;
extern cycles_t cacheflush_time;

static inline unsigned long get_cycles(void)
{
unsigned int hi, lo;
__asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
return (((unsigned long)hi)<<32) | ((unsigned long)lo);
}

#endif

#ifdef __PPC__

/* PowerPC */


+ 1
- 1
macosx/JackMacEngineRPC.cpp View File

@@ -42,7 +42,7 @@ rpc_type server_rpc_jack_client_check(mach_port_t private_port, client_name_t na

rpc_type server_rpc_jack_client_open(mach_port_t server_port, client_name_t name, int pid, mach_port_t* private_port, int* shared_engine, int* shared_client, int* shared_graph, int* result)
{
jack_log("rpc_jack_client_opne name = %s", name);
jack_log("rpc_jack_client_open name = %s", name);
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[server_port];
assert(channel);
channel->ClientOpen((char*)name, pid, private_port, shared_engine, shared_client, shared_graph, result);


+ 9
- 0
macosx/JackMachTime.c View File

@@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include "JackTime.h"
#include "JackError.h"
#include "JackTypes.h"
#include <mach/mach_time.h>
#include <unistd.h>

@@ -42,3 +43,11 @@ SERVER_EXPORT jack_time_t GetMicroSeconds(void)
{
return (jack_time_t) (mach_absolute_time () * __jack_time_ratio);
}

SERVER_EXPORT void SetClockSource(jack_timer_type_t source)
{}

SERVER_EXPORT const char* ClockSourceName(jack_timer_type_t source)
{
return "";
}

+ 4
- 0
macosx/Jackdmp.xcodeproj/project.pbxproj View File

@@ -577,6 +577,8 @@
4BF284190F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; };
4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF284160F31B4BC00B05BE3 /* JackArgParser.cpp */; };
4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF284170F31B4BC00B05BE3 /* JackArgParser.h */; };
4BF2F4210F9F4DA300B3FFAD /* JackDummyDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */; };
4BF2F4220F9F4DA700B3FFAD /* JackDummyDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */; };
4BF339160F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */; };
4BF339170F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF339150F8B86DC0080FB5B /* JackCoreMidiDriver.cpp */; };
4BF339180F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */; };
@@ -5475,6 +5477,7 @@
4BECB2FB0F4451C10091B70A /* JackProcessSync.cpp in Sources */,
4BF339190F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */,
4BF339210F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */,
4BF2F4220F9F4DA700B3FFAD /* JackDummyDriver.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -5855,6 +5858,7 @@
4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */,
4BECB2F50F4451C10091B70A /* JackProcessSync.cpp in Sources */,
4BF339230F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */,
4BF2F4210F9F4DA300B3FFAD /* JackDummyDriver.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};


+ 172
- 8
macosx/coreaudio/JackCoreAudioDriver.cpp View File

@@ -157,6 +157,14 @@ error:
return err;
}

static CFStringRef GetDeviceName(AudioDeviceID id)
{
UInt32 size = sizeof(CFStringRef);
CFStringRef UIname;
OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
return (err == noErr) ? UIname : NULL;
}

OSStatus JackCoreAudioDriver::Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
@@ -434,6 +442,136 @@ JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, Ja
JackCoreAudioDriver::~JackCoreAudioDriver()
{}

OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, AudioDeviceID* outAggregateDevice)
{
OSStatus osErr = noErr;
UInt32 outSize;
Boolean outWritable;

//-----------------------
// Start to create a new aggregate by getting the base audio hardware plugin
//-----------------------

osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
if (osErr != noErr)
return osErr;

AudioValueTranslation pluginAVT;

CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
AudioObjectID pluginID;

pluginAVT.mInputData = &inBundleRef;
pluginAVT.mInputDataSize = sizeof(inBundleRef);
pluginAVT.mOutputData = &pluginID;
pluginAVT.mOutputDataSize = sizeof(pluginID);

osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
if (osErr != noErr)
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);

//-------------------------------------------------
// Create a CFMutableArray for our sub-device list
//-------------------------------------------------
CFStringRef captureDeviceUID = GetDeviceName(captureDeviceID);
CFStringRef playbackDeviceUID = GetDeviceName(playbackDeviceID);
if (captureDeviceUID == NULL || playbackDeviceUID == NULL)
return -1;
// we need to append the UID for each device to a CFMutableArray, so create one here
CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

// two sub-devices in this example, so append the sub-device's UID to the CFArray
CFArrayAppendValue(subDevicesArray, captureDeviceUID);
CFArrayAppendValue(subDevicesArray, playbackDeviceUID);

//-----------------------------------------------------------------------
// 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(pluginID, &pluginAOPA, 0, NULL, &outDataSize);
if (osErr != noErr)
return osErr;

osErr = AudioObjectGetPropertyData(pluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
if (osErr != noErr)
return osErr;

// 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;
outDataSize = sizeof(CFMutableArrayRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
if (osErr != noErr)
return osErr;

// 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;
pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
outDataSize = sizeof(CFStringRef);
osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID); // capture is master...
if (osErr != noErr)
return osErr;

// pause again to give the changes time to take effect
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);

//----------
// Clean up
//----------

// release the CF objects we have created - we don't need them any more
CFRelease(aggDeviceDict);
CFRelease(subDevicesArray);

// release the device UID
CFRelease(captureDeviceUID);
CFRelease(playbackDeviceUID);
jack_log("New aggregate device %ld", *outAggregateDevice);
return noErr;
}

int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, char* playback_driver_name)
{
capture_driver_name[0] = 0;
@@ -442,16 +580,42 @@ int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char
// Duplex
if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
jack_log("JackCoreAudioDriver::Open duplex");
if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
jack_log("Will take default in/out");
if (GetDefaultDevice(&fDeviceID) != noErr) {
jack_error("Cannot open default device");
/*
AudioDeviceID captureID, playbackID;
if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr)
return -1;
if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr)
return -1;
if (CreateAggregateDevice(captureID, playbackID, &fDeviceID) != noErr)
return -1;
*/
// 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");