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.

179 lines
5.1KB

  1. /*
  2. Copyright (C) 2008 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 "JackNetIOAdapter.h"
  16. #include "JackError.h"
  17. #include "JackExports.h"
  18. #include <stdio.h>
  19. using namespace std;
  20. namespace Jack
  21. {
  22. #define DEFAULT_RB_SIZE 16384 /* ringbuffer size in frames */
  23. int JackNetIOAdapter::Process(jack_nframes_t frames, void* arg)
  24. {
  25. JackNetIOAdapter* adapter = static_cast<JackNetIOAdapter*>(arg);
  26. char* buffer;
  27. int i;
  28. for (i = 0; i < adapter->fCaptureChannels; i++) {
  29. buffer = static_cast<char*>(jack_port_get_buffer(adapter->fCapturePortList[i], frames));
  30. size_t len = jack_ringbuffer_write_space(adapter->fCaptureRingBuffer);
  31. if (len < frames * sizeof(float)) {
  32. jack_error("JackNetIOAdapter::Process : consumer too slow, skip frames...");
  33. jack_ringbuffer_write(adapter->fCaptureRingBuffer, buffer, len);
  34. } else {
  35. jack_ringbuffer_write(adapter->fCaptureRingBuffer, buffer, frames * sizeof(float));
  36. }
  37. }
  38. for (i = 0; i < adapter->fPlaybackChannels; i++) {
  39. buffer = static_cast<char*>(jack_port_get_buffer(adapter->fPlaybackPortList[i], frames));
  40. size_t len = jack_ringbuffer_read_space(adapter->fPlaybackRingBuffer);
  41. if (len < frames * sizeof(float)) {
  42. jack_error("JackNetIOAdapter::Process : producer too slow, missing frames...");
  43. jack_ringbuffer_read(adapter->fPlaybackRingBuffer, buffer, len);
  44. } else {
  45. jack_ringbuffer_read(adapter->fPlaybackRingBuffer, buffer, frames * sizeof(float));
  46. }
  47. }
  48. return 0;
  49. }
  50. JackNetIOAdapter::JackNetIOAdapter(jack_client_t* jack_client, JackIOAdapterInterface* audio_io, int input, int output)
  51. {
  52. int i;
  53. char name[32];
  54. fJackClient = jack_client;
  55. fCaptureChannels = input;
  56. fPlaybackChannels = output;
  57. fIOAdapter = audio_io;
  58. fCapturePortList = new jack_port_t* [fCaptureChannels];
  59. fPlaybackPortList = new jack_port_t* [fPlaybackChannels];
  60. fCaptureRingBuffer = jack_ringbuffer_create(fCaptureChannels * sizeof(float) * DEFAULT_RB_SIZE);
  61. if (fCaptureRingBuffer == NULL)
  62. goto fail;
  63. fPlaybackRingBuffer = jack_ringbuffer_create(fPlaybackChannels * sizeof(float) * DEFAULT_RB_SIZE);
  64. if (fPlaybackRingBuffer == NULL)
  65. goto fail;
  66. fIOAdapter->SetRingBuffers(fCaptureRingBuffer, fPlaybackRingBuffer);
  67. for (i = 0; i < fCaptureChannels; i++) {
  68. sprintf(name, "in_%d", i+1);
  69. if ((fCapturePortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
  70. goto fail;
  71. }
  72. for (i = 0; i < fPlaybackChannels; i++) {
  73. sprintf(name, "out_%d", i+1);
  74. if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == NULL)
  75. goto fail;
  76. }
  77. if (jack_set_process_callback(fJackClient, Process, this) < 0)
  78. goto fail;
  79. if (jack_activate(fJackClient) < 0)
  80. goto fail;
  81. return;
  82. fail:
  83. FreePorts();
  84. }
  85. JackNetIOAdapter::~JackNetIOAdapter()
  86. {
  87. // When called Close has already been sued for the client, thus ports are already unregistered.
  88. delete fIOAdapter;
  89. }
  90. void JackNetIOAdapter::FreePorts()
  91. {
  92. int i;
  93. if (fCaptureRingBuffer)
  94. jack_ringbuffer_free(fCaptureRingBuffer);
  95. if (fPlaybackRingBuffer)
  96. jack_ringbuffer_free(fPlaybackRingBuffer);
  97. for (i = 0; i < fCaptureChannels; i++) {
  98. if (fCapturePortList[i])
  99. jack_port_unregister(fJackClient, fCapturePortList[i]);
  100. }
  101. for (i = 0; i < fCaptureChannels; i++) {
  102. if (fPlaybackPortList[i])
  103. jack_port_unregister(fJackClient, fPlaybackPortList[i]);
  104. }
  105. delete[] fCapturePortList;
  106. delete[] fPlaybackPortList;
  107. }
  108. } //namespace
  109. static Jack::JackNetIOAdapter* adapter = NULL;
  110. #ifdef __cplusplus
  111. extern "C"
  112. {
  113. #endif
  114. #include "JackCoreAudioIOAdapter.h"
  115. EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
  116. {
  117. if (adapter) {
  118. jack_error("NetAudio Adapter already loaded");
  119. return 1;
  120. } else {
  121. jack_log("Loading NetAudio Adapter");
  122. adapter = new Jack::JackNetIOAdapter(jack_client, new Jack::JackCoreAudioIOAdapter(2, 2), 2, 2);
  123. return (adapter) ? 0 : 1;
  124. }
  125. }
  126. EXPORT void jack_finish(void* arg)
  127. {
  128. if (adapter) {
  129. jack_log("Unloading NetAudio Adapter");
  130. delete adapter;
  131. adapter = NULL;
  132. }
  133. }
  134. #ifdef __cplusplus
  135. }
  136. #endif