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.

200 lines
5.0KB

  1. /* SpiralSynthModular
  2. * Copyleft (C) 2002 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #ifdef HAVE_CONFIG_H
  19. #include <config.h>
  20. #endif
  21. #include <iostream>
  22. #include <cstdlib>
  23. #include <FL/Fl.H>
  24. #include <FL/Fl_Tooltip.h>
  25. #include <unistd.h>
  26. #include "SpiralSynthModular.h"
  27. pthread_t loopthread;
  28. SynthModular *synth;
  29. int pthread_create_realtime (pthread_t *new_thread,
  30. void *(*start)(void *), void *arg,
  31. int priority);
  32. bool CallbackOnly = false;
  33. void audioloop(void* o)
  34. {
  35. while(1)
  36. {
  37. if (!synth->CallbackMode())
  38. {
  39. // do funky stuff
  40. synth->Update();
  41. // slow down this thread if we are not going to be using the
  42. // oss plugin. prevents maxing the CPU out for no reason.
  43. if (CallbackOnly) usleep(100);
  44. }
  45. else
  46. {
  47. // the engine is currently in callback mode, so we don't
  48. // need to do anything unless we are switched back
  49. usleep(1000000);
  50. }
  51. }
  52. }
  53. int main(int argc, char **argv)
  54. {
  55. srand(time(NULL));
  56. SpiralSynthModularInfo::Get()->LoadPrefs();
  57. bool GUI = true;
  58. bool FIFO = false;
  59. // get args
  60. string cmd_filename="";
  61. bool cmd_specd = false;
  62. string cmd_pluginPath="";
  63. // parse the args
  64. if (argc>1)
  65. {
  66. for (int a=1; a<argc; a++)
  67. {
  68. if (!strcmp(argv[a],"--NoGUI")) GUI = false;
  69. else if (!strcmp(argv[a],"--SHED_FIFO")) FIFO = true;
  70. else if (!strcmp(argv[a],"--CallbackOnly")) CallbackOnly = true;
  71. else if (!strcmp(argv[a],"-h"))
  72. {
  73. cout<<"usage: spiralsynthmodular [options] [patch.ssm]"<<endl<<endl
  74. <<"options list"<<endl
  75. <<"-h : help"<<endl
  76. <<"-v : print version"<<endl
  77. <<"--NoGUI : run without GUI (only useful when loading patch from command line"<<endl
  78. <<"--SHED_FIFO : spawn audio thread with FIFO sheduling (run as root)"<<endl
  79. <<"--CallbackOnly : prevents 100% cpu usage when idle, but makes OSS output unsable"<<endl
  80. <<"--PluginPath <PATH> : look for plugins in the specified directory"<<endl;
  81. exit(0);
  82. }
  83. else if (!strcmp(argv[a],"-v"))
  84. {
  85. cout<<VER_STRING<<endl; exit(0);
  86. }
  87. else if (!strcmp(argv[a],"--PluginPath"))
  88. {
  89. a++;
  90. cmd_pluginPath=argv[a];
  91. }
  92. else
  93. {
  94. cmd_filename = argv[1];
  95. cmd_specd = true;
  96. }
  97. }
  98. }
  99. // set some fltk defaults
  100. Fl_Tooltip::size(10);
  101. Fl::visible_focus(false);
  102. //Fl::set_font(FL_HELVETICA,FL_SCREEN);
  103. Fl::visual(FL_DOUBLE|FL_RGB);
  104. synth=new SynthModular;
  105. // setup the synth
  106. Fl_Window* win = synth->CreateWindow();
  107. synth->LoadPlugins(cmd_pluginPath);
  108. win->xclass("");
  109. if (GUI) win->show(1, argv); // prevents stuff happening before the plugins have loaded
  110. // spawn the audio thread
  111. int ret;
  112. if (FIFO) ret=pthread_create_realtime(&loopthread,(void*(*)(void*))audioloop,NULL,10);
  113. else ret=pthread_create(&loopthread,NULL,(void*(*)(void*))audioloop,NULL);
  114. pthread_t GUIThread = pthread_self();
  115. // do we need to load a patch on startup?
  116. if (cmd_specd) synth->LoadPatch(cmd_filename.c_str());
  117. if (!GUI)
  118. {
  119. // if there is no gui needed, there is nothing more to do here
  120. Fl::check();
  121. for (;;) sleep(1);
  122. }
  123. for (;;)
  124. {
  125. if (!Fl::check()) break;
  126. synth->UpdatePluginGUIs(); // deletes any if necc
  127. usleep(10000);
  128. }
  129. //pthread_cancel(loopthread);
  130. delete synth;
  131. return 1;
  132. }
  133. // nicked from Paul Barton-Davis' Ardour code :)
  134. int pthread_create_realtime (pthread_t *new_thread,
  135. void *(*start)(void *), void *arg,
  136. int priority)
  137. {
  138. pthread_attr_t *rt_attributes;
  139. struct sched_param *rt_param;
  140. int retval;
  141. rt_attributes = (pthread_attr_t *) malloc (sizeof (pthread_attr_t));
  142. rt_param = (struct sched_param *) malloc (sizeof (struct sched_param));
  143. pthread_attr_init (rt_attributes);
  144. if (seteuid (0)) {
  145. cerr << "Cannot obtain root UID for RT scheduling operations"
  146. << endl;
  147. return -1;
  148. } else {
  149. if (pthread_attr_setschedpolicy (rt_attributes, SCHED_FIFO)) {
  150. cerr << "Cannot set FIFO scheduling attributes for RT thread" << endl;
  151. }
  152. if (pthread_attr_setscope (rt_attributes, PTHREAD_SCOPE_SYSTEM)) {
  153. cerr << "Cannot set scheduling scope for RT thread" << endl;
  154. }
  155. rt_param->sched_priority = priority;
  156. if (pthread_attr_setschedparam (rt_attributes, rt_param)) {
  157. cerr << "Cannot set scheduling priority for RT thread" << endl;
  158. }
  159. }
  160. retval = pthread_create (new_thread, rt_attributes, start, arg);
  161. seteuid (getuid());
  162. return retval;
  163. }