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.

380 lines
9.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::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. int flags = 0;
  138. if ( _direction == Output )
  139. flags |= JackPortIsOutput;
  140. else
  141. flags |= JackPortIsInput;
  142. if ( _terminal )
  143. flags |= JackPortIsTerminal;
  144. _port = jack_port_register( _client->jack_client(), _name,
  145. _type == Audio ? JACK_DEFAULT_AUDIO_TYPE : JACK_DEFAULT_MIDI_TYPE,
  146. flags,
  147. 0 );
  148. if ( ! _port )
  149. return false;
  150. _client->port_added( this );
  151. return true;
  152. }
  153. /** returns the sum of latency of all ports between this one and a
  154. terminal port. */
  155. /* FIMXE: how does JACK know that input A of client Foo connects to
  156. output Z of the same client in order to draw the line through Z to a
  157. terminal port? And, if this determination cannot be made, what use is
  158. this function? */
  159. nframes_t
  160. Port::total_latency ( void ) const
  161. {
  162. return jack_port_get_total_latency( _client->jack_client() , _port );
  163. }
  164. /** returns the number of frames of latency assigned to this port */
  165. nframes_t
  166. Port::latency ( void ) const
  167. {
  168. return jack_port_get_latency( _port );
  169. }
  170. /** inform JACK that port has /frames/ frames of latency */
  171. void
  172. Port::latency ( nframes_t frames )
  173. {
  174. jack_port_set_latency( _port, frames );
  175. }
  176. void
  177. Port::shutdown ( void )
  178. {
  179. if ( _port )
  180. jack_port_unregister( _client->jack_client(), _port );
  181. _client->port_removed( this );
  182. }
  183. /** rename port */
  184. bool
  185. Port::name ( const char *name )
  186. {
  187. _name = strdup( name );
  188. return 0 == jack_port_set_name( _port, name );
  189. }
  190. bool
  191. Port::name ( const char *base, int n, const char *type )
  192. {
  193. return name( name_for_port( this->direction(), base, n, type ) );
  194. }
  195. void
  196. Port::write ( sample_t *buf, nframes_t nframes )
  197. {
  198. memcpy( buffer( nframes ), buf, nframes * sizeof( sample_t ) );
  199. }
  200. void
  201. Port::read ( sample_t *buf, nframes_t nframes )
  202. {
  203. memcpy( buf, buffer( nframes ), nframes * sizeof( sample_t ) );
  204. }
  205. void *
  206. Port::buffer ( nframes_t nframes )
  207. {
  208. return jack_port_get_buffer( _port, nframes );
  209. }
  210. void
  211. Port::silence ( nframes_t nframes )
  212. {
  213. memset( buffer( nframes ), 0, nframes * sizeof( sample_t ) );
  214. }
  215. /** Return a malloc()'d null terminated array of strings
  216. * representing all ports to which this port is connected. */
  217. const char **
  218. Port::connections ( void )
  219. {
  220. return jack_port_get_connections( _port );
  221. }
  222. /** Restore the connections returned by connections() */
  223. bool
  224. Port::connections ( const char **port_names )
  225. {
  226. if ( ! port_names )
  227. return true;
  228. for ( const char **port_name = port_names; *port_name; ++port_name )
  229. {
  230. const char *src;
  231. const char *dst;
  232. const char *name = jack_port_name( _port );
  233. if ( direction() == Output )
  234. {
  235. src = name;
  236. dst = *port_name;
  237. }
  238. else
  239. {
  240. src = *port_name;
  241. dst = name;
  242. }
  243. if ( int err = jack_connect( _client->jack_client(), src, dst ) )
  244. {
  245. if ( EEXIST == err )
  246. {
  247. /* connection already exists, not a problem */
  248. }
  249. else
  250. {
  251. return false;
  252. }
  253. }
  254. }
  255. return true;
  256. }
  257. int
  258. Port::connect ( const char *to )
  259. {
  260. const char *name = jack_port_name( _port );
  261. if ( _direction == Output )
  262. {
  263. return jack_connect( _client->jack_client(), name, to );
  264. }
  265. else
  266. {
  267. return jack_connect( _client->jack_client(), to, name );
  268. }
  269. }
  270. int
  271. Port::disconnect ( const char *from )
  272. {
  273. const char *name = jack_port_name( _port );
  274. if ( _direction == Output )
  275. {
  276. return jack_disconnect( _client->jack_client(), name, from );
  277. }
  278. else
  279. {
  280. return jack_disconnect( _client->jack_client(), from, name );
  281. }
  282. }
  283. bool
  284. Port::connected_to ( const char *to )
  285. {
  286. return jack_port_connected_to( _port, to );
  287. }
  288. void
  289. Port::freeze ( void )
  290. {
  291. if ( _freezer )
  292. delete _freezer;
  293. freeze_state *f = new freeze_state();
  294. f->connections = connections();
  295. f->name = strdup( name() );
  296. _freezer = f;
  297. }
  298. void
  299. Port::thaw ( void )
  300. {
  301. activate();
  302. connections( _freezer->connections );
  303. delete _freezer;
  304. _freezer = NULL;
  305. }
  306. }