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.

371 lines
9.6KB

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