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.

363 lines
9.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. _direction = rhs._direction;
  37. _name = strdup( rhs._name );
  38. _client->port_added( this );
  39. }
  40. /* nframes is the number of frames to buffer */
  41. Port::Port ( JACK::Client *client, jack_port_t *port )
  42. {
  43. _freezer = NULL;
  44. _client = client;
  45. _port = port;
  46. _name = strdup( jack_port_name( port ) );
  47. _direction = jack_port_flags( _port ) == JackPortIsOutput ? Output : Input;
  48. }
  49. Port::Port ( JACK::Client *client, const char *name, type_e dir )
  50. {
  51. _name = NULL;
  52. _freezer = NULL;
  53. _client = client;
  54. _direction = dir;
  55. _name = strdup( name );
  56. }
  57. Port::Port ( JACK::Client *client, type_e dir, const char *base, int n, const char *type )
  58. {
  59. _name = NULL;
  60. _freezer = NULL;
  61. _client = client;
  62. _name = strdup( name_for_port( dir, base, n, type ) );
  63. _direction = dir;
  64. }
  65. Port::Port ( JACK::Client *client, type_e dir, int n, const char *type )
  66. {
  67. _name = NULL;
  68. _freezer = NULL;
  69. _client = client;
  70. _name = strdup( name_for_port( dir, NULL, n, type ) );
  71. _direction = dir;
  72. }
  73. Port::~Port ( )
  74. {
  75. if ( _name )
  76. free( _name );
  77. _client->port_removed( this );
  78. /* if ( _freezer ) */
  79. /* { */
  80. /* delete _freezer; */
  81. /* _freezer = NULL; */
  82. /* } */
  83. /* if ( _port ) */
  84. /* jack_port_unregister( _client, _port ); */
  85. }
  86. /* sort input before output and then by alpha */
  87. bool
  88. Port::operator < ( const Port & rhs ) const
  89. {
  90. if ( type() == rhs.type() )
  91. return strcmp( name(), rhs.name() );
  92. else
  93. return type() == Port::Input;
  94. }
  95. static const char *
  96. name_for_port ( Port::type_e dir, const char *base, int n, const char *type )
  97. {
  98. static char pname[ 512 ];
  99. const char *dir_s = dir == Port::Output ? "out" : "in";
  100. pname[0] = '\0';
  101. if ( base )
  102. {
  103. strncpy( pname, base, Port::max_name() );
  104. strcat( pname, "/" );
  105. }
  106. pname[ Port::max_name() - 1 ] = '\0';
  107. int l = strlen( pname );
  108. if ( type )
  109. snprintf( pname + l, sizeof( pname ) - l, "%s-%s-%d", type, dir_s, n + 1 );
  110. else
  111. snprintf( pname + l, sizeof( pname ) - l, "%s-%d", dir_s, n + 1 );
  112. return pname;
  113. }
  114. bool
  115. Port::activate ( const char *name, type_e dir )
  116. {
  117. _name = strdup( name );
  118. _direction = dir;
  119. return activate();
  120. }
  121. bool
  122. Port::activate ( void )
  123. {
  124. _port = jack_port_register( _client->jack_client(), _name,
  125. JACK_DEFAULT_AUDIO_TYPE,
  126. _direction == Output ? JackPortIsOutput : JackPortIsInput,
  127. 0 );
  128. if ( ! _port )
  129. return false;
  130. _client->port_added( this );
  131. return true;
  132. }
  133. /** returns the sum of latency of all ports between this one and a
  134. terminal port. */
  135. /* FIMXE: how does JACK know that input A of client Foo connects to
  136. output Z of the same client in order to draw the line through Z to a
  137. terminal port? And, if this determination cannot be made, what use is
  138. this function? */
  139. nframes_t
  140. Port::total_latency ( void ) const
  141. {
  142. return jack_port_get_total_latency( _client->jack_client() , _port );
  143. }
  144. /** returns the number of frames of latency assigned to this port */
  145. nframes_t
  146. Port::latency ( void ) const
  147. {
  148. return jack_port_get_latency( _port );
  149. }
  150. /** inform JACK that port has /frames/ frames of latency */
  151. void
  152. Port::latency ( nframes_t frames )
  153. {
  154. jack_port_set_latency( _port, frames );
  155. }
  156. void
  157. Port::shutdown ( void )
  158. {
  159. if ( _port )
  160. jack_port_unregister( _client->jack_client(), _port );
  161. _client->port_removed( this );
  162. }
  163. /** rename port */
  164. bool
  165. Port::name ( const char *name )
  166. {
  167. _name = strdup( name );
  168. return 0 == jack_port_set_name( _port, name );
  169. }
  170. bool
  171. Port::name ( const char *base, int n, const char *type )
  172. {
  173. return name( name_for_port( this->type(), base, n, type ) );
  174. }
  175. void
  176. Port::write ( sample_t *buf, nframes_t nframes )
  177. {
  178. memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) );
  179. }
  180. void
  181. Port::read ( sample_t *buf, nframes_t nframes )
  182. {
  183. memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) );
  184. }
  185. void *
  186. Port::buffer ( nframes_t nframes )
  187. {
  188. return jack_port_get_buffer( _port, nframes );
  189. }
  190. void
  191. Port::silence ( nframes_t nframes )
  192. {
  193. memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) );
  194. }
  195. /** Return a malloc()'d null terminated array of strings
  196. * representing all ports to which this port is connected. */
  197. const char **
  198. Port::connections ( void )
  199. {
  200. return jack_port_get_connections( _port );
  201. }
  202. Port::type_e
  203. Port::type ( void ) const
  204. {
  205. return _direction;
  206. }
  207. /** Restore the connections returned by connections() */
  208. bool
  209. Port::connections ( const char **port_names )
  210. {
  211. if ( ! port_names )
  212. return true;
  213. for ( const char **port_name = port_names; *port_name; ++port_name )
  214. {
  215. const char *src;
  216. const char *dst;
  217. const char *name = jack_port_name( _port );
  218. if ( type() == Output )
  219. {
  220. src = name;
  221. dst = *port_name;
  222. }
  223. else
  224. {
  225. src = *port_name;
  226. dst = name;
  227. }
  228. if ( int err = jack_connect( _client->jack_client(), src, dst ) )
  229. {
  230. if ( EEXIST == err )
  231. {
  232. /* connection already exists, not a problem */
  233. }
  234. else
  235. {
  236. return false;
  237. }
  238. }
  239. }
  240. return true;
  241. }
  242. int
  243. Port::connect ( const char *to )
  244. {
  245. const char *name = jack_port_name( _port );
  246. if ( _direction == Output )
  247. {
  248. return jack_connect( _client->jack_client(), name, to );
  249. }
  250. else
  251. {
  252. return jack_connect( _client->jack_client(), to, name );
  253. }
  254. }
  255. int
  256. Port::disconnect ( const char *from )
  257. {
  258. const char *name = jack_port_name( _port );
  259. if ( _direction == Output )
  260. {
  261. return jack_disconnect( _client->jack_client(), name, from );
  262. }
  263. else
  264. {
  265. return jack_disconnect( _client->jack_client(), from, name );
  266. }
  267. }
  268. bool
  269. Port::connected_to ( const char *to )
  270. {
  271. return jack_port_connected_to( _port, to );
  272. }
  273. void
  274. Port::freeze ( void )
  275. {
  276. if ( _freezer )
  277. delete _freezer;
  278. freeze_state *f = new freeze_state();
  279. f->connections = connections();
  280. f->name = strdup( name() );
  281. _freezer = f;
  282. }
  283. void
  284. Port::thaw ( void )
  285. {
  286. activate();
  287. connections( _freezer->connections );
  288. delete _freezer;
  289. _freezer = NULL;
  290. }
  291. }