home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / alt / lucidem / bug / 416 < prev    next >
Encoding:
Text File  |  1992-12-31  |  8.9 KB  |  374 lines

  1. x-gateway: rodan.UU.NET from bug-lucid-emacs to alt.lucid-emacs.bug; Thu, 31 Dec 1992 05:26:04 EST
  2. From: amir@matis.ingr.com (Amir J Katz)
  3. Message-ID: <9212311003.AA07617@simpson.ingr.com>
  4. Subject: SUMMARY: Sound on Sun hogs /dev/audio?
  5. Organization: SEE Technologies Ltd.
  6. Reply-To: amir@matis.ingr.com
  7. X-Mailer: ELM [version 2.3 PL11]
  8. Date: Thu, 31 Dec 1992 10:26:05 GMT
  9. Newsgroups: alt.lucid-emacs.bug
  10. Path: sparky!uunet!wendy-fate.uu.net!bug-lucid-emacs
  11. Sender: bug-lucid-emacs-request@lucid.com
  12. Lines: 360
  13.  
  14. Recently, I posted the follwing:
  15.  
  16. >> Guys,
  17. >> When Lucid 19.3 is up on my Sun SS-1, no other audio playing program
  18. >> (audiotool, soundtol, play, rplay) can play anything. None of them complain,
  19. >> though, but no sound is heard. Only after I go into soundtool or audiotool,
  20. >> set the output to Jack and then back to Speaker, only then the audio
  21. >> programs start to play sounds. Playing any sound in lemacs reverts the situation.
  22. >> Apparently, Lucid audio code leaves /dev/audio is some bad state.
  23. >> Before I start hacking the code (asuming that I know what I'm doing :-), has
  24. >> anyone fixed that?
  25.  
  26. The only response came from Mark Boyns (boyns@sciences.sdsu.edu) who said:
  27.  
  28. Mark> I am not sure about your /dev/audio busy problem but I would like to
  29. Mark> recommend that you use my rplay package.  rplay will allows you to play
  30. Mark> multiple sounds at once on local and remote machines.  The source
  31. Mark> can be obtained at sounds.sdsu.edu along with about 350Megs of audio files.
  32. Mark> 
  33. Mark> About your /dev/audio busy, are you sure the volume is not 0?
  34.  
  35. The verdict:
  36. The culprit is the existing play.c in the src directory of Lucid Emacs 19.3.
  37. Jamie has sent me a new version that no longer hogs the device.
  38. It works fine on SunOS 4.1.3, but your mileage may vary...
  39.  
  40. ---------- slice 'n' dice --------------------------------------- file: play.c
  41. /* play.c - play a sound file on the speaker
  42.  **
  43.  ** Copyright (C) 1989 by Jef Poskanzer.
  44.  **
  45.  ** Modified 24-May-91 by Jamie Zawinski (for Lucid Emacs.)
  46.  ** Modified 17-Dec-92 by Jamie Zawinski (largely rewritten for SunOS 4.1.3.)
  47.  **
  48.  ** Permission to use, copy, modify, and distribute this software and its
  49.  ** documentation for any purpose and without fee is hereby granted, provided
  50.  ** that the above copyright notice appear in all copies and that both that
  51.  ** copyright notice and this permission notice appear in supporting
  52.  ** documentation.  This software is provided "as is" without express or
  53.  ** implied warranty.
  54.  */
  55.  
  56. #if __STDC__
  57. #include <stdlib.h>
  58. #include <unistd.h>
  59. #endif
  60.  
  61. #include <stdio.h>
  62. #include <string.h>
  63. #include <sys/signal.h>
  64. #include <sys/fcntl.h>
  65. #include <sys/file.h>
  66.  
  67. #include <multimedia/libaudio.h>
  68. #include <multimedia/audio_device.h>
  69.  
  70. #if __STDC__                /* warning suppression */
  71. extern int audio__setplayhdr();
  72. extern int audio__setgain();
  73. extern int audio__flush();
  74. extern int audio_decode_filehdr();
  75. extern int audio_read_filehdr();
  76. extern int audio_cmp_hdr();
  77. extern int audio_enc_to_str();
  78. extern int audio_drain();
  79. extern void usleep();
  80. #endif
  81.  
  82. #ifdef emacs
  83. extern char *sys_errlist[];
  84. extern int errno, sys_nerr;
  85. extern void message ();
  86. # define perror(string) \
  87.     message("audio: %s, %s ", string, \
  88.         (errno < sys_nerr) ? sys_errlist[errno] : \
  89.         "unknown")
  90. # define warn(str) message ("audio: %s ", (str))
  91. #else /* !emacs */
  92. # define warn(str) fprintf (stderr, "%s\n", (str))
  93. #endif /* emacs */
  94.  
  95. static void (*sighup_handler) ();
  96. static void (*sigint_handler) ();
  97. static void sighandler ();
  98.  
  99. static int audio_fd;
  100.  
  101. #define audio_open()    open ("/dev/audio", (O_WRONLY | O_NDELAY))
  102.  
  103. static int reset_volume_p, reset_device_p;
  104. static double old_volume;
  105. static Audio_hdr dev_hdr;
  106.  
  107. static int
  108. init_device (volume, data, fd, header_length)
  109.      int volume;
  110.      unsigned char *data;
  111.      int fd;
  112.      int *header_length;
  113. {
  114. #ifdef SUNOS4_0_3
  115.   if (header_length) *header_length = 0;
  116.   return 0;
  117. #else
  118.   Audio_hdr file_hdr;
  119.   
  120.   reset_volume_p = 0;
  121.   reset_device_p = 0;
  122.  
  123.   if (data && fd) abort (); /* one or the other */
  124.  
  125.   if (AUDIO_SUCCESS != audio_get_play_config (audio_fd, &dev_hdr))
  126.     {
  127.       perror ("Not a valid audio device");
  128.       return 1;
  129.     }
  130.   
  131.   if (AUDIO_SUCCESS != (data
  132.             ? audio_decode_filehdr (data, &file_hdr, header_length)
  133.             : audio_read_filehdr (fd, &file_hdr, 0, 0)))
  134.     {
  135.       if (data)
  136.     perror ("invalid audio data");
  137.       else
  138.     perror ("invalid audio file");
  139.       return 1;
  140.     }
  141.   
  142.   audio_flush_play (audio_fd);
  143.  
  144.   if (0 != audio_cmp_hdr (&dev_hdr, &file_hdr))
  145.     {
  146.       Audio_hdr new_hdr = file_hdr;
  147.       reset_device_p = 1;
  148.       if (AUDIO_SUCCESS != audio_set_play_config (audio_fd, &new_hdr))
  149.     {
  150.       char buf1 [100], buf2 [100], buf3 [250];
  151.       audio_enc_to_str (&file_hdr, buf1);
  152.       audio_enc_to_str (&new_hdr, buf2);
  153.       sprintf (buf3, "wanted %s, got %s", buf1, buf2);
  154.       warn (buf3);
  155.       return 1;
  156.     }
  157.     }
  158.  
  159.   if (volume < 0 || volume > 100)
  160.     {
  161.       char buf [255];
  162.       sprintf (buf, "volume must be between 0 and 100 (not %d)", volume);
  163.       warn (buf);
  164.       return 1;
  165.     }
  166.   {
  167.     /* set the volume; scale it to 0.0 - 1.0 */
  168.     double V = (volume / 100.0);
  169.     audio_get_play_gain (audio_fd, &old_volume);
  170.     reset_volume_p = 1;
  171.     audio_set_play_gain (audio_fd, &V);
  172.   }
  173.  
  174.   return 0;
  175. #endif
  176. }
  177.  
  178. static void
  179. reset_device (wait_p)
  180.      int wait_p;
  181. {
  182.   if (wait_p)
  183.     audio_drain (audio_fd, 1);
  184.   else
  185.     audio_flush_play (audio_fd);
  186.   if (reset_device_p)
  187.     audio_set_play_config (audio_fd, &dev_hdr);
  188.   if (reset_volume_p)
  189.     audio_set_play_gain (audio_fd, &old_volume);
  190. }
  191.  
  192. void
  193. play_sound_file (sound_file, volume)
  194.     char *sound_file;
  195.     int volume;
  196. {
  197.   int rrtn, wrtn;
  198.   unsigned char buf [255];
  199.   int file_fd;
  200.   
  201.   audio_fd = audio_open ();
  202.  
  203.   if (audio_fd < 0)
  204.     {
  205.       perror ("open /dev/audio");
  206.       return;
  207.     }
  208.  
  209.   sighup_handler = signal (SIGHUP, sighandler);
  210.   sigint_handler = signal (SIGINT, sighandler);
  211.   
  212.   file_fd = open (sound_file, O_RDONLY);
  213.   if (file_fd < 0)
  214.     {
  215.       perror (sound_file);
  216.       goto END_OF_PLAY;
  217.     }
  218.  
  219.   if (init_device (volume, 0, file_fd, 0))
  220.     goto END_OF_PLAY;
  221.     
  222.   while (1)
  223.     {
  224.       rrtn = read (file_fd, (char *) buf, sizeof (buf));
  225.       if (rrtn < 0)
  226.     {
  227.       perror ("read");
  228.       goto END_OF_PLAY;
  229.     }
  230.       if (rrtn == 0)
  231.     break;
  232.     
  233.       while (1)
  234.     {
  235.       wrtn = write (audio_fd, (char *) buf, rrtn);
  236.       if (wrtn < 0)
  237.         {
  238.           perror ("write");
  239.           goto END_OF_PLAY;
  240.         }
  241.       if (wrtn != 0)
  242.         break;
  243.  
  244.       if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
  245.         goto END_OF_PLAY;
  246.     }
  247.       if (wrtn != rrtn)
  248.     {
  249.       char buf [255];
  250.       sprintf (buf, "play: rrtn = %d, wrtn = %d", rrtn, wrtn);
  251.       warn (buf);
  252.       goto END_OF_PLAY;
  253.     }
  254.     }
  255.   
  256.  END_OF_PLAY:
  257.  
  258.   if (file_fd > 0)
  259.     close (file_fd);
  260.  
  261.   if (audio_fd > 0)
  262.     {
  263.       reset_device (1);
  264.       close (audio_fd);
  265.     }
  266.  
  267.   (void) signal (SIGHUP, sighup_handler);
  268.   (void) signal (SIGINT, sigint_handler);
  269. }
  270.  
  271. void
  272. play_sound_data (data, length, volume)
  273.      unsigned char *data;
  274.      int length, volume;
  275. {
  276.   int wrtn, start = 0;
  277.   int ilen;
  278.  
  279.   audio_fd = -1;
  280.  
  281.   if (length == 0) return;
  282.  
  283.   /* this is just to get a better error message */
  284.   if (strncmp (".snd\0", (char *) data, 4))
  285.     {
  286.       warn ("Not valid audio data (bad magic number)");
  287.       goto END_OF_PLAY;
  288.     }
  289.   if (length <= sizeof (Audio_hdr))
  290.     {
  291.       warn ("Not valid audio data (too short)");
  292.       goto END_OF_PLAY;
  293.     }
  294.  
  295.   audio_fd = audio_open ();
  296.   if (audio_fd < 0)
  297.     {
  298.       perror ("open /dev/audio");
  299.       return;
  300.     }
  301.  
  302.   sighup_handler = signal (SIGHUP, sighandler);
  303.   sigint_handler = signal (SIGINT, sighandler);
  304.     
  305.   if (init_device (volume, data, 0, &ilen))
  306.     goto END_OF_PLAY;
  307.       
  308.   data   += (ilen<<2);
  309.   length -= (ilen<<2);
  310.   if (length <= 1)
  311.     goto END_OF_PLAY;
  312.     
  313.   while (1)
  314.     {
  315.       wrtn = write (audio_fd, (char *) (data+start), length-start);
  316.       if (wrtn < 0)
  317.     {
  318.       perror ("write");
  319.       goto END_OF_PLAY;
  320.     }
  321.       if (wrtn != 0)
  322.     {
  323.       start += wrtn;
  324.       break;
  325.     }
  326.       if (AUDIO_ERR_INTERRUPTED == audio_drain (audio_fd, 1))
  327.     goto END_OF_PLAY;
  328.     }
  329.   if (wrtn != length)
  330.     {
  331.       char buf [255];
  332.       sprintf (buf, "play: rrtn = %d, wrtn = %d", length, wrtn);
  333.       warn (buf);
  334.       goto END_OF_PLAY;
  335.     }
  336.   
  337.  END_OF_PLAY:
  338.  
  339.   if (audio_fd > 0)
  340.     {
  341.       reset_device (1);
  342.       close (audio_fd);
  343.     }
  344.  
  345.   (void) signal (SIGHUP, sighup_handler);
  346.   (void) signal (SIGINT, sigint_handler);
  347. }
  348.  
  349. static void
  350. sighandler (sig, code, scp, addr)
  351.      int sig, code;
  352.      struct sigcontext *scp;
  353.      char *addr;
  354. {
  355.   if (audio_fd > 0)
  356.     {
  357.       reset_device (0);
  358.       close (audio_fd);
  359.     }
  360.   if (sig == SIGHUP && sighup_handler)
  361.     sighup_handler (sig, code, scp, addr);
  362.   else if (sig == SIGINT && sigint_handler)
  363.     sigint_handler (sig, code, scp, addr);
  364.   else
  365.     exit (1);
  366. }
  367.  
  368. -- 
  369. /* ----------------------------------------------------------- */
  370. /*  Amir J. Katz             |   amir@matis.ingr.COM           */
  371. /*  System Specialist        |   Voice:  +972 52-584684        */
  372. /*  SEE Technologies Ltd.    |   Fax:    +972 52-543917        */
  373. /* ............ Solaris 2.1 - The Final Frontier ? ........... */
  374.