Capability fix (rt'ing engine instead of gui) - Alex
authorterminatorX <>
Tue, 19 Aug 2003 17:38:42 +0000 (17:38 +0000)
committerterminatorX <>
Tue, 19 Aug 2003 17:38:42 +0000 (17:38 +0000)
src/main.cc
src/tX_audiodevice.cc
src/tX_dialog.cc
src/tX_engine.cc
src/tX_engine.h
src/tX_loaddlg.cc
src/tX_vtt.cc
src/tX_vtt.h
src/tX_vttgui.cc

index dc84c7b4d018d37b1084e49bef09d03fec90b9a0..609819f2a31baae1855378184c9985e0ba377243 100644 (file)
 #include "tX_vtt.h"
 #endif
 
+#ifdef USE_SCHEDULER
+#include <sched.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
 #ifdef USE_JACK        
 void jack_check()
 {
@@ -239,9 +245,12 @@ int main(int argc, char **argv)
 #ifdef USE_JACK        
        tX_jack_client::init();
 #endif 
+
+#ifdef USE_SCHEDULER
+       tX_debug("main() GUI thread is p:%i, t:%i and has policy %i.", getpid(), pthread_self(), sched_getscheduler(getpid()));
+#endif 
        
        create_mastergui(globals.width, globals.height);
-
        
        if (globals.show_nag) {
                while (!timesup) {
index 39d5503dde3137518cf74e06b434f7ad18238bec..e7e4d5a789cba3881fc3c721752d86f0c55674c1 100644 (file)
@@ -321,6 +321,7 @@ pcm_handle(NULL) {}
 
 void tX_audiodevice_alsa :: play(int16_t *buffer)
 {
+       int underrun_ctr=0;
        snd_pcm_sframes_t pcmreturn;
 #ifdef BIG_ENDIAN_MACHINE
        swapbuffer (buffer, samples_per_buffer);
@@ -340,6 +341,11 @@ void tX_audiodevice_alsa :: play(int16_t *buffer)
 #else  
                pcmreturn = snd_pcm_mmap_writei(pcm_handle, buffer, samples_per_buffer >> 1);
 #endif
+               underrun_ctr++;
+               if (underrun_ctr>100) {
+                       tX_error("tX_audiodevice_alsa::play() more than 10 EPIPE cycles. Giving up.");
+                       break;
+               }
                //tX_warning("ALSA: ** buffer underrun **");
        }
        
index defcd52d1f5b8164a89b5b28cf08401d935d5091..5b96e3be57b584537f802ce11f9f6cbb2006f91a 100644 (file)
@@ -55,6 +55,7 @@
 
 #ifdef USE_SCHEDULER
 #include <sched.h>
+#include <pthread.h>
 #endif
 
 #ifdef USE_JACK
@@ -699,10 +700,14 @@ void show_about(int nag)
                add_about_wid_fix(sep);
 
                char buffer[4096];
-               int prio=sched_getscheduler(tX_engine::get_instance()->get_pid());
+               
+               int policy=-1;
+               struct sched_param parm;
+               
+               pthread_getschedparam(tX_engine::get_instance()->get_thread_id(), &policy, &parm);
                char prio_str[32]="";
                
-               switch (prio) {
+               switch (policy) {
                        case SCHED_OTHER:
                                strcpy(prio_str, "SCHED_OTHER");
                                break;
@@ -716,7 +721,7 @@ void show_about(int nag)
                                break;
                        
                        default:
-                               sprintf(prio_str, "UNKOWN (%i)", prio);
+                               sprintf(prio_str, "UNKOWN (%i)", policy);
                }
                
                sprintf(buffer, "Audio engine scheduling policy: %s.\n(Note: SCHED_FIFO equals realtime scheduling.)", prio_str);
index f2f403d5ddbd525ca1d26b47c4798df265586f19..b839a841a8c2bd9e08ed583f68c198065ee559fa 100644 (file)
@@ -158,15 +158,15 @@ void *engine_thread_entry(void *engine_void) {
 
 #ifdef USE_SCHEDULER
        pid_t pid=getpid();
+       struct sched_param parm;
 
 #ifdef USE_CAPABILITIES
        if (have_nice_capability()) {
                if (globals.use_realtime) {
-                       struct sched_param parm;
-       
                        sched_getparam(pid, &parm);
                        parm.sched_priority=sched_get_priority_max(SCHED_FIFO);
-                       if (sched_setscheduler(pid, SCHED_FIFO, &parm)) {
+                                               
+                       if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &parm)) {
                                tX_error("engine_thread_entry(): failed to set realtime priority.");
                        } else {
                                tX_debug("engine_thread_entry(): set SCHED_FIFO via capabilities.");
@@ -176,9 +176,10 @@ void *engine_thread_entry(void *engine_void) {
                tX_warning("engine_thread_entry(): can't set SCHED_FIFO -> lacking capabilities.");
        }
 #endif //USE_CAPABILITIES
-       engine->set_pid(pid);
+       int policy=0;
        
-       if (sched_getscheduler(pid)!=SCHED_FIFO) {
+       pthread_getschedparam(pthread_self(), &policy, &parm);
+       if (policy!=SCHED_FIFO) {
                tX_warning("engine_thread_entry() - engine has no realtime priority scheduling.");
        }
 #endif //USE_SCHEDULER
@@ -187,10 +188,14 @@ void *engine_thread_entry(void *engine_void) {
        /* Create the client now, so the user has something to connect to. */
        tX_jack_client::get_instance();
 #endif 
+
+#ifdef USE_SCHEDULER
+       tX_debug("engine_thread_entry() engine thread is p: %i, t: %i and has policy %i.", getpid(), pthread_self(), sched_getscheduler(getpid()));
+#endif
        
        engine->loop();
        
-       tX_debug("engine_thread_entry() - Engine thread terminating.");
+       tX_debug("engine_thread_entry() engine thread terminating.");
        
        pthread_exit(NULL);
 }
@@ -201,9 +206,6 @@ tX_engine :: tX_engine() {
        pthread_mutex_init(&start, NULL);
        pthread_mutex_lock(&start);
        thread_terminate=false;
-#ifdef USE_SCHEDULER
-       pid=-1;
-#endif 
        
        /* Creating the actual engine thread.. */
 #ifdef USE_SCHEDULER   
@@ -211,7 +213,7 @@ tX_engine :: tX_engine() {
                pthread_attr_t pattr;
                struct sched_param sparm;
                
-               tX_debug("tX_engine() - Have root privileges - using SCHED_FIFO.");
+               tX_debug("tX_engine() - setting SCHED_FIFO.");
                
                pthread_attr_init(&pattr);
                pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_JOINABLE);
index 281acf96fafbe9ba421fdaa792021539598e58ee..f1f12a0b62a3b29ef6863976c60286ed1ceb0e82 100644 (file)
@@ -82,14 +82,7 @@ class tX_engine {
        tX_midiin *get_midi() { return midi; }
 #endif 
 
-#ifdef USE_SCHEDULER
-       private:
-       pid_t pid;
-       
-       public:
-       pid_t get_pid() { return pid; }
-       void set_pid(pid_t value) { pid=value; }
-#endif
+       pthread_t get_thread_id() { return thread; }
        
        static tX_engine *get_instance();
        tX_engine();
index afe986f89bff710b7fe821f43515aa47e149cad5..4d6c2aaba530b7c75daa86d5c9cae3a55ea2ebdd 100644 (file)
@@ -111,6 +111,8 @@ int ld_create_loaddlg(int mode, int count)
 char *strip_path(char *name)
 {
        char *tmp;
+
+       if (!name) return NULL;
        
        tmp=strrchr(name, (int) '/');
        
index 883320ac656d825910fb6f0d922a0e7e8ecee903..da78b3781713891d6b97ab5e37366315fd7afc8a 100644 (file)
@@ -98,6 +98,8 @@ int vtt_class::mix_buffer_size=0;
 vtt_class :: vtt_class (int do_create_gui)
 {      
        vtt_amount++;
+       cleanup_required=false;
+       
        sprintf (name, "Turntable %i", vtt_amount);
        strcpy(filename, "NONE");
        buffer=NULL;
@@ -872,18 +874,16 @@ int16_t * vtt_class :: render_all_turntables()
                        }
                        
                        if (master_triggered) {
-                               pthread_mutex_unlock(&render_lock);
                                for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
                                        if ((*vtt)->is_sync_client)     {
                                                if ((*vtt)->sync_countdown)     {
                                                        (*vtt)->sync_countdown--;
                                                } else {
                                                        (*vtt)->sync_countdown=(*vtt)->sync_cycles;
-                                                       (*vtt)->trigger();
+                                                       (*vtt)->trigger(false);
                                                }
                                        }
                                }
-                               pthread_mutex_lock(&render_lock);
                        }
                        
                        vtt=render_list.begin();
@@ -1027,79 +1027,77 @@ void vtt_class :: forward_all_turntables()
        }
 }
 
-
-int vtt_class :: trigger()
+void vtt_class :: retrigger() 
 {
-       list <vtt_fx *> :: iterator effect;
-
-       if (!buffer) return (1);
-       
-       if (!is_playing) pthread_mutex_lock(&render_lock);
-       
        if (res_pitch>=0) pos_f=0;
        else pos_f=maxpos;
+               
        fade=NEED_FADE_OUT;
        speed=res_pitch;
        speed_real=res_pitch;
        speed_target=res_pitch;
        want_stop=0;
 
-       /* activating plugins */
-       for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
-       {
-               (*effect)->activate();
-       }
-
        max_value=0;
        
-       if (is_sync_master)
-       {
+       if (is_sync_master)     {
                master_triggered=1;
                master_triggered_at=0;
        }
+}
+
+int vtt_class :: trigger(bool need_lock)
+{
+       list <vtt_fx *> :: iterator effect;
+
+       if (!buffer) return 1;
        
-       if (!is_playing)
-       {
-               is_playing=1;
+       retrigger();
        
-               if (is_sync_master) 
-               {
+       if (!is_playing) {
+               if (need_lock) pthread_mutex_lock(&render_lock);
+               is_playing=1;
+               cleanup_required=false;
+               
+               /* activating plugins */
+               for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
+                       (*effect)->activate();
+               }
+               
+               if (is_sync_master)  {
                        render_list.push_front(this);           
-               }               
-               else
-               {
+               } else {
                        render_list.push_back(this);
                }
-               pthread_mutex_unlock(&render_lock);
+               
+               if (need_lock) pthread_mutex_unlock(&render_lock);              
        }
-       return(0);
-}
 
-static bool do_unlock=true;
+       return 0;
+}
 
+/* call this only when owning render_lock. */
 int vtt_class :: stop_nolock()
 {
        list <vtt_fx *> :: iterator effect;
 
-       if ((!is_playing) && do_unlock) {
-               pthread_mutex_unlock(&render_lock);
-               return(1);
+       if (!is_playing) {
+               return 1;
        }
+       
        render_list.remove(this);
        want_stop=0;
-
        is_playing=0;
        max_value=0;
 
-       cleanup_vtt(this);
-       //sync_countdown=0;
+       cleanup_required=true;
        
        /* deactivating plugins */
        for (effect=fx_list.begin(); effect != fx_list.end(); effect++) {
                (*effect)->deactivate();
        }
        
-       return(0);
+       return 0;
 }
 
 int vtt_class :: stop()
@@ -1107,13 +1105,7 @@ int vtt_class :: stop()
        int res;
        
        pthread_mutex_lock(&render_lock);
-
-       do_unlock=false;
-       
        res=stop_nolock();
-
-       do_unlock=true;
-       
        pthread_mutex_unlock(&render_lock);
 
        return(res);
@@ -1121,14 +1113,11 @@ int vtt_class :: stop()
 
 void vtt_class :: set_sync_master(int master)
 {
-       if (master)
-       {
+       if (master) {
                if (sync_master) sync_master->set_sync_master(0);
                sync_master=this;
                is_sync_master=1;
-       }
-       else
-       {
+       } else {
                if (sync_master==this) sync_master=0;
                is_sync_master=0;
                gui_clear_master_button(this);
@@ -1156,14 +1145,12 @@ void vtt_class :: set_master_volume(f_prec new_volume)
        master_volume=new_volume;
        globals.volume=new_volume;
        
-       if (main_list.size()>0)
-       {
+       if (main_list.size()>0) {
                vol_channel_adjust=sqrt((f_prec) main_list.size());
                res_master_volume=master_volume/vol_channel_adjust;             
        }
                
-       for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
-       {
+       for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
                (*vtt)->recalc_volume();
        }
 }
@@ -1173,8 +1160,7 @@ void vtt_class :: set_master_pitch(f_prec new_pitch)
        list <vtt_class *> :: iterator vtt;
        
        globals.pitch=new_pitch;
-       for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
-       {
+       for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
                (*vtt)->recalc_pitch();
        }
 }
@@ -1186,8 +1172,7 @@ void vtt_class :: focus_no(int no)
 
        focused_vtt=NULL;
        
-       for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
-       {
+       for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++) {
                if (i==no) {
                        focused_vtt=(*vtt);
                }
@@ -1198,10 +1183,8 @@ void vtt_class :: focus_next()
 {
        list <vtt_class *> :: iterator vtt;
        
-       if (!focused_vtt)
-       {
-               if (main_list.size())
-               {
+       if (!focused_vtt) {
+               if (main_list.size()) {
                        focused_vtt=(*main_list.begin());
                }
                return;
@@ -1240,14 +1223,11 @@ void vtt_class :: focus_next()
 
 void vtt_class :: set_scratch(int newstate)
 {
-       if (newstate)
-       {
+       if (newstate) {
                sp_spin.receive_input_value(0);
                do_scratch=1;
                sense_cycles=globals.sense_cycles;
-       }
-       else
-       {
+       } else {
                sp_spin.receive_input_value(1);
                do_scratch=0;
        }
@@ -1546,7 +1526,6 @@ void vtt_class :: delete_all()
        seq_update();
 }
 
-
 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
        xmlNodePtr root=xmlDocGetRootElement(doc);
        int elementFound=0;
@@ -1641,11 +1620,11 @@ int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
 
 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
 {
-       vtt_class *hmmpg;
-       hmmpg = new vtt_class(1);
-       gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
-       gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
-       if (fn) hmmpg->load_file(fn);
+       vtt_class *new_tt;
+       new_tt = new vtt_class(1);
+       gtk_box_pack_start(GTK_BOX(ctrl), new_tt->gui.control_box, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(audio), new_tt->gui.audio_box, TRUE, TRUE, 0);
+       if (fn) new_tt->load_file(fn);
 }
 
 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
@@ -1664,18 +1643,15 @@ void vtt_class :: effect_up(vtt_fx *effect)
        
        if ((*fx_list.begin())==effect) return;
        
-       for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
-       {
-               if ((*i) == effect)
-               {
+       for (previous=i=fx_list.begin(); i != fx_list.end(); i++) {
+               if ((*i) == effect) {
                        ok=1;
                        break;
                }
                previous=i;
        }
        
-       if (ok)
-       {       
+       if (ok) {       
                pthread_mutex_lock(&render_lock);
                fx_list.remove(effect);
                fx_list.insert(previous, effect);
@@ -1694,17 +1670,14 @@ void vtt_class :: effect_down(vtt_fx *effect)
 
        debug_fx_stack();
                
-       for (i=fx_list.begin(); i != fx_list.end(); i++)
-       {
-               if ((*i) == effect)
-               {
+       for (i=fx_list.begin(); i != fx_list.end(); i++) {
+               if ((*i) == effect) {
                        ok=1;
                        break;
                }
        }
        
-       if ((ok) && (i!=fx_list.end()))
-       {
+       if ((ok) && (i!=fx_list.end())) {
                i++;
                if (i==fx_list.end()) return;
                i++;
@@ -1717,7 +1690,7 @@ void vtt_class :: effect_down(vtt_fx *effect)
                pthread_mutex_unlock(&render_lock);
        }
        
-debug_fx_stack();      
+       debug_fx_stack();       
 }
 
 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
index a64b6b23179c9631ae391b32a30da8097019a166..2615cd21e208dd7bd35024e648a3282e095885e2 100644 (file)
@@ -271,10 +271,13 @@ class vtt_class
        static void focus_next();
        static void unfocus();
        static void set_sample_rate(int samplerate);
-       int trigger();
+       void retrigger();
+       int trigger(bool need_lock=true);
        
        int stop();
        int stop_nolock();
+       bool cleanup_required;
+       bool needs_cleaning_up() { return cleanup_required; }
        
        int save(FILE *, gzFile rz, char *indent);
        static int save_all(FILE *, gzFile rz);
index 8b4d1390c4b2c0d67f5840181f449f41f03691ac..e093c88d3c63f000485a16f7829fad1c5527e903 100644 (file)
@@ -251,7 +251,7 @@ void drop_file(GtkWidget *widget, GdkDragContext *context,
                if (fn) fn++; else fn=(char *) selection_data->data;
        }
 
-       load_part(realfn, vtt);
+       load_part(fn, vtt);
 
        if (realfn) g_free(realfn);
        if (host) g_free(host);
@@ -1276,6 +1276,14 @@ void delete_gui(vtt_class *vtt)
        if (vtt->gui.ladspa_menu) gtk_widget_destroy(vtt->gui.ladspa_menu);
 }
 
+void cleanup_vtt(vtt_class *vtt)
+{
+       gtk_tx_cleanup_pos_display(GTK_TX(vtt->gui.display));   
+       gtk_tx_flash_set_level(vtt->gui.flash, 0.0);
+       gtk_tx_flash_clear(vtt->gui.flash);
+       vtt->cleanup_required=false;
+}
+
 void update_all_vtts()
 {
        list <vtt_class *> :: iterator vtt;
@@ -1283,23 +1291,19 @@ void update_all_vtts()
        
        for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
        {
-               if ((*vtt)->is_playing)
-               {
+               if ((*vtt)->is_playing) {
                        gtk_tx_update_pos_display(GTK_TX((*vtt)->gui.display), (*vtt)->pos_i, (*vtt)->mute);
                        temp=(*vtt)->max_value*(*vtt)->res_volume*vtt_class::vol_channel_adjust;
                        (*vtt)->max_value=0;
                        gtk_tx_flash_set_level((*vtt)->gui.flash, temp);
                }
+               
+               if ((*vtt)->needs_cleaning_up()) {
+                       cleanup_vtt((*vtt));
+               }
        }
 }
 
-void cleanup_vtt(vtt_class *vtt)
-{
-               gtk_tx_cleanup_pos_display(GTK_TX(vtt->gui.display));   
-               gtk_tx_flash_set_level(vtt->gui.flash, 0.0);
-               gtk_tx_flash_clear(vtt->gui.flash);
-}
-
 void cleanup_all_vtts()
 {
        list <vtt_class *> :: iterator vtt;