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.

440 lines
10KB

  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(6);
  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->set_visible_focus();
  202. w->align(FL_ALIGN_TOP);
  203. w->labelsize( 10 );
  204. w->callback( cb_handle, this );
  205. if ( _pad )
  206. {
  207. Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( w );
  208. flg->set_visible_focus();
  209. size( flg->w(), flg->h() );
  210. add( flg );
  211. }
  212. else
  213. {
  214. w->resize( x(), y(), this->w(), h() );
  215. add( w );
  216. resizable( w );
  217. }
  218. }
  219. void
  220. Controller_Module::resize ( int X, int Y, int W, int H )
  221. {
  222. Module::resize( X, Y, W, H );
  223. if ( ! _pad && children() )
  224. {
  225. child( 0 )->resize( X, Y, W, H );
  226. }
  227. }
  228. void
  229. Controller_Module::update_cb ( void *v )
  230. {
  231. ((Controller_Module*)v)->update_cb();
  232. }
  233. void
  234. Controller_Module::update_cb ( void )
  235. {
  236. Fl::repeat_timeout( CONTROL_UPDATE_FREQ, update_cb, this );
  237. if ( control && control_output[0].connected() )
  238. control->value(control_value);
  239. }
  240. void
  241. Controller_Module::cb_handle ( Fl_Widget *w, void *v )
  242. {
  243. ((Controller_Module*)v)->cb_handle( w );
  244. }
  245. void
  246. Controller_Module::cb_handle ( Fl_Widget *w )
  247. {
  248. control_value = ((Fl_Valuator*)w)->value();
  249. if ( control_output[0].connected() )
  250. {
  251. control_output[0].control_value( control_value );
  252. Port *p = control_output[0].connected_port();
  253. Module *m = p->module();
  254. m->handle_control_changed( p );
  255. }
  256. }
  257. void
  258. Controller_Module::menu_cb ( Fl_Widget *w, void *v )
  259. {
  260. ((Controller_Module*)v)->menu_cb( (Fl_Menu_*) w );
  261. }
  262. void
  263. Controller_Module::menu_cb ( const Fl_Menu_ *m )
  264. {
  265. char picked[256];
  266. m->item_pathname( picked, sizeof( picked ) );
  267. Logger log( this );
  268. if ( ! strcmp( picked, "Mode/Manual" ) )
  269. mode( GUI );
  270. else if ( ! strcmp( picked, "Mode/Control Voltage" ) )
  271. mode( CV );
  272. }
  273. /** build the context menu for this control */
  274. Fl_Menu_Button &
  275. Controller_Module::menu ( void )
  276. {
  277. static Fl_Menu_Button m( 0, 0, 0, 0, "Controller" );
  278. Fl_Menu_Item items[] =
  279. {
  280. { "Mode", 0, 0, 0, FL_SUBMENU },
  281. { "Manual", 0, 0, 0, FL_MENU_RADIO | ( mode() == GUI ? FL_MENU_VALUE : 0 ) },
  282. { "Control Voltage", 0, 0, 0, FL_MENU_RADIO | ( mode() == CV ? FL_MENU_VALUE : 0 ) },
  283. // { "Open Sound Control (OSC)", 0, 0, 0, FL_MENU_RADIO | ( mode() == OSC ? FL_MENU_VALUE : 0 ) },
  284. { 0 },
  285. { 0 },
  286. };
  287. menu_set_callback( items, &Controller_Module::menu_cb, (void*)this );
  288. m.copy( items, (void*)this );
  289. return m;
  290. }
  291. int
  292. Controller_Module::handle ( int m )
  293. {
  294. switch ( m )
  295. {
  296. case FL_PUSH:
  297. {
  298. if ( test_press( FL_BUTTON3 ) )
  299. {
  300. /* context menu */
  301. menu_popup( &menu() );
  302. return 1;
  303. }
  304. else
  305. return Fl_Group::handle( m );
  306. }
  307. }
  308. return Fl_Group::handle( m );
  309. }
  310. /**********/
  311. /* Engine */
  312. /**********/
  313. void
  314. Controller_Module::process ( nframes_t nframes )
  315. {
  316. THREAD_ASSERT( RT );
  317. if ( control_output[0].connected() )
  318. {
  319. float f = control_value;
  320. if ( mode() == CV )
  321. {
  322. f = *((float*)jack_input[0].buffer( nframes ));
  323. const Port *p = control_output[0].connected_port();
  324. if (p->hints.ranged )
  325. {
  326. // scale value to range.
  327. // we assume that CV values are between 0 and 1
  328. float scale = p->hints.maximum - p->hints.minimum;
  329. float offset = p->hints.minimum;
  330. f = ( f * scale ) + offset;
  331. }
  332. }
  333. // else
  334. // f = *((float*)control_output[0].buffer());
  335. *((float*)control_output[0].buffer()) = f;
  336. control_value = f;
  337. }
  338. }