Assists music production by grouping standalone programs into sessions. Community version of "Non Session Manager".
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.

294 lines
7.7KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2008 Jonathan Moore Liles */
  3. /* */
  4. /* This program is free software; you can redistribute it and/or modify it */
  5. /* under the terms of the GNU General Public License as published by the */
  6. /* Free Software Foundation; either version 2 of the License, or (at your */
  7. /* option) any later version. */
  8. /* */
  9. /* This program is distributed in the hope that it will be useful, but WITHOUT */
  10. /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
  11. /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
  12. /* more details. */
  13. /* */
  14. /* You should have received a copy of the GNU General Public License along */
  15. /* with This program; see the file COPYING. If not,write to the Free Software */
  16. /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  17. /*******************************************************************************/
  18. /* Wrapper for a JACK audio port */
  19. #include "Port.H"
  20. #include <string.h>
  21. #include <stdio.h> // sprintf
  22. #include <errno.h>
  23. namespace JACK
  24. {
  25. static const char *name_for_port ( Port::type_e dir, const char *base, int n, const char *type );
  26. int
  27. Port::max_name ( void )
  28. {
  29. return jack_port_name_size() - jack_client_name_size() - 6;
  30. }
  31. Port::Port ( const Port &rhs )
  32. {
  33. _freezer = rhs._freezer;
  34. _client = rhs._client;
  35. _port = rhs._port;
  36. _name = strdup( rhs._name );
  37. _client->port_added( this );
  38. }
  39. /* nframes is the number of frames to buffer */
  40. Port::Port ( JACK::Client *client, jack_port_t *port )
  41. {
  42. _freezer = NULL;
  43. _client = client;
  44. _port = port;
  45. _name = strdup( jack_port_name( _port ) );
  46. }
  47. Port::Port ( JACK::Client *client, const char *name, type_e dir )
  48. {
  49. _freezer = NULL;
  50. _client = client;
  51. activate( name, dir );
  52. }
  53. Port::Port ( JACK::Client *client, type_e dir, const char *base, int n, const char *type )
  54. {
  55. _freezer = NULL;
  56. _client = client;
  57. const char *name = name_for_port( dir, base, n, type );
  58. activate( name, dir );
  59. }
  60. Port::Port ( JACK::Client *client, type_e dir, int n, const char *type )
  61. {
  62. _freezer = NULL;
  63. _client = client;
  64. const char *name = name_for_port( dir, NULL, n, type );
  65. activate( name, dir );
  66. }
  67. Port::~Port ( )
  68. {
  69. if ( _name )
  70. free( _name );
  71. _client->port_removed( this );
  72. /* if ( _freezer ) */
  73. /* { */
  74. /* delete _freezer; */
  75. /* _freezer = NULL; */
  76. /* } */
  77. /* if ( _port ) */
  78. /* jack_port_unregister( _client, _port ); */
  79. }
  80. static const char *
  81. name_for_port ( Port::type_e dir, const char *base, int n, const char *type )
  82. {
  83. static char pname[ 512 ];
  84. const char *dir_s = dir == Port::Output ? "out" : "in";
  85. pname[0] = '\0';
  86. if ( base )
  87. {
  88. strncpy( pname, base, Port::max_name() );
  89. strcat( pname, "/" );
  90. }
  91. pname[ Port::max_name() - 1 ] = '\0';
  92. int l = strlen( pname );
  93. if ( type )
  94. snprintf( pname + l, sizeof( pname ) - l, "%s-%s-%d", type, dir_s, n + 1 );
  95. else
  96. snprintf( pname + l, sizeof( pname ) - l, "%s-%d", dir_s, n + 1 );
  97. return pname;
  98. }
  99. void
  100. Port::activate ( const char *name, type_e dir )
  101. {
  102. _name = strdup( name );
  103. _port = jack_port_register( _client->jack_client(), _name,
  104. JACK_DEFAULT_AUDIO_TYPE,
  105. dir == Output ? JackPortIsOutput : JackPortIsInput,
  106. 0 );
  107. _client->port_added( this );
  108. }
  109. /** returns the sum of latency of all ports between this one and a
  110. terminal port. */
  111. /* FIMXE: how does JACK know that input A of client Foo connects to
  112. output Z of the same client in order to draw the line through Z to a
  113. terminal port? And, if this determination cannot be made, what use is
  114. this function? */
  115. nframes_t
  116. Port::total_latency ( void ) const
  117. {
  118. return jack_port_get_total_latency( _client->jack_client() , _port );
  119. }
  120. /** returns the number of frames of latency assigned to this port */
  121. nframes_t
  122. Port::latency ( void ) const
  123. {
  124. return jack_port_get_latency( _port );
  125. }
  126. /** inform JACK that port has /frames/ frames of latency */
  127. void
  128. Port::latency ( nframes_t frames )
  129. {
  130. jack_port_set_latency( _port, frames );
  131. }
  132. void
  133. Port::shutdown ( void )
  134. {
  135. if ( _port )
  136. jack_port_unregister( _client->jack_client(), _port );
  137. _client->port_removed( this );
  138. }
  139. /** rename port */
  140. bool
  141. Port::name ( const char *name )
  142. {
  143. _name = strdup( name );
  144. return 0 == jack_port_set_name( _port, name );
  145. }
  146. bool
  147. Port::name ( const char *base, int n, const char *type )
  148. {
  149. return name( name_for_port( this->type(), base, n, type ) );
  150. }
  151. void
  152. Port::write ( sample_t *buf, nframes_t nframes )
  153. {
  154. memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) );
  155. }
  156. void
  157. Port::read ( sample_t *buf, nframes_t nframes )
  158. {
  159. memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) );
  160. }
  161. void *
  162. Port::buffer ( nframes_t nframes )
  163. {
  164. return jack_port_get_buffer( _port, nframes );
  165. }
  166. void
  167. Port::silence ( nframes_t nframes )
  168. {
  169. memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) );
  170. }
  171. /** Return a malloc()'d null terminated array of strings
  172. * representing all ports to which this port is connected. */
  173. const char **
  174. Port::connections ( void )
  175. {
  176. return jack_port_get_connections( _port );
  177. }
  178. /** Restore the connections returned by connections() */
  179. bool
  180. Port::connections ( const char **port_names )
  181. {
  182. if ( ! port_names )
  183. return true;
  184. for ( const char **port_name = port_names; *port_name; ++port_name )
  185. {
  186. const char *src;
  187. const char *dst;
  188. const char *name = jack_port_name( _port );
  189. if ( type() == Output )
  190. {
  191. src = name;
  192. dst = *port_name;
  193. }
  194. else
  195. {
  196. src = *port_name;
  197. dst = name;
  198. }
  199. if ( int err = jack_connect( _client->jack_client(), src, dst ) )
  200. {
  201. if ( EEXIST == err )
  202. {
  203. /* connection already exists, not a problem */
  204. }
  205. else
  206. {
  207. return false;
  208. }
  209. }
  210. }
  211. return true;
  212. }
  213. void
  214. Port::freeze ( void )
  215. {
  216. if ( _freezer )
  217. delete _freezer;
  218. freeze_state *f = new freeze_state();
  219. f->connections = connections();
  220. f->direction = type();
  221. f->name = strdup( name() );
  222. _freezer = f;
  223. }
  224. void
  225. Port::thaw ( void )
  226. {
  227. activate( name(), _freezer->direction );
  228. connections( _freezer->connections );
  229. delete _freezer;
  230. _freezer = NULL;
  231. }
  232. }