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.

365 lines
9.4KB

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