2 * Copyleft (C) 2002 David Griffiths <dave@pawfal.org>
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.
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.
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.
26 #include <FL/Fl_Tooltip.H>
29 #include <sys/resource.h>
31 #include "SpiralSynthModular.h"
32 #include "SpiralSound/SpiralInfo.h"
34 pthread_t loopthread
,watchdogthread
;
37 char watchdog_check
= 1;
38 char gui_watchdog_check
= 1;
40 int pthread_create_realtime (pthread_t
*new_thread
,
41 void *(*start
)(void *), void *arg
,
44 bool CallbackOnly
= false;
48 /////////////////////////////////////////////////////////////
50 void watchdog (void *arg
)
52 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
55 gui_watchdog_check
= 0;
60 // gui watchdog goes off with modal dialog boxes
61 if (watchdog_check
== 0)// || gui_watchdog_check== 0)
63 cerr
<<"ssm watchdog: timeout - killing ssm"<<endl
;
64 if (watchdog_check
==0) cerr
<<"diagnosis: audio hung?"<<endl
;
65 if (gui_watchdog_check
==0) cerr
<<"diagnosis: gui starved by audio"<<endl
;
69 gui_watchdog_check
= 0;
73 ///////////////////////////////////////////////////////////////////////
75 void audioloop(void* o
)
79 if (!synth
->CallbackMode())
84 // put the brakes on if there is no blocking output running
85 if (!synth
->IsBlockingOutputPluginReady()||
93 // the engine is currently in callback mode, so we don't
94 // need to do anything unless we are switched back
102 //////////////////////////////////////////////////////
104 #include <CoreFoundation/CFBundle.h>
108 #include "GraphSort.h"
110 int main(int argc
, char **argv
)
113 // --with-plugindir=./Libraries
115 CFBundleRef main
= CFBundleGetMainBundle();
116 CFURLRef url
= main
? CFBundleCopyExecutableURL(main
) : NULL
;
117 CFStringRef path
= url
? CFURLCopyFileSystemPath(url
, kCFURLPOSIXPathStyle
) : NULL
;
118 char * dst
= (char*)CFStringGetCStringPtr(path
, 0);
120 printf("main %p url %p path %p dst %p", main
, url
, path
, dst
);
122 printf("Have a valid name '%s'\n", dst
);
126 printf("No base pathname\n");
129 SpiralInfo::Get()->LoadPrefs();
132 string cmd_filename
="";
133 bool cmd_specd
= false;
134 string cmd_pluginPath
="";
138 for (int a
=1; a
<argc
; a
++)
140 if (!strcmp(argv
[a
],"--NoGUI")) GUI
= false;
141 else if (!strcmp(argv
[a
],"--Realtime")) FIFO
= true;
142 else if (!strcmp(argv
[a
],"-h"))
144 cout
<<"usage: spiralsynthmodular [patch.ssm] [options]"<<endl
<<endl
145 <<"options list"<<endl
147 <<"-v : print version"<<endl
148 <<"--NoGUI : run without GUI (only useful when loading patch from command line"<<endl
149 <<"--Realtime : spawn audio thread with FIFO scheduling (run as root)"<<endl
150 <<"--PluginPath <PATH> : look for plugins in the specified directory"<<endl
;
153 else if (!strcmp(argv
[a
],"-v"))
155 cout
<<VER_STRING
<<endl
; exit(0);
157 else if (!strcmp(argv
[a
],"--PluginPath"))
160 cmd_pluginPath
=argv
[a
];
164 cmd_filename
= argv
[1];
170 // set some fltk defaults
171 Fl_Tooltip::size(10);
172 Fl::visible_focus(false);
173 Fl::visual(FL_DOUBLE
|FL_RGB
);
175 synth
=new SynthModular
;
178 Fl_Window
* win
= synth
->CreateWindow();
180 synth
->LoadPlugins(cmd_pluginPath
);
182 if (GUI
) win
->show(1, argv
); // prevents stuff happening before the plugins have loaded
184 // spawn the audio thread
187 pthread_create_realtime(&watchdogthread
,(void*(*)(void*))watchdog
,NULL
,sched_get_priority_max(SCHED_FIFO
));
188 pthread_create_realtime(&loopthread
,(void*(*)(void*))audioloop
,NULL
,sched_get_priority_max(SCHED_FIFO
)-1);
192 pthread_create(&loopthread
,NULL
,(void*(*)(void*))audioloop
,NULL
);
193 // reduce the priority of the gui
194 if (setpriority(PRIO_PROCESS
,0,20)) cerr
<<"Could not set priority for GUI thread"<<endl
;
197 // do we need to load a patch on startup?
198 if (cmd_specd
) synth
->LoadPatch(cmd_filename
.c_str());
202 // if there is no gui needed, there is nothing more to do here
209 if (!Fl::check()) break;
210 synth
->UpdatePluginGUIs(); // deletes any if necc
212 gui_watchdog_check
=1;
215 //pthread_cancel(loopthread);
221 // nicked from Paul Barton-Davis' Ardour code :)
222 int pthread_create_realtime (pthread_t
*new_thread
,
223 void *(*start
)(void *), void *arg
,
227 pthread_attr_t
*rt_attributes
;
228 struct sched_param
*rt_param
;
231 rt_attributes
= (pthread_attr_t
*) malloc (sizeof (pthread_attr_t
));
232 rt_param
= (struct sched_param
*) malloc (sizeof (struct sched_param
));
234 pthread_attr_init (rt_attributes
);
237 cerr
<< "Cannot obtain root UID for RT scheduling operations"
243 if (pthread_attr_setschedpolicy (rt_attributes
, SCHED_FIFO
)) {
244 cerr
<< "Cannot set FIFO scheduling attributes for RT thread" << endl
;
248 if (pthread_attr_setscope (rt_attributes
, PTHREAD_SCOPE_SYSTEM
)) {
249 cerr
<< "Cannot set scheduling scope for RT thread" << endl
;
253 rt_param
->sched_priority
= priority
;
254 if (pthread_attr_setschedparam (rt_attributes
, rt_param
)) {
255 cerr
<< "Cannot set scheduling priority for RT thread" << endl
;
260 retval
= pthread_create (new_thread
, rt_attributes
, start
, arg
);