home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / mod-0.000 / mod-0 / mod / controller.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-29  |  19.2 KB  |  930 lines

  1. /*
  2.  *  controller.c - Main loop and interactive interface.
  3.  *
  4.  *  (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9. #include <unistd.h>
  10. #include <sys/time.h>
  11. #include <sys/wait.h>
  12. #include <errno.h>
  13. #include <time.h>
  14. #include <sys/soundcard.h>
  15. #include <dirent.h>
  16.  
  17. #include "mod.h"
  18. #include "message.h"
  19. #include "ncurses.h"
  20.  
  21. /* External variables */
  22.  
  23. SEQ_DECLAREBUF();
  24. extern int seqfd, gus_dev;
  25. extern struct mod_info M;
  26. extern struct options default_opt, opt;
  27. extern char workdir[PATH_MAX+1];
  28.  
  29. extern pid_t pid_main, pid_player;
  30. extern int total_time;     /* Total time spent playing modules */
  31.  
  32. extern int nr_songs, nr_files;
  33. extern int swin_LINES;     /* For page-DN/UP */
  34. extern int nr_dirs;
  35.  
  36. /* Variables */
  37.  
  38. int ack_pipe[2];           /* Player acks main */
  39. int player2main_synced[2]; /* Message from player to main (synced) */
  40. int main2player[2];        /* Message from main to player */
  41.  
  42. int nr_visible_voices;     /* Maximum number of visible voices */
  43. char loaded;               /* True when a module has been loaded */
  44. char quit;                 /* Set when program is aborting     */
  45.  
  46. /* Local variables */
  47.  
  48. static int maxfd;
  49. static int first_voice;   /* First voice to be shown on screen */
  50.  
  51. static int first_sample;  /* First sample shown on screen    */
  52. static char playing;      /* Are playing or idling           */
  53. static char selecting;    /* Are we selecting a new song?    */
  54.  
  55. static int starting_time; /* When module was started */
  56. static int restart_time;  /* When player had to be restarted last */
  57.  
  58. static int cur_filenr;    /* Current file active (real order) */
  59. static int saved_filenr;  /* Saved file# in case we abort file-select */
  60. static char saved_dir[PATH_MAX+1]; /* Ditto with workdir */
  61.  
  62. static char voice_toggle; /* Voice-toggling (2 keys) */
  63.  
  64. /* Variables for commands requiring player to back up */
  65.  
  66. static int pending_restart, pending_info;
  67. static int last_speed, last_tempo, last_pos, last_line;
  68.  
  69. /* Constants */
  70.  
  71. #define STATUS_READY    1
  72. #define STATUS_PLAYING  2
  73.  
  74.  
  75. void main_loop(void)
  76. {
  77.     fd_set rset;
  78.     int nr;
  79.  
  80.     if(opt.quiet && nr_songs == 0)
  81.     return;
  82.     
  83.     maxfd=getdtablesize();
  84.     draw_screen();
  85.     set_voice_detail(1); /* Start with highest detail */
  86.     
  87.     set_status(STATUS_READY);
  88.     selecting=quit=0;
  89.     cur_filenr=first_voice=0;
  90.  
  91.     if(opt.play_list) {
  92.     if(opt.auto_next) {
  93.         cur_filenr=seqidx_to_fileidx(0);
  94.         load_next_module();
  95.     }
  96.     else {
  97.         start_selecting();
  98.         print_selectingbar();
  99.         print_files(cur_filenr);
  100.     }
  101.     }
  102.     else {
  103.     strcpy(saved_dir, workdir);
  104.     init_dir(workdir);
  105.     start_selecting();
  106.     print_selectingbar();
  107.     print_files(cur_filenr);
  108.     }
  109.  
  110.     while(!quit) {
  111.     FD_ZERO(&rset);
  112.     FD_SET(STDIN_FILENO, &rset);
  113.     if(loaded)
  114.         FD_SET(seqfd, &rset);
  115.     if((nr=select(maxfd, &rset, 0, 0, 0)) >= 0) {
  116.         if(FD_ISSET(STDIN_FILENO, &rset))
  117.         read_key();
  118.         else if(FD_ISSET(seqfd, &rset))
  119.         read_sequencer();
  120.         if(!nr)
  121.         warning("nr == 0 ?!?!?\n");
  122.     }
  123.     else {
  124.         if(errno != EINTR)
  125.         error("select() failed (errno=%d).\n", errno);
  126.     }
  127.     }
  128. }
  129.  
  130.  
  131. void load_next_module(void)
  132. {
  133.     struct mod_message mess;
  134.     char buf[80];
  135.     int nr, tmp;
  136.  
  137.     voice_toggle=-1; /* Forget previous keypress */
  138.  
  139.     /* Release resources used by the previous module */
  140.     if(loaded) {
  141.     mess.type=MESSAGE_EXIT;
  142.     send_to_player(&mess);
  143.     
  144.     drain_pipes(0);
  145.     do {
  146.         if((nr=waitpid(pid_player, 0, 0)) == -1 && errno != EINTR)
  147.         error("waitpid() failed in main.\n");
  148.     }
  149.     while(nr != pid_player);
  150.     drain_pipes(1);
  151.     
  152.     free_module();
  153.     loaded=0;
  154.     }
  155.  
  156.     first_voice=0;
  157.     print_channelnumbers(first_voice);
  158.     clear_screen();
  159.     clear_all_info();
  160.  
  161.     /* Make sure sequencer is clean */
  162.     cleanup_sound();
  163.     init_sound();
  164.  
  165.     /* Try loading a module until we succeed or abort */
  166.     while(!quit) {
  167.     get_module(fileidx_to_seqidx(cur_filenr));    
  168.     print_filename(fileidx_to_seqidx(cur_filenr));
  169.     tmp=load_module();
  170.     chdir(workdir); /* Restore current directory after load_module() */
  171.     if(!tmp) {
  172.         if(quit != QUIT_SIGNAL) {
  173.         print_status("Loading failed");
  174.         sleep(1);
  175.         free_module();
  176.         loaded=0;
  177.         if(should_autoselect_next()) {
  178.             select_next_file();
  179.             continue;
  180.         }
  181.         else {
  182.             clear_all_info();
  183.             set_status(STATUS_READY);
  184.             start_selecting();
  185.             print_selectingbar();
  186.             print_files(cur_filenr);
  187.             return;
  188.         }
  189.         }
  190.         else {
  191.         return; /* Leave if we got a Ctrl-C */
  192.         }
  193.     }
  194.     else
  195.         break; /* Found module, leave load-loop */
  196.     }    
  197.  
  198.     if(quit) {   /* Is this one still needed? */
  199.     return;
  200.     }
  201.  
  202.     switch(pid_player=fork()) {
  203.       case -1:
  204.     error("Fork failed.\n");
  205.     break;
  206.     
  207.       case 0:  /* Child - player */
  208.     play_module();
  209.     cleanup_sound();
  210.     exit(0);
  211.     break;
  212.     
  213.       default: /* Parent */
  214.     }
  215.     
  216.     starting_time=restart_time=time(0);
  217.     
  218.     pending_restart=0;
  219.     first_sample=1;
  220.     loaded=1;
  221.  
  222.     last_speed=6; /* Defaults if a key is hit b4 1st line is played */
  223.     last_tempo=125;
  224.  
  225.     set_voice_detail(opt.voice_detail);
  226.     
  227.     clear_screen();
  228.     print_samples(1);
  229.     set_status(STATUS_PLAYING);
  230.     print_channelnumbers(first_voice);
  231.     
  232.     read(STDIN_FILENO, buf, 80); /* Flush input */
  233. }
  234.  
  235.  
  236. char *basename(char *s)
  237. {
  238.     int i;
  239.     for(i=strlen(s)-1; i >=0 && s[i] != '/'; --i)
  240.     ;
  241.     return &s[++i];
  242. }
  243.  
  244.  
  245. void read_key(void)
  246. {
  247.     struct mod_message mess;
  248.     int ch, tmp;
  249.     char tmpname[NAME_MAX+1];
  250.     char c;
  251.     char dotdot=0, done;
  252.  
  253.     if(opt.verbose || opt.quiet) {
  254.     read(STDIN_FILENO, &c, 1);
  255.     ch=c;
  256.     if(opt.quiet)
  257.         return;
  258.     }
  259.     else
  260.     ch=getch();
  261.  
  262.     if(!(ch >= '0' && ch <= '9'))
  263.     voice_toggle=-1;
  264.     
  265.     /* Keys always available */
  266.     done=1;
  267.     switch(ch) {
  268.       case KEY_F(1):
  269.       case 'h':
  270.     print_minihelp();
  271.     break;
  272.       case 'q':
  273.     mess.type=MESSAGE_EXIT;
  274.     send_to_player(&mess);
  275.     quit=QUIT_QUIT;
  276.     if(playing)
  277.         total_time+=time(0)-restart_time;
  278.     break;
  279.       case '+':
  280.     change_mastervolume(5);
  281.     break;
  282.       case '-':
  283.     change_mastervolume(-5);
  284.     break;
  285.       case 'm':    
  286.     change_mastervolume(0);
  287.     break;
  288. #if 0
  289.       case '*':
  290.     debug("Main sending NOP.\n");
  291.     mess.type=MESSAGE_NOP;
  292.     write(main2player[PIPE_WRITE], &mess, sizeof(mess));
  293.     break;
  294. #endif
  295.       default:
  296.     done=0;
  297.     }
  298.  
  299.     if(done)      /* Ugly but saves time */
  300.     goto skip;
  301.  
  302.     if(selecting) {
  303.     switch(ch) {
  304.       case KEY_UP:
  305.       case 'p':
  306.         cur_filenr=MAX(cur_filenr-1, 0);
  307.         print_files(cur_filenr);
  308.         break;
  309.       case KEY_DOWN:
  310.       case 'n':
  311.         cur_filenr=MIN(cur_filenr+1, nr_files-1);
  312.         print_files(cur_filenr);
  313.         break;
  314.       case KEY_PPAGE:
  315.       case 'P':
  316.         cur_filenr=MAX(cur_filenr-swin_LINES/2, 0);
  317.         print_files(cur_filenr);
  318.         break;
  319.       case KEY_NPAGE:
  320.       case 'N':
  321.         cur_filenr=MIN(cur_filenr+swin_LINES/2, nr_files-1);
  322.         print_files(cur_filenr);
  323.         break;
  324.       case KEY_HOME:
  325.         cur_filenr=0;
  326.         print_files(cur_filenr);
  327.         break;
  328.       case KEY_END:
  329.         cur_filenr=nr_files-1;
  330.         print_files(cur_filenr);
  331.         break;
  332.       case '\n':
  333.         if(!is_dir(cur_filenr)) { /* is_dir() == 0 when opt.play_list */
  334.         do_select_file();
  335.         if(playing)
  336.             total_time+=time(0)-restart_time;
  337.         load_next_module();
  338.         }
  339.         else {
  340.         if(!strcmp("..", get_dirnamestring(cur_filenr)))
  341.             dotdot=1;
  342.         chdir(get_dirnamestring(cur_filenr));
  343.           yucky_goto:
  344.         strcpy(tmpname, basename(workdir));
  345.         getcwd(workdir, PATH_MAX); /* Change working directory */
  346.         init_dir(workdir);
  347.         cur_filenr=(dotdot ? name_to_filenr(tmpname) : 0);
  348.         print_selectingbar();
  349.         print_files(cur_filenr);
  350.         }
  351.         break;
  352.       case 'u':
  353.         if(opt.play_list || !strcmp("/", workdir))
  354.         break;
  355.         chdir("..");
  356.         dotdot=1;
  357.         goto yucky_goto;
  358.       case 'l':
  359.         if(!loaded)
  360.         return;
  361.  
  362.         abort_selecting();
  363.         print_channelnumbers(first_voice);
  364.         if(playing && !default_opt.noscroll)
  365.         print_line(last_pos, last_line, first_voice);
  366.         else
  367.         clear_screen();
  368.         break;
  369.       default: /* All other keys ignored */
  370.     }
  371.     }
  372.     else {
  373.     /* The following keys are available only when we have a loaded song */
  374.     if(loaded) {
  375.         switch(ch) {
  376.           case KEY_RIGHT:
  377.         first_voice=
  378.             MAX(0, MIN(first_voice+1, M.nr_voices-nr_visible_voices));
  379.         print_channelnumbers(first_voice);
  380.         break;
  381.           case KEY_LEFT:
  382.         first_voice=MAX(first_voice-1, 0);
  383.         print_channelnumbers(first_voice);
  384.         break;
  385.           case 'f':
  386.         if(playing) {
  387.             pending_restart=MESSAGE_JUMPPATTERN;
  388.             pending_info=1;
  389.             if(!selecting)
  390.             clear_screen();
  391.         }
  392.         else {
  393.             last_pos=MIN(last_pos+1, M.songlength-1);
  394.             print_pos(last_pos, 0);
  395.         }
  396.         break;
  397.           case 'b':
  398.         if(playing) {
  399.             pending_info=-1;
  400.             pending_restart=MESSAGE_JUMPPATTERN;
  401.             if(!selecting)
  402.             clear_screen();
  403.         }
  404.         else {
  405.             last_pos=MAX(last_pos-1, 0);
  406.             print_pos(last_pos, 0);
  407.         }
  408.         break;
  409.           case 'r':
  410.         set_status(STATUS_PLAYING);
  411.         pending_restart=MESSAGE_RESTART;
  412.         handle_restart(42); /* Done here as no lines coming */
  413.         clear_screen();
  414.         break;
  415.           case KEY_UP:
  416.           case 'a':
  417.         first_sample=MAX(first_sample-1, 1);
  418.         print_samples(first_sample);
  419.         break;
  420.           case KEY_DOWN:
  421.           case 'z':
  422.         first_sample=MAX(1, MIN(first_sample+1, M.nr_samples-7));
  423.         print_samples(first_sample);
  424.         break;
  425.           case KEY_NPAGE:
  426.         first_sample=MAX(1, MIN(first_sample+8, M.nr_samples-7));
  427.         print_samples(first_sample);
  428.         break;
  429.           case KEY_PPAGE:
  430.         first_sample=MAX(first_sample-8, 1);
  431.         print_samples(first_sample);
  432.         break;
  433.           case KEY_HOME:
  434.         first_sample=1;
  435.         print_samples(first_sample);
  436.         break;
  437.           case KEY_END:
  438.         first_sample=MAX(1, M.nr_samples-7);
  439.         print_samples(first_sample);
  440.         break;
  441.           case '\n':
  442.         if(playing) {
  443.             set_status(STATUS_READY);
  444.             pending_restart=MESSAGE_STOP;
  445.             total_time+=time(0)-restart_time; /* Must be done here
  446.                                * as status=ready.
  447.                                */
  448.             clear_screen();
  449.         }
  450.         else {
  451.             starting_time=time(0);
  452.             pending_restart=MESSAGE_JUMPPATTERN;
  453.             pending_info=0;
  454.             handle_restart(last_pos);   /* Done here as no lines are
  455.                              * sent from player.
  456.                          */
  457.             set_status(STATUS_PLAYING); /* _after_ restart */
  458.         }
  459.         break;
  460.           case '0': case '1': case '2': case '3': case '4':
  461.           case '5': case '6': case '7': case '8': case '9':
  462.         if(M.nr_voices <= 9) { /* Single-key mode */
  463.             tmp=ch-'0';
  464.             voice_toggle=-1;
  465.             if(tmp == 0 || tmp > M.nr_voices)
  466.             break;
  467.         }
  468.         else { /* Double-key mode */
  469.             if(voice_toggle == -1) { /* First key */
  470.             voice_toggle=ch-'0';
  471.             if(voice_toggle*10 > M.nr_voices)
  472.                 voice_toggle=-1;
  473.             break;
  474.             }
  475.             else { /* Second key */
  476.             tmp=voice_toggle*10+ch-'0';
  477.             voice_toggle=-1;
  478.             if(!tmp || tmp > M.nr_voices)
  479.                 break;
  480.             }
  481.         }
  482.         tmp--;
  483.         tmp=1<<tmp;
  484.         opt.active_voices=(opt.active_voices&(~tmp))|
  485.             ((~(opt.active_voices&tmp))&tmp);
  486.         
  487.         if(playing) {
  488.             pending_info=0;
  489.             pending_restart=MESSAGE_JUMPPATTERN;
  490.             if(!selecting)
  491.             clear_screen();
  492.         }
  493.         print_channelnumbers(first_voice);
  494.         break;
  495.           default:
  496.         }
  497.         }
  498.     
  499.     /* Keys available anytime we are not selecting a new file */
  500.     switch(ch) {
  501.       case ' ':
  502.       case 'n':
  503.         select_next_file();
  504.         if(playing)
  505.         total_time+=time(0)-restart_time;
  506.         load_next_module();
  507.         break;
  508.       case 'p':
  509.         select_prev_file();
  510.         if(playing)
  511.         total_time+=time(0)-restart_time;
  512.         load_next_module();
  513.         break;
  514.       case 'l':
  515.         start_selecting();
  516.         print_selectingbar();
  517.         print_files(cur_filenr);
  518.         break;
  519.  
  520.       case 's':
  521.         if(default_opt.noscroll) {
  522.         default_opt.noscroll=0;
  523.         if(playing)
  524.             print_line(last_pos, last_line, first_voice);
  525.         }
  526.         else {
  527.         clear_screen();
  528.         default_opt.noscroll=1;
  529.         }
  530.         break;
  531.       case 'v':
  532.         if(nr_visible_voices == 4)
  533.         nr_visible_voices=9;
  534.         else if(nr_visible_voices == 9)
  535.         nr_visible_voices=17;
  536.         else
  537.         nr_visible_voices=4;
  538.  
  539.         first_voice=
  540.         MAX(0, MIN(first_voice, M.nr_voices-nr_visible_voices));
  541.         
  542.         print_channelnumbers(first_voice);
  543.         if(playing && !default_opt.noscroll)
  544.         print_line(last_pos, last_line, first_voice);
  545.         break;
  546.       default:
  547.     }
  548.     }
  549.   skip:
  550. #ifdef FLUSH_INPUT
  551.     read(STDIN_FILENO, tmpname, 80); /* Flush input (for slow CPU's) */
  552. #endif
  553. }
  554.  
  555.  
  556. void start_selecting(void)
  557. {
  558.     saved_filenr=cur_filenr;
  559.     if(!opt.play_list)
  560.     getcwd(saved_dir, PATH_MAX); /* Store working directory */
  561.     selecting=1;
  562. }
  563.  
  564. /* Do what is necessery when selecting a file (except perform the actual
  565.  * loading).
  566.  */
  567.  
  568. void do_select_file(void)
  569. {
  570.     if(!opt.play_list)
  571.     strcpy(saved_dir, workdir); /* Set the new working directory */
  572.     selecting=0;
  573. }
  574.  
  575.  
  576. void abort_selecting(void)
  577. {
  578.     if(!opt.play_list) {
  579.     if(strcmp(saved_dir, workdir)) {
  580.         strcpy(workdir, saved_dir);
  581.         chdir(workdir);
  582.         init_dir(workdir);
  583.     }
  584.     }
  585.     cur_filenr=saved_filenr;
  586.     selecting=0;
  587. }
  588.  
  589.  
  590. int should_autoselect_next(void)
  591. {
  592.     if(!opt.auto_next)
  593.     return 0;
  594.  
  595.     /* No forever when there is no playlist */
  596.     if(opt.play_list && opt.replay_forever)
  597.     return 1;
  598.     
  599.     if(opt.play_list) {
  600.     if(fileidx_to_seqidx(cur_filenr) == nr_songs-1) {
  601.         return 0;
  602.     }
  603.     }
  604.     else {
  605.     if(cur_filenr == nr_files-1) {
  606.         return 0;
  607.     }
  608.     }
  609.     return 1;
  610. }
  611.  
  612.  
  613. void select_next_file(void)
  614. {
  615.     int tmp;
  616.     
  617.     if(opt.play_list) {
  618.     if((tmp=fileidx_to_seqidx(cur_filenr)) == nr_songs-1) {
  619.         if(opt.replay_forever) {
  620.         cur_filenr=seqidx_to_fileidx(0); /* Take the first one again */
  621.         }
  622.         else
  623.         return; /* Replay last song */
  624.     }
  625.     else
  626.         cur_filenr=seqidx_to_fileidx(tmp+1);
  627.     }
  628.     else {
  629.     cur_filenr=MIN(cur_filenr+1, nr_files-1);
  630.     }
  631. }
  632.  
  633.  
  634. void select_prev_file(void)
  635. {
  636.     int tmp;
  637.  
  638.     if(opt.play_list) {
  639.     if(!(tmp=fileidx_to_seqidx(cur_filenr)))
  640.         return; /* Replay first song */
  641.     cur_filenr=seqidx_to_fileidx(tmp-1);
  642.     }
  643.     else {
  644.     cur_filenr=MAX(cur_filenr-1, nr_dirs);
  645.     }
  646. }
  647.  
  648.  
  649. void read_sequencer(void)
  650. {
  651.     char buf[4];
  652.     int msg;
  653.     struct mod_message mess;
  654.     
  655.     safe_read(seqfd, (struct mod_message *)buf, 4);
  656.     
  657.     msg=(*(unsigned long *)buf)>>8;
  658.     switch(msg) {
  659.       case MESSAGE_PRINTLINE:
  660.       case MESSAGE_PRINTSPEED:
  661.     read_syncedmessage();
  662.     break;
  663.       case MESSAGE_DONE:       /* Song played to the end */
  664.     total_time+=time(0)-restart_time;
  665.  
  666.     if(opt.loop_module) {
  667.         pending_restart=MESSAGE_RESTART;
  668.         handle_restart(42); /* Done here as no lines coming */
  669.     }
  670.     else {
  671.         set_status(STATUS_READY);
  672.         last_pos=last_line=0;
  673.         print_pos(0, 0);
  674.         if(!selecting) {
  675.         if(should_autoselect_next()) {
  676.             select_next_file();
  677.             load_next_module();
  678.         }
  679.         else {
  680.             clear_screen();
  681.             /* Exit if we are in batch-mode */
  682.             if(opt.quiet) {
  683.             mess.type=MESSAGE_EXIT;
  684.             send_to_player(&mess);
  685.             quit=QUIT_QUIT;
  686.             }
  687.         }
  688.         }
  689.     }
  690.     break;
  691.       default:
  692.     error("Invalid message %d\n", msg);
  693.     }
  694. }
  695.  
  696.  
  697. void read_syncedmessage(void)
  698. {
  699.     struct mod_message mess;
  700.     unsigned int t;
  701.     
  702.     safe_read(player2main_synced[PIPE_READ], &mess, sizeof(mess));
  703.     switch(mess.type) {
  704.       case MESSAGE_PRINTSPEED:
  705.     last_speed=mess.a1.speed;
  706.     last_tempo=mess.a2.tempo;
  707.     print_speed(last_speed, last_tempo);
  708.     break;
  709.       case MESSAGE_PRINTLINE:
  710.     if(pending_restart)
  711.         handle_restart(mess.a1.songpos);
  712.     else {
  713.         last_pos=mess.a1.songpos;
  714.         last_line=mess.a2.line;
  715.         if(!pending_syncedmessage()) {
  716.         if(!selecting && !default_opt.noscroll)
  717.             print_line(last_pos, last_line, first_voice);
  718.         }
  719.         print_pos(last_pos, last_line);
  720.         t=time(0)-starting_time;
  721.         if(opt.maxtime && t > opt.maxtime) {
  722.         total_time+=time(0)-restart_time-1;
  723.         set_status(STATUS_READY);
  724.         last_pos=last_line=0;
  725.         print_pos(0, 0);
  726.         if(selecting) {
  727.             pending_restart=MESSAGE_STOP;
  728.             handle_restart(42);
  729.         }
  730.         else {
  731.             clear_screen();
  732.             if(should_autoselect_next()) {
  733.             select_next_file();
  734.             load_next_module();
  735.             }
  736.             else {
  737.             /* Exit if we are in batch-mode */
  738.             if(opt.quiet) {
  739.                 mess.type=MESSAGE_EXIT;
  740.                 send_to_player(&mess);
  741.                 quit=QUIT_QUIT;
  742.             }
  743.             else {
  744.                 pending_restart=MESSAGE_STOP;
  745.                 handle_restart(42);
  746.             }
  747.             }
  748.         }
  749.         }
  750.         else
  751.         print_time(t);
  752.     }
  753.     break;
  754.       default:
  755.     error("Illegal synced message received by main (%d).\n", mess.type);
  756.     }
  757. }
  758.  
  759.  
  760. int pending_syncedmessage(void)
  761. {
  762.     fd_set rset;
  763.     int nr;
  764.     struct timeval null_time={0,0};
  765.  
  766.     FD_ZERO(&rset);
  767.     FD_SET(seqfd, &rset);
  768.     if((nr=select(seqfd+1, &rset, 0, 0, &null_time)) >= 0) {
  769.     if(FD_ISSET(seqfd, &rset))
  770.         return 1;
  771.     else
  772.         return 0;
  773.     }
  774.     else {
  775.     if(errno != EINTR)
  776.         error("select() failed (errno=%d).\n", errno);
  777.     }
  778.     return 0; /* Remove warning */
  779. }
  780.  
  781.  
  782. void handle_restart(int songpos)
  783. {
  784.     struct mod_message mess;
  785.  
  786.     if(playing)
  787.     total_time+=time(0)-restart_time;
  788.  
  789.     mess.type=pending_restart;
  790.     switch(pending_restart) {
  791.       case MESSAGE_STOP:
  792.       case MESSAGE_RESTART:
  793.     send_to_player(&mess);
  794.     if(pending_restart == MESSAGE_RESTART)
  795.         send_to_player_generic(&opt.active_voices,
  796.                    sizeof(opt.active_voices));
  797.     wait_ack();
  798.     if(pending_restart != MESSAGE_STOP) {
  799.         set_status(STATUS_PLAYING);
  800.         last_line=0;
  801.     }
  802.     starting_time=time(0);
  803.     opt.maxtime=0;
  804.     break;
  805.       case MESSAGE_JUMPPATTERN:
  806.     mess.a1.songpos=MIN(MAX(0, songpos+pending_info), M.songlength-1);
  807.     send_to_player(&mess);
  808.     mess.a1.speed=last_speed;
  809.     mess.a2.tempo=last_tempo;
  810.     send_to_player(&mess);
  811.     send_to_player_generic(&opt.active_voices, sizeof(opt.active_voices));
  812.     last_line=0;
  813.     wait_ack();
  814.     opt.maxtime=0;
  815.     break;
  816.       default:
  817.     error("Internal error in handle_restart()");
  818.     }
  819.     restart_time=time(0);
  820.     pending_restart=0;
  821. }
  822.  
  823.  
  824. /* If outgoing_too is false this function will hang until somone drains
  825.  * the main2player-pipe (busy-wait, but this should only be for very
  826.  * short periods of time if everything is working as it should).
  827.  */
  828.  
  829. void drain_pipes(char outgoing_too)
  830. {
  831.     fd_set rset;
  832.     char buf[256];
  833.     int nr;
  834.     struct timeval nulltime;
  835.  
  836.     while(1) {
  837.     nulltime.tv_sec=0;
  838.     nulltime.tv_usec=0;
  839.     FD_ZERO(&rset);
  840.  
  841.     FD_SET(main2player[PIPE_READ], &rset);
  842.     FD_SET(player2main_synced[PIPE_READ], &rset);
  843.     FD_SET(seqfd, &rset);
  844.     FD_SET(STDIN_FILENO, &rset);
  845.  
  846.         if((nr=select(maxfd, &rset, 0, 0, &nulltime)) > 0) {
  847.         if(outgoing_too && FD_ISSET(main2player[PIPE_READ], &rset))
  848.         read(main2player[PIPE_READ], buf, 256);
  849.         if(FD_ISSET(player2main_synced[PIPE_READ], &rset))
  850.         read(player2main_synced[PIPE_READ], buf, 256);
  851.         if(FD_ISSET(seqfd, &rset))
  852.         read(seqfd, buf, 256);
  853.         if(FD_ISSET(STDIN_FILENO, &rset))
  854.         read(STDIN_FILENO, buf, 256);
  855.     }
  856.     else {
  857.         if(nr < 0)
  858.         error("Select problems (%d).\n", errno);
  859.         break;
  860.     }
  861.     }
  862. }
  863.  
  864.  
  865. /* S between 1 and 3. If 0 and loaded we select a "good" one */
  866.  
  867. void set_voice_detail(int s)
  868. {
  869.     int detail[]={4, 9, 17};
  870.  
  871.     if(!s) {
  872.     if(loaded) {
  873.         if(M.nr_voices <=4)
  874.         s=1;
  875.         else if(M.nr_voices <=9)
  876.         s=2;
  877.         else
  878.         s=3;
  879.     }
  880.     else
  881.         s=1;
  882.     }  
  883.     nr_visible_voices=detail[s-1];
  884. }
  885.  
  886.  
  887. void set_status(int s)
  888. {
  889.     switch(s) {
  890.       case STATUS_PLAYING:
  891.     print_status("Playing");
  892.     playing=1;
  893.     break;
  894.       case STATUS_READY:
  895.     print_status("Ready");
  896.     playing=0;
  897.     break;
  898.       default:
  899.     error("Unknown status (%d).\n", s);
  900.     }
  901. }
  902.  
  903.  
  904. void send_to_player(struct mod_message *m)
  905. {
  906.     safe_write(main2player[PIPE_WRITE], m, sizeof(struct mod_message));
  907. }
  908.  
  909.  
  910. void send_to_player_generic(void *m, int size)
  911. {
  912.     safe_write(main2player[PIPE_WRITE], (struct mod_message *)m, size);
  913. }
  914.  
  915.  
  916. /* Handshake-functions */
  917.  
  918. void send_ack()
  919. {
  920.     char data;
  921.     safe_write(ack_pipe[PIPE_WRITE], (struct mod_message *)&data, 1);
  922. }
  923.  
  924.  
  925. void wait_ack()
  926. {
  927.     char data;
  928.     safe_read(ack_pipe[PIPE_READ], (struct mod_message *)&data, 1);
  929. }
  930.