home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / mod-0.000 / mod-0 / mod / util.c < prev   
Encoding:
C/C++ Source or Header  |  1994-11-10  |  6.2 KB  |  341 lines

  1. /*
  2.  *  util.c - Various support functions.
  3.  *
  4.  *  (C) 1994 Mikael Nordqvist (d91mn@efd.lth.se, mech@df.lth.se)
  5.  */
  6.  
  7. #include <ctype.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <sys/time.h>
  11. #include <sys/types.h>
  12. #include <unistd.h>
  13. #include <stdlib.h>
  14. #include <errno.h>
  15. #include <sys/wait.h>
  16. #include <fcntl.h>
  17. #include <sys/ioctl.h>
  18. #include <sys/soundcard.h>
  19.  
  20. #include "mod.h"
  21. #include "message.h"
  22.  
  23. extern struct mod_info M;
  24. extern char quit;
  25. extern int seqfd, mixerfd;
  26.  
  27. SEQ_DECLAREBUF();
  28.  
  29. /*
  30.  *  Wordswapping functions
  31.  */
  32.  
  33. unsigned short SWAPSHORT(char *a)
  34. {
  35.     return (((*(unsigned short *)a&0xff)<<8)|((*(unsigned short *)a>>8)&0xff));
  36. }
  37.  
  38. unsigned long SWAPLONG(char *a)
  39. {
  40.     return (SWAPSHORT(a)<<16 | SWAPSHORT(a+2));
  41. }
  42.  
  43. /*
  44.  *  Removes nonprintable characters and trailing spaces from a string.
  45.  */
  46.  
  47. void fix_string(char *s)
  48. {
  49.     char *a;
  50.  
  51.     a=s;
  52.     while(*s) {
  53.     if(*s >= 32 && *s <=126)
  54.         s++;
  55.     else
  56.         *s++=' ';
  57.     }
  58.  
  59.     for(--s; s >=a; --s)  {
  60.     if(*s == ' ')
  61.         *s=0;
  62.     else
  63.         break;
  64.     }
  65. }
  66.  
  67. /* Fills out a string with spaces, or truncates it if its too long. */
  68.  
  69. char *fill_string(char *s, int len)
  70. {
  71.     static char buf[128];
  72.     int i;
  73.  
  74.     strcpy(buf, s);
  75.  
  76.     i=strlen(s);
  77.     if(i > len)
  78.     i=len;
  79.  
  80.     for(; i < len; ++i)
  81.     buf[i]=' ';
  82.     
  83.     buf[i]=0;
  84.     return buf;
  85. }
  86.  
  87. /*
  88.  *  This is seqbuf_dump() used by the SEQ_DUMPBUF macro.
  89.  */
  90.  
  91. void seqbuf_dump()
  92. {
  93.     int thisone=0; /* No need to initialize, but it removes a warning */
  94.     fd_set wset;
  95.  
  96.     while(_seqbufptr) {
  97.     FD_ZERO(&wset);
  98.     FD_SET(seqfd, &wset);
  99.     if(select(seqfd+1, 0, &wset, 0, 0) >= 0) {
  100.         if((thisone=write(seqfd, _seqbuf, _seqbufptr)) == -1)
  101.         error("Unable to write(sequencer)");
  102.  
  103.         if(thisone < _seqbufptr) {
  104.         memmove(_seqbuf, &(_seqbuf[thisone]), _seqbufptr-thisone);
  105.         _seqbufptr-=thisone;
  106.         }
  107.         else
  108.         _seqbufptr=0;
  109.     }
  110.     else {
  111.         if(errno != EINTR)
  112.         error("select() in seqbuf_dump failed (errno=%d)\n", errno);
  113.     }
  114.     }
  115. }
  116.  
  117. /*
  118.  *  Changes the master volume by amount. amount=0 mutes/demutes
  119.  */
  120.  
  121. void change_mastervolume(int amount)
  122. {
  123.     static int muted=100;
  124.     int current;
  125.  
  126.     if(mixerfd == -1)
  127.     return;
  128.  
  129.     if(ioctl(mixerfd, SOUND_MIXER_READ_SYNTH, ¤t) == -1)
  130.     return;
  131.  
  132.     /* Take average of left/right */
  133.     current=((current&0xff)+((current>>8)&0xff))/2;
  134.     if(amount == 0) {
  135.     if(!current)
  136.         current=muted;
  137.     else {
  138.         muted=current;
  139.         current=0;
  140.     }
  141.     }
  142.     else {
  143.     current=MIN(MAX(0, current+amount), 100);
  144.     }
  145.     current=current|(current<<8);
  146.  
  147.     if(ioctl(mixerfd, SOUND_MIXER_WRITE_SYNTH, ¤t) == -1)
  148.     return;
  149. }
  150.  
  151.  
  152. /*
  153.  *  Takes track-data and returns the corresponding track-index.
  154.  *  This is where identical tracks are found.
  155.  */
  156.  
  157. int get_track_idx(struct event *e)
  158. {
  159.     int i;
  160.     
  161.     for(i=0; i < M.nr_tracks; ++i)
  162.     if(!bcmp(e, M.tracks[i], sizeof(struct event)*64))
  163.         return i;
  164.     
  165.     M.tracks[M.nr_tracks]=(struct event *)malloc(sizeof(struct event)*64);
  166.     memcpy((void *)M.tracks[M.nr_tracks], (void *)e, sizeof(struct event)*64);
  167.     return M.nr_tracks++;
  168. }
  169.  
  170.  
  171. /* Allows reading of a small amounts of bytes from a file, n <= 10. Buffers
  172.  * data to minimize number of read()-calls.
  173.  * n = 0   Init.
  174.  * n = -1  Cleanup (only needed if you need the read-ahead flushed).
  175.  * The function returns true if all bytes could be read, false otherwise.
  176.  */
  177.  
  178. int get_bytes(int fd, char *dest, int n)
  179. {
  180.     static char buf[1024];
  181.     static int bufpos, lastbufpos, nomore;
  182.     int thisone;
  183.  
  184.     if(n == -1) {
  185.     if(lseek(fd, -(lastbufpos-bufpos+1), SEEK_CUR) == -1)
  186.         error("Seek() failed.\n");
  187.     return 1;
  188.     }
  189.     
  190.     if(!n) {
  191.     bufpos=0;
  192.     lastbufpos=read(fd, buf, 1024);
  193.     if(!lastbufpos || lastbufpos == -1) {
  194.         return 0;
  195.     }
  196.     else {
  197.         if(lastbufpos != 1024)
  198.         nomore=1;
  199.         else
  200.         nomore=0;
  201.         --lastbufpos;
  202.         return 1;
  203.     }
  204.     }
  205.  
  206.     if(bufpos+n-1 <= lastbufpos) {
  207.     memcpy(dest, &buf[bufpos], n);
  208.     bufpos+=n;
  209.     }
  210.     else {
  211.     return 0;
  212.     }
  213.  
  214.     if(bufpos > 1010 && !nomore) {
  215.     memmove(buf, &buf[bufpos], 1024-bufpos);
  216.     if((thisone=read(fd, &buf[1024-bufpos], bufpos)) == 0 ||
  217.        thisone == -1 || thisone != bufpos) {
  218.         nomore=1;
  219.         if(thisone <= 0)
  220.         thisone=0;
  221.         lastbufpos=1024-bufpos+thisone-1;
  222.     }
  223.     bufpos=0;
  224.     }
  225.     return 1;
  226. }
  227.  
  228.  
  229. /*
  230.  * Writes a string to a filedescriptor
  231.  */
  232.  
  233. void safe_read(int fd, struct mod_message *buf, int len)
  234. {
  235.     int sofar, thisone;
  236.     
  237.     sofar=0;
  238.     do {
  239.     thisone=read(fd, ((char *)buf)+sofar, len-sofar);
  240.     if(thisone >= 0) {
  241.         sofar+=thisone;
  242.         if(!thisone)
  243.         debug("safe_read(): 0\n");
  244.     }
  245.     else {
  246.         if(errno != EAGAIN) {
  247.         debug("Error reading pipe %d (seq=%d) (errno=%d)\n",
  248.               fd, seqfd, errno);
  249.         }
  250.         else
  251.         debug("safe_read() returned EAGAIN, retrying...\n");
  252.     }
  253.     }
  254.     while(sofar < len);
  255. }
  256.  
  257.  
  258. /*
  259.  * Writes a string to a filedescriptor
  260.  */
  261.  
  262. void safe_write(int fd, struct mod_message *buf, int len)
  263. {
  264.     int sofar, thisone;
  265.     
  266.     sofar=0;
  267.     do {
  268.     thisone=write(fd, ((char *)buf)+sofar, len-sofar);
  269.     if(thisone >= 0) {
  270.         sofar+=thisone;
  271.         if(!thisone)
  272.         debug("safe_write(): 0\n");
  273.     }
  274.     else {
  275.         if(errno != EAGAIN)
  276.         error("Error writing pipe (%d)\n", errno);
  277.         error("safe_write() would block...\n");
  278.     }
  279.     }
  280.     while(sofar < len);
  281. }
  282.  
  283.  
  284. /* Returns < 0 if we got SIG_QUIT otherwise exitstatus of command */
  285.  
  286. int my_system(char *a)
  287. {
  288.     int p, status;
  289.  
  290.     switch(p=fork()) {
  291.       case -1:
  292.     error("Fork failed in my_system.");
  293.     break;
  294.       case 0:
  295.     exit(system(a));
  296.     break;
  297.       default:
  298.     while(1) {
  299.         if(waitpid(p, &status, 0) >= 0) {
  300.         if(WIFEXITED(status)) {
  301.             if(quit == QUIT_SIGNAL)
  302.             return -1;
  303.             else
  304.             return WEXITSTATUS(status);
  305.         }
  306.         else {
  307.             debug("Huh??!! system()-problems\n");
  308.             return 1;
  309.         }
  310.         }
  311.         else {
  312.         if(errno != EINTR && errno != ERESTARTSYS) {
  313.             error("Huh??!! waitpid()-problems\n");
  314.         }
  315.         }
  316.     }
  317.     }
  318.     error("Never reached");
  319.     return 0; /* Remove warning */
  320. }
  321.  
  322.  
  323. /* Escapes characters for the shell */
  324.  
  325. char *escape_name(char *s, int a)
  326. {
  327.     static char buf1[PATH_MAX+1], buf2[PATH_MAX+1];
  328.     char *d;
  329.     
  330.     d=(a ? buf2 : buf1);
  331.     while(*s) {
  332.     if(!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||
  333.          (*s >= '0' && *s <= '9') || *s == '.' || *s == '/' || *s == '-'
  334.          || *s == '_'))
  335.         *d++='\\';
  336.     *d++=*s++;
  337.     }
  338.     *d=0;
  339.     return (a ? buf2 : buf1);
  340. }
  341.