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.

312 lines
8.1KB

  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. /* sort input before output and then by alpha */
  81. bool
  82. Port::operator < ( const Port & rhs ) const
  83. {
  84. if ( type() == rhs.type() )
  85. return strcmp( name(), rhs.name() );
  86. else
  87. return type() == Port::Input;
  88. }
  89. static const char *
  90. name_for_port ( Port::type_e dir, const char *base, int n, const char *type )
  91. {
  92. static char pname[ 512 ];
  93. const char *dir_s = dir == Port::Output ? "out" : "in";
  94. pname[0] = '\0';
  95. if ( base )
  96. {
  97. strncpy( pname, base, Port::max_name() );
  98. strcat( pname, "/" );
  99. }
  100. pname[ Port::max_name() - 1 ] = '\0';
  101. int l = strlen( pname );
  102. if ( type )
  103. snprintf( pname + l, sizeof( pname ) - l, "%s-%s-%d", type, dir_s, n + 1 );
  104. else
  105. snprintf( pname + l, sizeof( pname ) - l, "%s-%d", dir_s, n + 1 );
  106. return pname;
  107. }
  108. void
  109. Port::activate ( const char *name, type_e dir )
  110. {
  111. _name = strdup( name );
  112. _port = jack_port_register( _client->jack_client(), _name,
  113. JACK_DEFAULT_AUDIO_TYPE,
  114. dir == Output ? JackPortIsOutput : JackPortIsInput,
  115. 0 );
  116. _client->port_added( this );
  117. }
  118. /** returns the sum of latency of all ports between this one and a
  119. terminal port. */
  120. /* FIMXE: how does JACK know that input A of client Foo connects to
  121. output Z of the same client in order to draw the line through Z to a
  122. terminal port? And, if this determination cannot be made, what use is
  123. this function? */
  124. nframes_t
  125. Port::total_latency ( void ) const
  126. {
  127. return jack_port_get_total_latency( _client->jack_client() , _port );
  128. }
  129. /** returns the number of frames of latency assigned to this port */
  130. nframes_t
  131. Port::latency ( void ) const
  132. {
  133. return jack_port_get_latency( _port );
  134. }
  135. /** inform JACK that port has /frames/ frames of latency */
  136. void
  137. Port::latency ( nframes_t frames )
  138. {
  139. jack_port_set_latency( _port, frames );
  140. }
  141. void
  142. Port::shutdown ( void )
  143. {
  144. if ( _port )
  145. jack_port_unregister( _client->jack_client(), _port );
  146. _client->port_removed( this );
  147. }
  148. /** rename port */
  149. bool
  150. Port::name ( const char *name )
  151. {
  152. _name = strdup( name );
  153. return 0 == jack_port_set_name( _port, name );
  154. }
  155. bool
  156. Port::name ( const char *base, int n, const char *type )
  157. {
  158. return name( name_for_port( this->type(), base, n, type ) );
  159. }
  160. void
  161. Port::write ( sample_t *buf, nframes_t nframes )
  162. {
  163. memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) );
  164. }
  165. void
  166. Port::read ( sample_t *buf, nframes_t nframes )
  167. {
  168. memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) );
  169. }
  170. void *
  171. Port::buffer ( nframes_t nframes )
  172. {
  173. return jack_port_get_buffer( _port, nframes );
  174. }
  175. void
  176. Port::silence ( nframes_t nframes )
  177. {
  178. memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) );
  179. }
  180. /** Return a malloc()'d null terminated array of strings
  181. * representing all ports to which this port is connected. */
  182. const char **
  183. Port::connections ( void )
  184. {
  185. return jack_port_get_connections( _port );
  186. }
  187. Port::type_e
  188. Port::type ( void ) const
  189. {
  190. if ( _freezer )
  191. return _freezer->direction;
  192. else
  193. return jack_port_flags( _port ) == JackPortIsOutput ? Output : Input;
  194. }
  195. /** Restore the connections returned by connections() */
  196. bool
  197. Port::connections ( const char **port_names )
  198. {
  199. if ( ! port_names )
  200. return true;
  201. for ( const char **port_name = port_names; *port_name; ++port_name )
  202. {
  203. const char *src;
  204. const char *dst;
  205. const char *name = jack_port_name( _port );
  206. if ( type() == Output )
  207. {
  208. src = name;
  209. dst = *port_name;
  210. }
  211. else
  212. {
  213. src = *port_name;
  214. dst = name;
  215. }
  216. if ( int err = jack_connect( _client->jack_client(), src, dst ) )
  217. {
  218. if ( EEXIST == err )
  219. {
  220. /* connection already exists, not a problem */
  221. }
  222. else
  223. {
  224. return false;
  225. }
  226. }
  227. }
  228. return true;
  229. }
  230. void
  231. Port::freeze ( void )
  232. {
  233. if ( _freezer )
  234. delete _freezer;
  235. freeze_state *f = new freeze_state();
  236. f->connections = connections();
  237. f->direction = type();
  238. f->name = strdup( name() );
  239. _freezer = f;
  240. }
  241. void
  242. Port::thaw ( void )
  243. {
  244. activate( name(), _freezer->direction );
  245. connections( _freezer->connections );
  246. delete _freezer;
  247. _freezer = NULL;
  248. }
  249. }