home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / dtr / play.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-15  |  10.5 KB  |  327 lines

  1. /*
  2.  * Copyright (c) 1990, 1991 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and 
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that (i) the above copyright notices and this permission notice appear in
  7.  * all copies of the software and related documentation, and (ii) the name
  8.  * Stanford may not be used in any advertising or publicity relating to
  9.  * the software without the specific, prior written permission of
  10.  * Stanford.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  15.  *
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
  19.  * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
  20.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21.  * SOFTWARE.
  22.  */
  23.  
  24. /* $Header: /Source/Media/collab/DTR/RCS/play.c,v 1.10 92/01/09 12:42:42 drapeau Exp Locker: derek $ */
  25. /* $Log:    play.c,v $
  26.  * Revision 1.10  92/01/09  12:42:42  drapeau
  27.  * Slight modifications to the code to make it ANSI-compliant.
  28.  * 
  29.  * Revision 1.0  92/01/07  14:16:55  drapeau
  30.  * Made a number of cosmetic changes to make code easier to read and
  31.  * to conform to programming specifications.
  32.  * Also, changed an alert message in Play(); alert message is now owned
  33.  * by the main window, no longer by the editing status message that has
  34.  * been removed.
  35.  * 
  36.  * Revision 0.21  91/09/18  22:47:34  derek
  37.  * The following things are done:
  38.  * 1.    The Makefile is changed corresponding to the changes in collab/.
  39.  * 2.    Copyright messages included.
  40.  * 3.    Some minor bugs fixed.
  41.  * 
  42.  * Revision 0.20  91/08/21  11:34:28  derek
  43.  * The following changes are made:
  44.  * 1.    Now the duration and size of the recorded sound will be displayed
  45.  *     during recording.
  46.  * 2.    I have changed GetSelection() corresponding to the request of Tek joo
  47.  * 3.    Info Panel is added to the application.
  48.  * 4.    Fixed SizeToFitHandler() so that when no file or buffer is currently
  49.  *     loaded, it would not do anything (except giving a warning
  50.  *     notice_prompt).
  51.  * 5.    Inplemented the `Close' Menu option in the document menu.
  52.  * 6.    Fixed the bug in which after ClearAll and I press PreviewEdit,
  53.  *     the edit wont be played.
  54.  * 7.    I have made the changes corresponding to the change in OpenPanel's
  55.  *     name.  (from OpenPanel to Browse).
  56.  * 8.    Incorporated BrowseCheck to check command line arg.
  57.  * 9.    Changed most EditingStatusMessages to NoticePrompts.
  58.  * 10.    SoundFileSaveAsPopUp and EditListSaveAsPopUp are removed 
  59.  *     from the application.
  60.  * 
  61.  * Revision 0.19  91/08/16  18:10:48  derek
  62.  * 
  63.  * The following things are done:
  64.  * 1.    I have fixed an openpanel bug in my code in which I 
  65.  *     made the app return the wrong values to OpenHandler and
  66.  *     the SaveHandler.
  67.  * 2.    The flashing color of the play button has been changed from
  68.  *     Red to Green.
  69.  * 3.    Fixed a quantization bug: Buffer.play.end, when converted
  70.  *     from endingTimeInSec, should not exceed Buffer_hdr_data_size - 1.
  71.  * 
  72.  * Revision 0.18  91/08/13  20:38:36  derek
  73.  * The buttons (play, pause, record) will now flash after they are pressed.
  74.  * This only applies to times when audio files (not edit-lists) are 
  75.  * played.
  76.  * 
  77.  * Revision 0.17  91/08/07  16:24:38  derek
  78.  * The Edit list part of DTR is done.  OpenPanel is also incorporated.
  79.  * 
  80.  * Revision 0.16  91/07/29  15:10:26  derek
  81.  * The playing w/o stopping error is fixed.
  82.  * 
  83.  * Revision 0.15  91/07/23  21:25:23  derek
  84.  * This version is not ready for release.  Disk space editing is half-done:
  85.  * the application can play an infinite sound and the canvases can handle
  86.  * infinite sound files.  The app is pretty bug free too, I think.  The
  87.  * weakness is that it cannot record sond infinitely.
  88.  * 
  89.  * Revision 0.14  91/06/26  15:55:24  derek
  90.  * I have reformatted the code to conform coding specs.
  91.  * 
  92.  * Revision 0.13  91/06/25  16:27:35  derek
  93.  * The displaying of wrong pause message is fixed.
  94.  * 
  95.  * Revision 0.12  91/06/20  20:01:16  derek
  96.  * The network part should be working.  Also fixed a number of bugs involving
  97.  * canvases and display.
  98.  * 
  99.  * Revision 0.10  1991/04/25  01:50:53  derek
  100.  * This version is checked in on 4/24/91
  101.  * */
  102. static char rcsid[] = "$Header: /Source/Media/collab/DTR/RCS/play.c,v 1.10 92/01/09 12:42:42 drapeau Exp Locker: derek $";
  103.  
  104. #include "dtr.h"
  105. #include "dtr_ui.h"
  106.  
  107. extern   dtr_editListPanelPopUp_objects*    dtr_editListPanelPopUp;
  108.  
  109.  
  110. void
  111.   StopPlay()
  112. {
  113.   unsigned    u;
  114.   
  115.   EVENT("Stop_Play");
  116.   
  117.   ActiveFlag &= ~PLAY;
  118.   
  119.   if (WaitFlag & PLAY)                            /*  If waiting for device open, quit waiting now.   */
  120.   {
  121.     WaitFlag &= ~PLAY;
  122.     return;
  123.   }
  124.   
  125.   Buffer.draining = FALSE;
  126.   
  127.   (void) audio_get_play_error(Audio_fd, &u);                /*  Get latest error count.                         */
  128.   
  129.   Audio_state.play.error = u;
  130.   if (!ActiveFlag)
  131.   {
  132.     AudioFlushClose();
  133.     CancelVUMeterTimer();
  134.     CancelButtonGlowTimer();
  135.   }
  136.   
  137.   UpdateMessageDisplay();                        /*  Update Message display.                         */
  138.   ClearVUMeterCanvas();                            /*  Clear VU Meter Canvas.                          */
  139.   CancelButtonGlow();
  140.  
  141.   xv_set(dtr_editListPanelPopUp->addButton,                
  142.      PANEL_INACTIVE, FALSE, NULL);
  143.   xv_set(dtr_editListPanelPopUp->modifyButton,
  144.      PANEL_INACTIVE, FALSE, NULL);
  145.   xv_set(dtr_editListPanelPopUp->deleteButton,                
  146.      PANEL_INACTIVE, FALSE, NULL);
  147.   xv_set(dtr_editListPanelPopUp->deleteAllButton,
  148.      PANEL_INACTIVE, FALSE, NULL);
  149.   xv_set(dtr_editListPanelPopUp->editListScrollList,            /*  Enable the scroll-list.                         */
  150.      PANEL_INACTIVE, FALSE, NULL);
  151. }                                    /* end function StopPlay */
  152.  
  153.  
  154. /*
  155.  *  This routine is called when the buffer markers are changed.
  156.  */
  157. void
  158.   PlayUpdateCursor()
  159. {
  160.   Audio_info    tmpinfo;
  161.   
  162.   EVENT("Play_Update_Cursor");
  163.   if (!(ActiveFlag & PLAY))                        /*  No need to take action if not actually playing. */
  164.     return;
  165.   if (Buffer.play.end <= Buffer.play.start)                 /*  If start and end points are the same, catch...  */
  166.   {                                    /*  ...it here.                                     */
  167.     StopPlay();          
  168.     return;  
  169.   }
  170.   ActiveFlag &= ~PLAY;                            /*  Turn off the SIGPOLL handler for now.           */
  171.   
  172.   (void) audio_flush_play(Audio_fd);                    /*  Flush queue and start over.                     */
  173.   Buffer.draining = FALSE;
  174.   Buffer.play.io_position = Buffer.play.start;
  175.   ActiveFlag |= PLAY;
  176.   
  177.   AUDIO_INITINFO(&tmpinfo);                        /*  Reset sample, error, and eof counts.  SIGPOLL.. */
  178.   tmpinfo.play.eof = 0;                            /*  ...will kick play.                              */
  179.   tmpinfo.play.error = 0;
  180.   tmpinfo.play.samples = 0;
  181.   (void) audio_setinfo(Audio_fd, &tmpinfo);
  182. }                                    /* end function PlayUpdateCursor */
  183.  
  184.  
  185. void
  186.   StartPlay()
  187. {
  188.   EVENT("Start_Play");
  189.   
  190.   /**    if (SelectCheck() <= 0) {
  191.     StopPlay();
  192.     return;
  193.     }
  194.     ***/
  195.   Buffer.play.io_position = Buffer.play.start;
  196.   Buffer.display.last = -1;
  197.   Buffer.draining = FALSE;
  198.   
  199.   ActiveFlag |= PLAY;                            /*  Set the play flag here.                         */
  200.   
  201.   ResetVUMeter();                            /*  Reset VU Meter parameters.                      */
  202.   
  203.   xv_set(dtr_editListPanelPopUp->addButton,                
  204.      PANEL_INACTIVE, TRUE, NULL);
  205.   xv_set(dtr_editListPanelPopUp->modifyButton,
  206.      PANEL_INACTIVE, TRUE, NULL);
  207.   xv_set(dtr_editListPanelPopUp->deleteButton,                
  208.      PANEL_INACTIVE, TRUE, NULL);
  209.   xv_set(dtr_editListPanelPopUp->deleteAllButton,
  210.      PANEL_INACTIVE, TRUE, NULL);
  211.   SetButtonGlowTimer(GLOW_INTERVAL);
  212.   SetVUMeterTimer((double)SCOPE_WIDTH/ 
  213.           (double)Buffer.hdr.sample_rate);             /*  Set a Timer to go off, probably painting the    */
  214.                                     /*  screen once per Scope width.                    */
  215.   (void) kill(getpid(), SIGPOLL);                    /*  This sends a signal SIGPOLL to the server,...   */
  216.                                     /*  ...which then notifies SigpollAsyncHandler().   */
  217.                                     /*  ...This procedure later triggers PlayService(). */
  218. }    
  219.  
  220.  
  221. /*
  222.  *  This is the routine that is called from the main loop that writes
  223.  *  sound to the device.
  224.  *
  225.  *  It needs the following state data:
  226.  *    - cursor start and end (calculate in proc)
  227.  *    - current position in the buffer
  228.  */
  229. void
  230.   PlayService()
  231. {
  232.   int    start;
  233.   int    end;
  234.   int    outcnt;
  235.   int    rtn;
  236.   int   cnt;
  237.   
  238.   EVENT("Play_Service");
  239.   if (Buffer.draining)
  240.     return;
  241.   start = Buffer.play.io_position;
  242.   end = Buffer.play.end;
  243.   outcnt = end - start + 1;
  244.   if (FileReady)
  245.   {
  246.     soundfd = open(Buffer.filename, O_RDONLY);                /*  ...buffer mode.                                 */
  247.     lseek(soundfd, Buffer.hdr_size + start, L_SET);
  248.   }
  249.   while (outcnt > 0)
  250.   {
  251.     if (FileReady) 
  252.     {
  253.       cnt = read(soundfd, (char *)SndBuf, (outcnt > 1024 ? 1024 : outcnt));            
  254.       rtn = write(Audio_fd, (char *)SndBuf, cnt); 
  255.     }
  256.     else
  257.     {
  258.       rtn = write(Audio_fd, (char *)&Buffer.data[start], outcnt); 
  259.     }
  260.     if (rtn > 0)
  261.     {
  262.       outcnt -= rtn;
  263.       start += rtn;
  264.       Buffer.play.io_position = start;
  265.     }
  266.     else
  267.     {
  268.       break;
  269.     }
  270.   }
  271.   if (FileReady)
  272.   {
  273.     close(soundfd);
  274.     if (outcnt <= 0)
  275.     {
  276.       if (!Buffer.draining)
  277.       {
  278.     Buffer.draining = TRUE;
  279.     (void) write(Audio_fd, (char *)&Buffer.data[0], 0);
  280.       }
  281.     }
  282.   }
  283.   else
  284.   {
  285.     if (outcnt == 0)                            /*  Check for end of sound condition.               */
  286.     {
  287.       if (!Buffer.draining)
  288.       {
  289.     Buffer.draining = TRUE;                        
  290.     (void) write(Audio_fd, (char *)&Buffer.data[0], 0);        /*  Write EOF marker.                               */
  291.       }
  292.     }
  293.   }
  294. }                                    /* end function PlayService*/
  295.  
  296.  
  297.  
  298. /*
  299.  *  This procedure Play() is called by PlayButtonHandler() and is run
  300.  *  when the play button is pressed.  Before executing this procedure,
  301.  *  the audio file is already loaded into memory.
  302.  */
  303. void
  304.   Play(ip)
  305. dtr_mainWindow_objects    *ip;
  306. {
  307.   EVENT("Play");
  308.   
  309.   if ((ActiveFlag & RECORD) || (WaitFlag & RECORD))            /*  Play stops in-progress Record.                  */
  310.     StopRecord();
  311.   
  312.   switch (AudioOpen(PLAY))
  313.   {
  314.    case 0:                                /*  Open succeeded.                                 */
  315.     break;
  316.    case 1:                                /*  Open returned EBUSY.                            */
  317.     WaitFlag |= PLAY;                            /*  SIGPOLL is sent on close().                     */
  318.     return;
  319.    case -1:                                /*  Open error.                                     */
  320.    default:
  321.     AlertByNoticePrompt(ip->mainWindow,
  322.             "Could not open the audio device.");
  323.     return;
  324.   }
  325.   StartPlay();
  326. }                                    /* end function Play */
  327.