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.

471 lines
13KB

  1. /*******************************************************************************/
  2. /* Copyright (C) 2009 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. /* Mixer strip control. Handles GUI and control I/O for this strip. */
  19. /* A mixer strip is home to some (JACK) input ports, a fader, some
  20. * meters, and a filter chain which can terminate either at the input
  21. * to the spacializer or some (JACK) output ports. Since mixer strips
  22. * are not necessarily in a 1:1 association with Non-DAW tracks, there
  23. * is no need for busses per se. If you want to route the output of
  24. * several strips into a single fader or filter chain, then you just
  25. * gives those strips JACK outputs and connect them to the common
  26. * inputs. This mechanism can also do away with the need for 'sends'
  27. * and 'inserts'.
  28. */
  29. /* Each mixer strip comprises a fader and a panner */
  30. #include "Mixer_Strip.H"
  31. #include "Engine/Engine.H"
  32. #include <dsp.h>
  33. #include <string.h>
  34. #include "debug.h"
  35. #include "FL/Fl_Flowpack.H"
  36. #include <FL/Fl_Input.H>
  37. #include <FL/fl_ask.H>
  38. #include "Mixer.H"
  39. #include "Chain.H"
  40. #include "Gain_Module.H"
  41. #include "Meter_Module.H"
  42. #include "Controller_Module.H"
  43. #include "Meter_Indicator_Module.H"
  44. #include "util/debug.h"
  45. extern Mixer *mixer;
  46. void
  47. Mixer_Strip::get ( Log_Entry &e ) const
  48. {
  49. e.add( ":name", name() );
  50. e.add( ":width", prepost_button->value() ? "wide" : "narrow" );
  51. e.add( ":tab", tab_button->value() ? "signal" : "fader" );
  52. e.add( ":color", (unsigned long)color());
  53. }
  54. void
  55. Mixer_Strip::set ( Log_Entry &e )
  56. {
  57. for ( int i = 0; i < e.size(); ++i )
  58. {
  59. const char *s, *v;
  60. e.get( i, &s, &v );
  61. if ( ! strcmp( s, ":name" ) )
  62. name( v );
  63. else if ( ! strcmp( s, ":width" ) )
  64. {
  65. prepost_button->value( strcmp( v, "wide" ) == 0 );
  66. prepost_button->do_callback();
  67. }
  68. else if ( ! strcmp( s, ":tab" ) )
  69. {
  70. tab_button->value( strcmp( v, "signal" ) == 0 );
  71. tab_button->do_callback();
  72. }
  73. else if ( ! strcmp( s, ":color" ) )
  74. {
  75. color( (Fl_Color)atoll( v ) );
  76. redraw();
  77. }
  78. }
  79. if ( ! mixer->contains( this ) )
  80. mixer->add( this );
  81. }
  82. void
  83. Mixer_Strip::log_children ( void )
  84. {
  85. log_create();
  86. _chain->log_children();
  87. }
  88. void
  89. Mixer_Strip::color ( Fl_Color c )
  90. {
  91. _color = c;
  92. name_field->color( _color );
  93. name_field->redraw();
  94. }
  95. Fl_Color
  96. Mixer_Strip::color ( void ) const
  97. {
  98. return _color;
  99. }
  100. void
  101. Mixer_Strip::chain ( Chain *c )
  102. {
  103. if ( _chain )
  104. delete _chain;
  105. _chain = c;
  106. c->strip( this );
  107. Fl_Group *g = signal_tab;
  108. c->resize( g->x(), g->y(), g->w(), g->h() );
  109. g->add( c );
  110. g->resizable( c );
  111. c->labelsize( 10 );
  112. c->align( FL_ALIGN_TOP );
  113. c->color( FL_RED );
  114. c->configure_outputs_callback( configure_outputs, this );
  115. c->name( name() );
  116. gain_controller->chain( c );
  117. jack_input_controller->chain( c );
  118. meter_indicator->chain( c );
  119. }
  120. /* add a new mixer strip (with default configuration) */
  121. Mixer_Strip::Mixer_Strip( const char *strip_name, int channels ) : Fl_Group( 0, 0, 120, 600 )
  122. {
  123. label( strdup( strip_name ) );
  124. labeltype( FL_NO_LABEL );
  125. init();
  126. chain( new Chain() );
  127. _chain->initialize_with_default();
  128. _chain->configure_ports();
  129. color( (Fl_Color)rand() );
  130. // name( strdup( strip_name ) );
  131. log_create();
  132. }
  133. /* virgin strip created from journal */
  134. Mixer_Strip::Mixer_Strip() : Fl_Group( 0, 0, 120, 600 )
  135. {
  136. init();
  137. log_create();
  138. }
  139. Mixer_Strip::~Mixer_Strip ( )
  140. {
  141. DMESSAGE( "Destroying mixer strip" );
  142. delete _chain;
  143. _chain = NULL;
  144. log_destroy();
  145. }
  146. void Mixer_Strip::cb_handle(Fl_Widget* o) {
  147. // parent()->parent()->damage( FL_DAMAGE_ALL, x(), y(), w(), h() );
  148. if ( o == tab_button )
  149. {
  150. if ( tab_button->value() == 0 )
  151. {
  152. fader_tab->show();
  153. signal_tab->hide();
  154. }
  155. else
  156. {
  157. signal_tab->show();
  158. fader_tab->hide();
  159. }
  160. }
  161. else if ( o == left_button )
  162. {
  163. mixer->move_left( this );
  164. }
  165. else if ( o == right_button )
  166. {
  167. mixer->move_right( this );
  168. }
  169. else if ( o == close_button )
  170. {
  171. if ( Fl::event_shift() || 1 == fl_choice( "Are you sure you want to remove this strip?\n\n(this action cannot be undone)", "Cancel", "Remove", NULL ) )
  172. {
  173. ((Mixer*)parent())->remove( this );
  174. }
  175. }
  176. else if ( o == name_field )
  177. name( name_field->value() );
  178. else if ( o == prepost_button )
  179. {
  180. if ( ((Fl_Button*)o)->value() )
  181. size( 300, h() );
  182. else
  183. size( 120, h() );
  184. if ( parent() )
  185. parent()->parent()->redraw();
  186. }
  187. }
  188. void Mixer_Strip::cb_handle(Fl_Widget* o, void* v) {
  189. ((Mixer_Strip*)(v))->cb_handle(o);
  190. }
  191. void
  192. Mixer_Strip::name ( const char *name ) {
  193. char *s = strdup( name );
  194. name_field->value( s );
  195. label( s );
  196. if ( _chain )
  197. _chain->name( s );
  198. }
  199. void
  200. Mixer_Strip::configure_outputs ( Fl_Widget *o, void *v )
  201. {
  202. ((Mixer_Strip*)v)->configure_outputs();
  203. }
  204. void
  205. Mixer_Strip::configure_outputs ( void )
  206. {
  207. DMESSAGE( "Got signal to configure outputs" );
  208. }
  209. /* called by the chain to let us know that a module has been added */
  210. void
  211. Mixer_Strip::handle_module_added ( Module *m )
  212. {
  213. if ( m->is_default() )
  214. {
  215. DMESSAGE( "Connecting controls to default module \"%s\"", m->name() );
  216. /* connect default modules to their default controllers/indicators */
  217. if ( 0 == strcmp( m->name(), "JACK" ) && m->ninputs() == 0 )
  218. {
  219. if ( !jack_input_controller->control_output[0].connected() )
  220. jack_input_controller->connect_to( &m->control_input[1] );
  221. }
  222. else if ( 0 == strcmp( m->name(), "Gain" ) )
  223. {
  224. gain_controller->connect_to( &m->control_input[0] );
  225. }
  226. else if ( 0 == strcmp( m->name(), "Meter" ) )
  227. {
  228. meter_indicator->connect_to( &m->control_output[0] );
  229. }
  230. }
  231. }
  232. /* update GUI with values from RT thread */
  233. void
  234. Mixer_Strip::update ( void )
  235. {
  236. THREAD_ASSERT( UI );
  237. }
  238. void
  239. Mixer_Strip::init ( )
  240. {
  241. _chain = 0;
  242. // box(FL_THIN_UP_BOX);
  243. box( FL_RFLAT_BOX );
  244. Fl_Group::color( fl_darker( FL_BACKGROUND_COLOR ) );
  245. clip_children( 1 );
  246. Fl_Pack *gain_pack;
  247. { Fl_Pack *o = new Fl_Pack( 2, 2, 114, 100 );
  248. o->type( Fl_Pack::VERTICAL );
  249. o->spacing( 2 );
  250. {
  251. Fl_Sometimes_Input *o = new Fl_Sometimes_Input( 2, 2, 144, 24 );
  252. name_field = o;
  253. o->color( color() );
  254. o->up_box( FL_ROUNDED_BOX );
  255. o->box( FL_ROUNDED_BOX );
  256. o->labeltype( FL_NO_LABEL );
  257. o->labelcolor( FL_GRAY0 );
  258. o->textcolor( FL_FOREGROUND_COLOR );
  259. o->value( name() );
  260. o->callback( cb_handle, (void*)this );
  261. }
  262. { Fl_Scalepack *o = new Fl_Scalepack( 7, 143, 110, 25 );
  263. o->type( Fl_Pack::HORIZONTAL );
  264. { Fl_Button* o = left_button = new Fl_Button(7, 143, 35, 25, "@<-");
  265. o->tooltip( "Move left" );
  266. o->type(0);
  267. o->labelsize(10);
  268. o->when( FL_WHEN_RELEASE );
  269. o->callback( ((Fl_Callback*)cb_handle), this );
  270. } // Fl_Button* o
  271. { Fl_Button* o = close_button = new Fl_Button(7, 143, 35, 25, "X");
  272. o->tooltip( "Remove strip" );
  273. o->type(0);
  274. o->labeltype( FL_EMBOSSED_LABEL );
  275. o->color( FL_LIGHT1 );
  276. o->selection_color( FL_RED );
  277. o->labelsize(10);
  278. o->when( FL_WHEN_RELEASE );
  279. o->callback( ((Fl_Callback*)cb_handle), this );
  280. } // Fl_Button* o
  281. { Fl_Button* o = right_button = new Fl_Button(7, 143, 35, 25, "@->");
  282. o->tooltip( "Move right" );
  283. o->type(0);
  284. o->labelsize(10);
  285. o->when( FL_WHEN_RELEASE );
  286. o->callback( ((Fl_Callback*)cb_handle), this );
  287. } // Fl_Button* o
  288. o->end();
  289. } // Fl_Group* o
  290. { Fl_Flip_Button* o = prepost_button = new Fl_Flip_Button(61, 183, 45, 22, "narrow/wide");
  291. o->type(1);
  292. o->labelsize(14);
  293. o->callback( ((Fl_Callback*)cb_handle), this );
  294. o->when(FL_WHEN_RELEASE);
  295. } // Fl_Flip_Button* o
  296. { Fl_Flip_Button* o = tab_button = new Fl_Flip_Button(61, 183, 45, 22, "fader/signal");
  297. o->type(1);
  298. o->labelsize( 14 );
  299. o->callback( cb_handle, this );
  300. o->when(FL_WHEN_RELEASE);
  301. }
  302. // { Fl_Pack* o = new Fl_Pack(8, 208, 103, 471);
  303. // { Fl_Pack* o = gain_pack = new Fl_Pack(8, 208, 103, 516 );
  304. o->end();
  305. }
  306. Fl_Pack *fader_pack;
  307. { Fl_Group *o = fader_tab = new Fl_Group( 7, 115, 105, 330, "Fader" );
  308. o->box( FL_NO_BOX );
  309. o->labeltype( FL_NO_LABEL );
  310. { Fl_Pack* o = fader_pack = new Fl_Pack(7, 116, 103, 330 );
  311. o->spacing( 20 );
  312. o->type( Fl_Pack::HORIZONTAL );
  313. { Controller_Module *o = gain_controller = new Controller_Module( true );
  314. o->pad( false );
  315. o->size( 33, 0 );
  316. }
  317. { Meter_Indicator_Module *o = meter_indicator = new Meter_Indicator_Module( true );
  318. o->pad( false );
  319. o->size( 58, 0 );
  320. o->clip_children( 0 );
  321. Fl_Group::current()->resizable(o);
  322. }
  323. o->end();
  324. Fl_Group::current()->resizable(o);
  325. } // Fl_Group* o
  326. o->end();
  327. Fl_Group::current()->resizable(o);
  328. }
  329. { Fl_Group *o = signal_tab = new Fl_Group( 7, 115, 105, 330 );
  330. o->box( FL_NO_BOX );
  331. o->labeltype( FL_NO_LABEL );
  332. o->hide();
  333. o->end();
  334. }
  335. { Fl_Pack *o = panner_pack = new Fl_Pack( 2, 443, 114, 40 );
  336. o->spacing( 2 );
  337. o->type( Fl_Pack::VERTICAL );
  338. o->box( FL_NO_BOX );
  339. { Fl_Box *o = new Fl_Box( 0, 0, 100, 24 );
  340. o->align( (Fl_Align)(FL_ALIGN_BOTTOM | FL_ALIGN_INSIDE) );
  341. o->labelsize( 10 );
  342. o->label( "Spatialization" );
  343. }
  344. { Panner* o = new Panner(0, 0, 110, 90);
  345. o->deactivate();
  346. o->box(FL_THIN_UP_BOX);
  347. o->color(FL_GRAY0);
  348. o->selection_color(FL_BACKGROUND_COLOR);
  349. o->labeltype(FL_NORMAL_LABEL);
  350. o->labelfont(0);
  351. o->labelsize(11);
  352. o->labelcolor(FL_FOREGROUND_COLOR);
  353. o->align(FL_ALIGN_TOP);
  354. o->when(FL_WHEN_RELEASE);
  355. } // Panner* o
  356. { Fl_Box *o = new Fl_Box( 0, 0, 100, 12 );
  357. o->align( (Fl_Align)(FL_ALIGN_BOTTOM | FL_ALIGN_INSIDE) );
  358. o->labelsize( 10 );
  359. o->label( "Inputs" );
  360. }
  361. {
  362. Controller_Module *m = jack_input_controller = new Controller_Module( true );
  363. m->labeltype( FL_NO_LABEL );
  364. m->chain( _chain );
  365. m->pad( false );
  366. // m->connect_to( &_chain->module( 0 )->control_input[1] );
  367. m->size( 33, 24 );
  368. }
  369. o->end();
  370. }
  371. end();
  372. color( FL_BLACK );
  373. // _chain->configure_ports();
  374. }
  375. int
  376. Mixer_Strip::handle ( int m )
  377. {
  378. Logger log( this );
  379. switch ( m )
  380. {
  381. /* case FL_ENTER: */
  382. /* name_field->color( FL_BLACK ); */
  383. /* name_field->redraw(); */
  384. /* return 1; */
  385. /* break; */
  386. /* case FL_LEAVE: */
  387. /* name_field->color( _color ); */
  388. /* name_field->redraw(); */
  389. /* return 1; */
  390. /* break; */
  391. default:
  392. return Fl_Group::handle( m );
  393. }
  394. return 0;
  395. }