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.

438 lines
10.0KB

  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. #include "const.h"
  19. #include "Controller_Module.H"
  20. #include <stdio.h>
  21. #include <FL/Fl.H>
  22. #include <FL/Fl_Box.H>
  23. #include <FL/fl_ask.H>
  24. #include <FL/Fl_Counter.H>
  25. #include <FL/Fl_Menu_Item.H>
  26. #include <FL/Fl_Menu_Button.H>
  27. #include <FL/Fl_Menu_.H>
  28. #include <FL/Fl_Light_Button.H>
  29. #include "FL/Boxtypes.H"
  30. #include <FL/fl_draw.H>
  31. #include "FL/Fl_Arc_Dial.H"
  32. #include "FL/Fl_Labelpad_Group.H"
  33. #include "FL/Fl_Value_SliderX.H"
  34. #include "FL/test_press.H"
  35. #include "FL/menu_popup.H"
  36. #include "Engine/Engine.H"
  37. #include "Chain.H"
  38. const float CONTROL_UPDATE_FREQ = 0.1f;
  39. Controller_Module::Controller_Module ( bool is_default ) : Module( is_default, 50, 100, name() )
  40. {
  41. // label( "" );
  42. box( FL_NO_BOX );
  43. _pad = true;
  44. control = 0;
  45. control_value =0.0f;
  46. add_port( Port( this, Port::OUTPUT, Port::CONTROL ) );
  47. _mode = GUI;
  48. // mode( GUI );
  49. // mode( CV );
  50. // configure_inputs( 1 );
  51. end();
  52. Fl::add_timeout( CONTROL_UPDATE_FREQ, update_cb, this );
  53. log_create();
  54. }
  55. Controller_Module::~Controller_Module ( )
  56. {
  57. Fl::remove_timeout( update_cb, this );
  58. log_destroy();
  59. }
  60. void
  61. Controller_Module::get ( Log_Entry &e ) const
  62. {
  63. Module::get( e );
  64. Port *p = control_output[0].connected_port();
  65. Module *m = p->module();
  66. e.add( ":module", m );
  67. e.add( ":port", m->control_input_port_index( p ) );
  68. e.add( ":mode", mode() );
  69. }
  70. void
  71. Controller_Module::set ( Log_Entry &e )
  72. {
  73. Module::set( e );
  74. int port = -1;
  75. Module *module = NULL;
  76. for ( int i = 0; i < e.size(); ++i )
  77. {
  78. const char *s, *v;
  79. e.get( i, &s, &v );
  80. if ( ! strcmp( s, ":port" ) )
  81. {
  82. port = atoi( v );
  83. }
  84. else if ( ! strcmp( s, ":module" ) )
  85. {
  86. int i;
  87. sscanf( v, "%X", &i );
  88. Module *t = (Module*)Loggable::find( i );
  89. assert( t );
  90. module = t;
  91. }
  92. }
  93. if ( port >= 0 && module )
  94. {
  95. connect_to( &module->control_input[port] );
  96. module->chain()->add_control( this );
  97. label( module->control_input[port].name() );
  98. }
  99. for ( int i = 0; i < e.size(); ++i )
  100. {
  101. const char *s, *v;
  102. e.get( i, &s, &v );
  103. if ( ! strcmp( s, ":mode" ) )
  104. {
  105. mode( (Mode)atoi( v ) );
  106. }
  107. }
  108. }
  109. void
  110. Controller_Module::mode ( Mode m )
  111. {
  112. if( mode() != CV && m == CV )
  113. {
  114. if ( control_output[0].connected() )
  115. {
  116. chain()->engine()->lock();
  117. Port *p = control_output[0].connected_port();
  118. JACK::Port po( chain()->engine(), JACK::Port::Input, p->name(), 0, "CV" );
  119. if ( ! po.activate() )
  120. {
  121. fl_alert( "Could not activate JACK port \"%s\"", po.name() );
  122. return;
  123. }
  124. if ( po.valid() )
  125. {
  126. jack_input.push_back( po );
  127. }
  128. chain()->engine()->unlock();
  129. }
  130. }
  131. else if ( mode() == CV && m == GUI )
  132. {
  133. chain()->engine()->lock();
  134. jack_input.back().shutdown();
  135. jack_input.pop_back();
  136. chain()->engine()->unlock();
  137. }
  138. _mode = m ;
  139. }
  140. void
  141. Controller_Module::connect_to ( Port *p )
  142. {
  143. control_output[0].connect_to( p );
  144. Fl_Widget *w;
  145. if ( p->hints.type == Module::Port::Hints::BOOLEAN )
  146. {
  147. Fl_Light_Button *o = new Fl_Light_Button( 0, 0, 40, 40, p->name() );
  148. w = o;
  149. o->value( p->control_value() );
  150. }
  151. else if ( p->hints.type == Module::Port::Hints::INTEGER )
  152. {
  153. Fl_Counter *o = new Fl_Counter(0, 0, 58, 24, p->name() );
  154. control = o;
  155. w = o;
  156. o->type(1);
  157. o->step(1);
  158. if ( p->hints.ranged )
  159. {
  160. o->minimum( p->hints.minimum );
  161. o->maximum( p->hints.maximum );
  162. }
  163. o->value( p->control_value() );
  164. }
  165. else if ( p->hints.type == Module::Port::Hints::LOGARITHMIC )
  166. {
  167. Fl_Value_SliderX *o = new Fl_Value_SliderX(0, 0, 30, 250, p->name() );
  168. control = o;
  169. w = o;
  170. o->type(4);
  171. o->color(FL_GRAY0);
  172. o->selection_color((Fl_Color)1);
  173. o->minimum(1.5);
  174. o->maximum(0);
  175. o->value(1);
  176. o->textsize(14);
  177. if ( p->hints.ranged )
  178. {
  179. o->minimum( p->hints.maximum );
  180. o->maximum( p->hints.minimum );
  181. }
  182. o->value( p->control_value() );
  183. }
  184. else
  185. {
  186. { Fl_Arc_Dial *o = new Fl_Arc_Dial( 0, 0, 40, 40, p->name() );
  187. w = o;
  188. control = o;
  189. if ( p->hints.ranged )
  190. {
  191. o->minimum( p->hints.minimum );
  192. o->maximum( p->hints.maximum );
  193. }
  194. o->box( FL_BURNISHED_OVAL_BOX );
  195. o->color( fl_darker( fl_darker( FL_GRAY ) ) );
  196. o->selection_color( FL_WHITE );
  197. o->value( p->control_value() );
  198. }
  199. }
  200. control_value = p->control_value();
  201. w->align(FL_ALIGN_TOP);
  202. w->labelsize( 10 );
  203. w->callback( cb_handle, this );
  204. if ( _pad )
  205. {
  206. Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( w );
  207. size( flg->w(), flg->h() );
  208. add( flg );
  209. }
  210. else
  211. {
  212. w->resize( x(), y(), this->w(), h() );
  213. add( w );
  214. resizable( w );
  215. }
  216. }
  217. void
  218. Controller_Module::resize ( int X, int Y, int W, int H )
  219. {
  220. Module::resize( X, Y, W, H );
  221. if ( ! _pad && children() )
  222. {
  223. child( 0 )->resize( X, Y, W, H );
  224. }
  225. }
  226. void
  227. Controller_Module::update_cb ( void *v )
  228. {
  229. ((Controller_Module*)v)->update_cb();
  230. }
  231. void
  232. Controller_Module::update_cb ( void )
  233. {
  234. Fl::repeat_timeout( CONTROL_UPDATE_FREQ, update_cb, this );
  235. if ( control && control_output[0].connected() )
  236. control->value(control_value);
  237. }
  238. void
  239. Controller_Module::cb_handle ( Fl_Widget *w, void *v )
  240. {
  241. ((Controller_Module*)v)->cb_handle( w );
  242. }
  243. void
  244. Controller_Module::cb_handle ( Fl_Widget *w )
  245. {
  246. control_value = ((Fl_Valuator*)w)->value();
  247. if ( control_output[0].connected() )
  248. {
  249. control_output[0].control_value( control_value );
  250. Port *p = control_output[0].connected_port();
  251. Module *m = p->module();
  252. m->handle_control_changed( p );
  253. }
  254. }
  255. void
  256. Controller_Module::menu_cb ( Fl_Widget *w, void *v )
  257. {
  258. ((Controller_Module*)v)->menu_cb( (Fl_Menu_*) w );
  259. }
  260. void
  261. Controller_Module::menu_cb ( const Fl_Menu_ *m )
  262. {
  263. char picked[256];
  264. m->item_pathname( picked, sizeof( picked ) );
  265. Logger log( this );
  266. if ( ! strcmp( picked, "Mode/Manual" ) )
  267. mode( GUI );
  268. else if ( ! strcmp( picked, "Mode/Control Voltage" ) )
  269. mode( CV );
  270. }
  271. /** build the context menu for this control */
  272. Fl_Menu_Button &
  273. Controller_Module::menu ( void )
  274. {
  275. static Fl_Menu_Button m( 0, 0, 0, 0, "Controller" );
  276. Fl_Menu_Item items[] =
  277. {
  278. { "Mode", 0, 0, 0, FL_SUBMENU },
  279. { "Manual", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 ) },
  280. { "Control Voltage", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) },
  281. // { "Open Sound Control (OSC)", 0, 0, 0, FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) },
  282. { 0 },
  283. { 0 },
  284. };
  285. menu_set_callback( items, &Controller_Module::menu_cb, (void*)this );
  286. m.copy( items, (void*)this );
  287. return m;
  288. }
  289. int
  290. Controller_Module::handle ( int m )
  291. {
  292. switch ( m )
  293. {
  294. case FL_PUSH:
  295. {
  296. if ( test_press( FL_BUTTON3 ) )
  297. {
  298. /* context menu */
  299. menu_popup( &menu() );
  300. return 1;
  301. }
  302. else
  303. return Fl_Group::handle( m );
  304. }
  305. }
  306. return Fl_Group::handle( m );
  307. }
  308. /**********/
  309. /* Engine */
  310. /**********/
  311. void
  312. Controller_Module::process ( nframes_t nframes )
  313. {
  314. THREAD_ASSERT( RT );
  315. if ( control_output[0].connected() )
  316. {
  317. float f = control_value;
  318. if ( mode() == CV )
  319. {
  320. f = *((float*)jack_input[0].buffer( nframes ));
  321. const Port *p = control_output[0].connected_port();
  322. if (p->hints.ranged )
  323. {
  324. // scale value to range.
  325. // we assume that CV values are between 0 and 1
  326. float scale = p->hints.maximum - p->hints.minimum;
  327. float offset = p->hints.minimum;
  328. f = ( f * scale ) + offset;
  329. }
  330. }
  331. // else
  332. // f = *((float*)control_output[0].buffer());
  333. *((float*)control_output[0].buffer()) = f;
  334. control_value = f;
  335. }
  336. }