jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
9.9KB

  1. /*
  2. Copyright (C) 2014 C├ędric Schieli
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  14. */
  15. #ifndef __JackProxyDriver__
  16. #define __JackProxyDriver__
  17. #include "JackTimedDriver.h"
  18. #define DEFAULT_UPSTREAM "default" /*!< Default upstream Jack server to connect to */
  19. #define DEFAULT_CLIENT_NAME "proxy" /*!< Default client name to use when connecting to upstream Jack server */
  20. #ifdef __APPLE__
  21. #define JACK_PROXY_CLIENT_LIB "libjack.0.dylib"
  22. #elif defined(WIN32)
  23. #ifdef _WIN64
  24. #define JACK_PROXY_CLIENT_LIB "libjack64.dll"
  25. #else
  26. #define JACK_PROXY_CLIENT_LIB "libjack.dll"
  27. #endif
  28. #else
  29. #define JACK_PROXY_CLIENT_LIB "libjack.so.0"
  30. #endif
  31. #define PROXY_DEF_SYMBOL(ret,name,...) ret (*name) (__VA_ARGS__)
  32. #define PROXY_LOAD_SYMBOL(ret,name,...) name = (ret (*) (__VA_ARGS__)) GetJackProc(fHandle, #name); assert(name)
  33. namespace Jack
  34. {
  35. /*! \Brief This class describes the Proxy Backend
  36. It uses plain Jack API to connect to an upstream server. The latter is
  37. either running as the same user, or is running in promiscuous mode.
  38. The main use case is the multi-user, multi-session, shared workstation:
  39. - a classic server with hw driver is launched system-wide at boot time, in
  40. promiscuous mode, optionally restricted to the audio group
  41. - in each user session, a jackdbus server is automatically started with
  42. JackProxyDriver as master driver, automatically connected to the
  43. system-wide one
  44. - optionally, each user run PulseAudio with a pulse-jack bridge
  45. */
  46. class JackProxyDriver : public JackRestarterDriver
  47. {
  48. private:
  49. char fUpstream[JACK_CLIENT_NAME_SIZE+1]; /*<! the upstream server name */
  50. char fClientName[JACK_CLIENT_NAME_SIZE+1]; /*<! client name to use when connecting */
  51. const char* fPromiscuous; /*<! if not null, group or gid to use for promiscuous mode */
  52. //jack data
  53. jack_client_t* fClient; /*<! client handle */
  54. jack_port_t** fUpstreamCapturePorts; /*<! ports registered for capture in the upstream server */
  55. jack_port_t** fUpstreamPlaybackPorts; /*<! ports registered for playback in the upstream server */
  56. int* fUpstreamCapturePortConnected; /*<! map of capture ports connected upstream, for optimization purpose */
  57. int* fUpstreamPlaybackPortConnected; /*<! map of playback ports connected upstream, for optimization purpose */
  58. bool fAutoSave; /*<! whether the local connections should be saved/restored when upstream connection is restarted */
  59. bool fAutoConnect; /*<! whether the upstream ports should be automatically connected to upstream physical ports */
  60. bool fDetectPlaybackChannels; /*<! whether the number of playback ports registered should match the number of upstream physical playback ports */
  61. bool fDetectCaptureChannels; /*<! whether the number of capture ports registered should match the number of upstream physical capture ports */
  62. bool Initialize(); /*<! establish upstream connection and register the client callbacks */
  63. int AllocPorts(); /*<! register local and upstream ports */
  64. int FreePorts(); /*<! unregister local ports */
  65. void ConnectPorts(); /*<! connect upstream ports to physical ones */
  66. int CountIO(const char*, int); /*<! get the number of upstream ports of a specific type */
  67. // client callbacks
  68. static int process_callback(jack_nframes_t, void*);
  69. static int bufsize_callback(jack_nframes_t, void*);
  70. static int srate_callback(jack_nframes_t, void*);
  71. static void connect_callback(jack_port_id_t, jack_port_id_t, int, void*);
  72. static void shutdown_callback(void*);
  73. // indirect member callbacks
  74. int bufsize_callback(jack_nframes_t);
  75. int srate_callback(jack_nframes_t);
  76. void connect_callback(jack_port_id_t, jack_port_id_t, int);
  77. JACK_HANDLE fHandle; /*<! handle to the jack client library */
  78. // map needed client library symbols as members to override those from the jackserver library
  79. PROXY_DEF_SYMBOL(jack_client_t*, jack_client_open, const char*, jack_options_t, jack_status_t*, ...);
  80. PROXY_DEF_SYMBOL(int, jack_set_process_callback, jack_client_t*, JackProcessCallback, void*);
  81. PROXY_DEF_SYMBOL(int, jack_set_buffer_size_callback, jack_client_t*, JackBufferSizeCallback, void*);
  82. PROXY_DEF_SYMBOL(int, jack_set_sample_rate_callback, jack_client_t*, JackSampleRateCallback, void*);
  83. PROXY_DEF_SYMBOL(int, jack_set_port_connect_callback, jack_client_t*, JackPortConnectCallback, void*);
  84. PROXY_DEF_SYMBOL(void, jack_on_shutdown, jack_client_t*, JackShutdownCallback, void*);
  85. PROXY_DEF_SYMBOL(jack_nframes_t, jack_get_buffer_size, jack_client_t*);
  86. PROXY_DEF_SYMBOL(jack_nframes_t, jack_get_sample_rate, jack_client_t*);
  87. PROXY_DEF_SYMBOL(int, jack_activate, jack_client_t*);
  88. PROXY_DEF_SYMBOL(int, jack_deactivate, jack_client_t*);
  89. PROXY_DEF_SYMBOL(jack_port_t*, jack_port_by_id, jack_client_t*, jack_port_id_t);
  90. PROXY_DEF_SYMBOL(int, jack_port_is_mine, const jack_client_t*, const jack_port_t*);
  91. PROXY_DEF_SYMBOL(const char**, jack_get_ports, jack_client_t*, const char*, const char*, unsigned long);
  92. PROXY_DEF_SYMBOL(void, jack_free, void*);
  93. PROXY_DEF_SYMBOL(jack_port_t*, jack_port_register, jack_client_t*, const char*, const char*, unsigned long, unsigned long);
  94. PROXY_DEF_SYMBOL(int, jack_port_unregister, jack_client_t*, jack_port_t*);
  95. PROXY_DEF_SYMBOL(void*, jack_port_get_buffer, jack_port_t*, jack_nframes_t);
  96. PROXY_DEF_SYMBOL(int, jack_connect, jack_client_t*, const char*, const char*);
  97. PROXY_DEF_SYMBOL(const char*, jack_port_name, const jack_port_t*);
  98. PROXY_DEF_SYMBOL(int, jack_client_close, jack_client_t*);
  99. /*! load the needed library symbols */
  100. void LoadSymbols()
  101. {
  102. PROXY_LOAD_SYMBOL(jack_client_t*, jack_client_open, const char*, jack_options_t, jack_status_t*, ...);
  103. PROXY_LOAD_SYMBOL(int, jack_set_process_callback, jack_client_t*, JackProcessCallback, void*);
  104. PROXY_LOAD_SYMBOL(int, jack_set_buffer_size_callback, jack_client_t*, JackBufferSizeCallback, void*);
  105. PROXY_LOAD_SYMBOL(int, jack_set_sample_rate_callback, jack_client_t*, JackSampleRateCallback, void*);
  106. PROXY_LOAD_SYMBOL(int, jack_set_port_connect_callback, jack_client_t*, JackPortConnectCallback, void*);
  107. PROXY_LOAD_SYMBOL(void, jack_on_shutdown, jack_client_t*, JackShutdownCallback, void*);
  108. PROXY_LOAD_SYMBOL(jack_nframes_t, jack_get_buffer_size, jack_client_t*);
  109. PROXY_LOAD_SYMBOL(jack_nframes_t, jack_get_sample_rate, jack_client_t*);
  110. PROXY_LOAD_SYMBOL(int, jack_activate, jack_client_t*);
  111. PROXY_LOAD_SYMBOL(int, jack_deactivate, jack_client_t*);
  112. PROXY_LOAD_SYMBOL(jack_port_t*, jack_port_by_id, jack_client_t*, jack_port_id_t);
  113. PROXY_LOAD_SYMBOL(int, jack_port_is_mine, const jack_client_t*, const jack_port_t*);
  114. PROXY_LOAD_SYMBOL(const char**, jack_get_ports, jack_client_t*, const char*, const char*, unsigned long);
  115. PROXY_LOAD_SYMBOL(void, jack_free, void*);
  116. PROXY_LOAD_SYMBOL(jack_port_t*, jack_port_register, jack_client_t*, const char*, const char*, unsigned long, unsigned long);
  117. PROXY_LOAD_SYMBOL(int, jack_port_unregister, jack_client_t*, jack_port_t*);
  118. PROXY_LOAD_SYMBOL(void*, jack_port_get_buffer, jack_port_t*, jack_nframes_t);
  119. PROXY_LOAD_SYMBOL(int, jack_connect, jack_client_t*, const char*, const char*);
  120. PROXY_LOAD_SYMBOL(const char*, jack_port_name, const jack_port_t*);
  121. PROXY_LOAD_SYMBOL(int, jack_client_close, jack_client_t*);
  122. }
  123. int LoadClientLib(); /*!< load the client library */
  124. public:
  125. JackProxyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
  126. const char* upstream, const char* promiscuous, char* client_name, bool auto_connect, bool auto_save);
  127. virtual ~JackProxyDriver();
  128. int Open(jack_nframes_t buffer_size,
  129. jack_nframes_t samplerate,
  130. bool capturing,
  131. bool playing,
  132. int inchannels,
  133. int outchannels,
  134. bool monitor,
  135. const char* capture_driver_name,
  136. const char* playback_driver_name,
  137. jack_nframes_t capture_latency,
  138. jack_nframes_t playback_latency);
  139. int Close();
  140. int Stop();
  141. int Attach();
  142. int Detach();
  143. int Read();
  144. int Write();
  145. };
  146. }
  147. #endif