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.

293 lines
10KB

  1. /*
  2. Copyright (C) 2008 Romain Moret at Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (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., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackPortAudioDevices.h"
  16. #include "JackError.h"
  17. using namespace std;
  18. PortAudioDevices::PortAudioDevices()
  19. {
  20. PaError err;
  21. PaDeviceIndex id;
  22. jack_log("Initializing PortAudio...");
  23. if ( ( err = Pa_Initialize() ) == paNoError )
  24. {
  25. fNumHostApi = Pa_GetHostApiCount();
  26. fNumDevice = Pa_GetDeviceCount();
  27. fDeviceInfo = new PaDeviceInfo*[fNumDevice];
  28. for ( id = 0; id < fNumDevice; id++ )
  29. fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id));
  30. fHostName = new string[fNumHostApi];
  31. for ( id = 0; id < fNumHostApi; id++ )
  32. fHostName[id] = string ( Pa_GetHostApiInfo(id)->name );
  33. }
  34. else
  35. jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err));
  36. }
  37. PortAudioDevices::~PortAudioDevices()
  38. {
  39. // Desactivate for now: crash the server..
  40. //Pa_Terminate();
  41. delete[] fDeviceInfo;
  42. delete[] fHostName;
  43. }
  44. PaDeviceIndex PortAudioDevices::GetNumDevice()
  45. {
  46. return fNumDevice;
  47. }
  48. PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id )
  49. {
  50. return fDeviceInfo[id];
  51. }
  52. string PortAudioDevices::GetDeviceName ( PaDeviceIndex id )
  53. {
  54. return string ( fDeviceInfo[id]->name );
  55. }
  56. string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device )
  57. {
  58. return fHostName[device->hostApi];
  59. }
  60. string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id )
  61. {
  62. return fHostName[fDeviceInfo[id]->hostApi];
  63. }
  64. string PortAudioDevices::GetFullName ( PaDeviceIndex id )
  65. {
  66. string hostname = GetHostFromDevice ( id );
  67. string devicename = GetDeviceName ( id );
  68. //some hostname are quite long...use shortcuts
  69. if ( hostname.compare ( "Windows DirectSound" ) == 0 )
  70. hostname = string ( "DirectSound" );
  71. return ( hostname + "::" + devicename );
  72. }
  73. string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename )
  74. {
  75. //some hostname are quite long...use shortcuts
  76. if ( hostname.compare ( "Windows DirectSound" ) == 0 )
  77. hostname = string ( "DirectSound" );
  78. return ( hostname + "::" + devicename );
  79. }
  80. PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id, bool isInput )
  81. {
  82. PaDeviceInfo* ret = NULL;
  83. //no driver to find
  84. if ( fullname.size() == 0 )
  85. return NULL;
  86. //first get host and device names from fullname
  87. string::size_type separator = fullname.find ( "::", 0 );
  88. if ( separator == 0 )
  89. return NULL;
  90. char* hostname = (char*)malloc(separator + 9);
  91. fill_n ( hostname, separator + 9, 0 );
  92. fullname.copy ( hostname, separator );
  93. //we need the entire hostname, replace shortcuts
  94. if ( strcmp ( hostname, "DirectSound" ) == 0 )
  95. strcpy ( hostname, "Windows DirectSound" );
  96. string devicename = fullname.substr ( separator + 2 );
  97. //then find the corresponding device
  98. for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ )
  99. {
  100. bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0);
  101. if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 )
  102. && ( GetDeviceName(dev_id).compare(devicename) == 0 )
  103. && flag )
  104. {
  105. id = dev_id;
  106. ret = fDeviceInfo[dev_id];
  107. }
  108. }
  109. free(hostname);
  110. return ret;
  111. }
  112. void PortAudioDevices::PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters)
  113. {
  114. static double standardSampleRates[] =
  115. {
  116. 8000.0, 9600.0, 11025.0, 12000.0, 16000.0, 22050.0, 24000.0, 32000.0,
  117. 44100.0, 48000.0, 88200.0, 96000.0, 192000.0, -1 /* negative terminated list */
  118. };
  119. int i, printCount;
  120. PaError err;
  121. printCount = 0;
  122. for (i = 0; standardSampleRates[i] > 0; i++)
  123. {
  124. err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
  125. if (err == paFormatIsSupported)
  126. {
  127. if (printCount == 0)
  128. {
  129. jack_info("\t%8.2f", standardSampleRates[i]);
  130. printCount = 1;
  131. }
  132. else if (printCount == 4)
  133. {
  134. jack_info(",\n\t%8.2f", standardSampleRates[i]);
  135. printCount = 1;
  136. }
  137. else
  138. {
  139. jack_info(", %8.2f", standardSampleRates[i]);
  140. ++printCount;
  141. }
  142. }
  143. }
  144. if (!printCount) {
  145. jack_info("None");
  146. } else {
  147. jack_info("\n");
  148. }
  149. }
  150. int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input)
  151. {
  152. string fullname = string ( devicename );
  153. PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, true );
  154. if ( device )
  155. max_input = device->maxInputChannels;
  156. else
  157. {
  158. id = Pa_GetDefaultInputDevice();
  159. if ( fullname.size() )
  160. jack_error("Can't open %s, PortAudio will use default input device.", devicename);
  161. if ( id == paNoDevice )
  162. return -1;
  163. max_input = GetDeviceInfo(id)->maxInputChannels;
  164. }
  165. return id;
  166. }
  167. int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
  168. {
  169. string fullname = string ( devicename );
  170. PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, false );
  171. if ( device )
  172. max_output = device->maxOutputChannels;
  173. else
  174. {
  175. id = Pa_GetDefaultOutputDevice();
  176. if ( fullname.size() )
  177. jack_error("Can't open %s, PortAudio will use default output device.", devicename);
  178. if ( id == paNoDevice )
  179. return -1;
  180. max_output = GetDeviceInfo(id)->maxOutputChannels;
  181. }
  182. return id;
  183. }
  184. void PortAudioDevices::DisplayDevicesNames()
  185. {
  186. PaDeviceIndex id;
  187. PaStreamParameters inputParameters, outputParameters;
  188. jack_info ( "********************** Devices list, %d detected **********************", fNumDevice );
  189. for ( id = 0; id < fNumDevice; id++ )
  190. {
  191. jack_info ( "-------- device #%d ------------------------------------------------", id );
  192. if ( id == Pa_GetDefaultInputDevice() )
  193. {
  194. jack_info("[ Default Input ]");
  195. }
  196. else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice )
  197. {
  198. const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
  199. jack_info ( "[ Default %s Input ]", host_info->name );
  200. }
  201. if ( id == Pa_GetDefaultOutputDevice() )
  202. {
  203. jack_info ( "[ Default Output ]" );
  204. }
  205. else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice )
  206. {
  207. const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
  208. jack_info ( "[ Default %s Output ]", host_info->name );
  209. }
  210. /* print device info fields */
  211. jack_info ( "Name = %s", GetFullName ( id ).c_str() );
  212. jack_info ( "Max inputs = %d", fDeviceInfo[id]->maxInputChannels );
  213. jack_info ( "Max outputs = %d", fDeviceInfo[id]->maxOutputChannels );
  214. #ifdef WIN32
  215. /* ASIO specific latency information */
  216. if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO )
  217. {
  218. long minLatency, maxLatency, preferredLatency, granularity;
  219. PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity );
  220. jack_info ( "ASIO minimum buffer size = %ld", minLatency );
  221. jack_info ( "ASIO maximum buffer size = %ld", maxLatency );
  222. jack_info ( "ASIO preferred buffer size = %ld", preferredLatency );
  223. if ( granularity == -1 )
  224. jack_info ( "ASIO buffer granularity = power of 2" );
  225. else
  226. jack_info ( "ASIO buffer granularity = %ld", granularity );
  227. }
  228. #endif
  229. jack_info ( "Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate );
  230. /* poll for standard sample rates */
  231. inputParameters.device = id;
  232. inputParameters.channelCount = fDeviceInfo[id]->maxInputChannels;
  233. inputParameters.sampleFormat = paInt16;
  234. inputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
  235. inputParameters.hostApiSpecificStreamInfo = NULL;
  236. outputParameters.device = id;
  237. outputParameters.channelCount = fDeviceInfo[id]->maxOutputChannels;
  238. outputParameters.sampleFormat = paInt16;
  239. outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
  240. outputParameters.hostApiSpecificStreamInfo = NULL;
  241. }
  242. jack_info ( "**************************** End of list ****************************" );
  243. }
  244. bool PortAudioDevices::IsDuplex ( PaDeviceIndex id )
  245. {
  246. //does the device has in and out facilities
  247. if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
  248. return true;
  249. //else is another complementary device ? (search in devices with the same name)
  250. for ( PaDeviceIndex i = 0; i < fNumDevice; i++ )
  251. if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) )
  252. if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
  253. || ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) )
  254. return true;
  255. //then the device isn't full duplex
  256. return false;
  257. }