Logo Search packages:      
Sourcecode: nas version File versions  Download package

audiotool.c

/*
 * Copyright 1993 Network Computing Devices, Inc.
 * 
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name Network Computing Devices, Inc. not be
 * used in advertising or publicity pertaining to distribution of this
 * software without specific, written prior permission.
 * 
 * THIS SOFTWARE IS PROVIDED 'AS-IS'.  NETWORK COMPUTING DEVICES, INC.,
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NONINFRINGEMENT.  IN NO EVENT SHALL NETWORK
 * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
 * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
 * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 * 
 * $Id: audiotool.c,v 1.5 2004/06/20 23:27:08 jon Exp $
 * $NCDId: @(#)audiotool.c,v 1.27 1994/11/01 23:16:14 greg Exp $
 */

/*
 * auplay -- a simple clone of Sun's audiotool
 */

#include "config.h"

#include    <stdio.h>

#if defined(HAVE_STDLIB_H)
# include <stdlib.h> 
#endif

#if defined(HAVE_MALLOC_H)
# include <malloc.h>
#endif

#include    <audio/audiolib.h>
#include    <audio/soundlib.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <audio/Xtutil.h>

/* widgets */
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Scrollbar.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/SimpleMenu.h>
#include <X11/Xaw/MenuButton.h>
#include <X11/Xaw/SmeBSB.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/Toggle.h>

#if XtSpecificationRelease < 5
#define XawChainTop XtChainTop
#define XawChainLeft XtChainLeft
#endif

#define APP_INSTANCE          "autool"
#define     APP_CLASS         "Autool"
#define SPACING_X       5
#define SPACING_Y       5
#define BORDER_X        5
#define BORDER_Y        5
#define INFO_COLS       50
#define INFO_ROWS       10
#define SAMPLES_COLS          50
#define SAMPLES_ROWS          10
#define BUCKETS_COLS          strlen(BUCKET_HEADER)
#define BUCKETS_ROWS          5
#define     VOLUME_FORMAT           "Volume: %3d%%"
#define     DEFAULT_VOLUME          10
#define BUF_SIZE        200
#define     MAX_VOLUME        200
#define     MIN_VOLUME        1
#define     DOUBLE_CLICK_TIME 500000            /* in microseconds */
#define PORTAL_SIZE           100000
#define VOL             AuFixedPointFromFraction(globals->volume, 100)


#define AddToLinkedList(head, item)                                            \
{                                                                              \
    (item)->prev = NULL;                                                       \
    (item)->next = head;                                           \
    if (head)                                                      \
      (head)->prev = item;                                         \
    head = item;                                             \
}

#define RemoveFromLinkedList(head, item)                           \
{                                                            \
    if ((item)->next)                                              \
      (item)->next->prev = (item)->prev;                           \
                                                         \
   if ((item)->prev)                                              \
       (item)->prev->next = (item)->next;                         \
   else                                                     \
       head = (item)->next;                                       \
}


static String   defaultResources[] =
{
    "*font:       *courier-medium-r-normal*140*",
    NULL
};

static void     fatalError();

#define Invert(w)                                            \
{                                                            \
    Pixel fg, bg;                                            \
                                                             \
    XtVaGetValues(w, XtNforeground, &fg, XtNbackground, &bg, NULL);            \
    XtVaSetValues(w, XtNforeground, bg, XtNbackground, fg, NULL);        \
}

#define makeArg(resource, value)                                   \
    XtSetArg(args[i], resource, (XtArgVal) (value)); i++

#define Anchor()                                             \
    makeArg(XtNtop, XawChainTop);                                  \
    makeArg(XtNbottom, XawChainTop);                                     \
    makeArg(XtNleft, XawChainLeft);                                \
    makeArg(XtNright, XawChainLeft);                                     \

#define MakeCommandButton(w, parent, label, horiz, vert, callback)             \
{                                                            \
    Arg args[6];                                             \
    int i = 0;                                                     \
                                                             \
    Anchor();                                                      \
    makeArg(XtNfromHoriz, horiz);                                  \
    makeArg(XtNfromVert, vert);                                          \
                                                             \
    (w) = XtCreateManagedWidget(label, commandWidgetClass, parent, args, i);   \
                                                             \
    /* SUPPRESS 558 */                                             \
    if ((void *) (callback) != NULL)                                     \
      XtAddCallback(w, XtNcallback, callback, (XtPointer) globals);            \
}

#define MakeLabel(w, parent, label, horiz, vert)                         \
{                                                            \
    Arg args[7];                                             \
    int i = 0;                                                     \
                                                             \
    Anchor();                                                      \
    makeArg(XtNfromHoriz, horiz);                                  \
    makeArg(XtNfromVert, vert);                                          \
    makeArg(XtNborderWidth, 0);                                          \
                                                             \
    (w) = XtCreateManagedWidget(label, labelWidgetClass, parent, args, i);     \
}

typedef struct _VolumeList
{
    AuFlowID        flow;
    unsigned int    elementNumber;
    struct _VolumeList *prev,
                   *next;
}               VolumeListRec, *VolumeListPtr;

typedef VolumeListPtr VolumeListId;

typedef struct
{
    Widget          topLevel,
                    quit,
                    form,
                    play,
                    stop,
                    samples,
                    info,
                    view,
                    volumeBar,
                    volumeLabel;
    int             volume;
    AuServer       *aud;
    Display        *dpy;
    AuDeviceID      inputDeviceId;
    char           *filename;

    Bool            playing;
    AuFlowID        flow;
    int             multiplier;
    VolumeListId    vol;
}               GlobalDataRec, *GlobalDataPtr;

static VolumeListPtr VolumeList;
static int      VolumeListCount;

#define RemoveFromVolumeList(id)                                   \
{                                                            \
    RemoveFromLinkedList(VolumeList, (VolumeListPtr) id);                \
    VolumeListCount--;                                             \
}

static          VolumeListId
AddToVolumeList(flow, elementNumber)
AuFlowID        flow;
unsigned int    elementNumber;
{
    VolumeListPtr   p;

    if (!(p = (VolumeListPtr) malloc(sizeof(VolumeListRec))))
      fatalError("malloc error in AddToVolumeList");

    p->flow = flow;
    p->elementNumber = elementNumber;

    AddToLinkedList(VolumeList, p);
    VolumeListCount++;

    return (VolumeListId) p;
}

typedef struct
{
    GlobalDataPtr   globals;
    void            (*callback) ();
}               DonePrivRec, *DonePrivPtr;

/* ARGSUSED */
static void
doneCB(aud, handler, ev, d)
AuServer       *aud;
AuEventHandlerRec *handler;
AuEvent        *ev;
AuPointer       d;
{
    DonePrivPtr     data = (DonePrivPtr) d;

    (*data->callback) (NULL, data->globals, data);
}

/* ARGSUSED */
static void
stopCB(w, g, data)
Widget          w;
XtPointer       g;
XtPointer       data;
{
    GlobalDataPtr   globals = (GlobalDataPtr) g;

    if (globals->playing)
    {
      if (w)
          /* user requested stop */
          AuStopFlow(globals->aud, globals->flow, NULL);
      else
      {
          /* got a done callback */
          RemoveFromVolumeList(globals->vol);
          globals->playing = False;
          Invert(globals->play);
      }

      return;
    }
}

/* ARGSUSED */
static void
playCB(w, g, data)
Widget          w;
XtPointer       g;
XtPointer       data;
{
    static DonePrivRec priv;
    GlobalDataPtr   globals = (GlobalDataPtr) g;

    priv.globals = globals;
    priv.callback = stopCB;

    if (globals->playing)
      return;
    if (AuSoundPlayFromFile(globals->aud, globals->filename, AuNone,
           VOL, doneCB, &priv, &globals->flow, &globals->multiplier, NULL,
                      NULL))
    {
      globals->vol = AddToVolumeList(globals->flow, globals->multiplier);
      globals->playing = True;
      Invert(globals->play);
    }
}

static          Bool
showInfo(globals)
GlobalDataPtr   globals;
{
    Sound           s;

    if ((s = SoundOpenFileForReading(globals->filename)))
    {
      char           *buf,
                     *p;

#define PRINT(p, f, a)                                             \
{                                                            \
    sprintf(p, f, a);                                              \
    p += strlen(p);                                                \
}

      if (!(p = buf = (char *) malloc(2000 + strlen(SoundComment(s)))))
          fatalError("Can't malloc text in showInfo");

      PRINT(p, "   Filename: %s\n", globals->filename);
      PRINT(p, "File Format: %s\n", SoundFileFormatString(s));
      PRINT(p, "Data Format: %s\n", SoundDataFormatString(s));
      PRINT(p, "     Tracks: %d\n", SoundNumTracks(s));
      PRINT(p, "  Frequency: %d Hz\n", SoundSampleRate(s));
      PRINT(p, "   Duration: %.2f seconds\n",
            (float) SoundNumSamples(s) / SoundSampleRate(s));

      PRINT(p, "\n%s", SoundComment(s));

      XtVaSetValues(globals->info, XtNstring, buf, NULL);

      free(buf);
      SoundCloseFile(s);
      return AuTrue;
    }
    else
    {
      return AuFalse;
    }
}

/* ARGSUSED */
static void
quitCB(w, data, call_data)
Widget          w;
XtPointer       data;
XtPointer       call_data;
{
    exit(0);
}

static void
adjustVolume(globals)
GlobalDataPtr   globals;
{
    AuElementParameters *parms;
    VolumeListPtr   p = VolumeList;
    int             i = 0;

    if (!VolumeListCount)
      return;

    if (!(parms = (AuElementParameters *)
        malloc(sizeof(AuElementParameters) * VolumeListCount)))
      fatalError("malloc error in adjustVolume");

    while (p)
    {
      parms[i].flow = p->flow;
      parms[i].element_num = p->elementNumber;
      parms[i].num_parameters = AuParmsMultiplyConstant;
      parms[i].parameters[AuParmsMultiplyConstantConstant] = VOL;

      p = p->next;
      i++;
    }

    AuSetElementParameters(globals->aud, VolumeListCount, parms, NULL);
    free(parms);
}

/* ARGSUSED */
static void
scrollProcCB(w, data, cd)
Widget          w;
XtPointer       data;
XtPointer       cd;
{
    GlobalDataPtr   globals = (GlobalDataPtr) data;
    int             position = (int) cd;
    int             newVolume;
    char            buf[50];

    newVolume = globals->volume + (position > 0 ? -1 : 1);

    if (newVolume < MIN_VOLUME)
      newVolume = MIN_VOLUME;
    else if (newVolume > MAX_VOLUME)
      newVolume = MAX_VOLUME;

    if (newVolume != globals->volume)
    {
      globals->volume = newVolume;
      sprintf(buf, VOLUME_FORMAT, globals->volume);
      XtVaSetValues(globals->volumeLabel, XtNlabel, buf, NULL);

      XawScrollbarSetThumb(globals->volumeBar,
                       (float) globals->volume / MAX_VOLUME, -1.0);
      adjustVolume(globals);
    }
}

/* ARGSUSED */
static void
jumpProcCB(w, data, cd)
Widget          w;
XtPointer       data;
XtPointer       cd;
{
    int             newVolume;
    char            buf[50];
    GlobalDataPtr   globals = (GlobalDataPtr) data;
    float          *percent = (float *) cd;;

    newVolume = *percent * MAX_VOLUME;

    if (newVolume < MIN_VOLUME)
      newVolume = MIN_VOLUME;

    if (newVolume != globals->volume)
    {
      globals->volume = newVolume;
      sprintf(buf, VOLUME_FORMAT, globals->volume);
      XtVaSetValues(globals->volumeLabel, XtNlabel, buf, NULL);
      adjustVolume(globals);
    }
}

static          Dimension
getFontCharWidth(w)
Widget          w;
{
    XFontStruct    *font;

    XtVaGetValues(w, XtNfont, &font, NULL);
    return font->max_bounds.rbearing - font->min_bounds.lbearing;
}

static          Dimension
getFontCharHeight(w)
Widget          w;
{
    XFontStruct    *font;

    XtVaGetValues(w, XtNfont, &font, NULL);
    return font->max_bounds.ascent + font->max_bounds.descent;
}

static char    *progname;

static void
usage()
{
    fprintf(stderr,
          "Usage: %s [-audio servername] [-volume percentage] [-toolkitoption ...] file\n", APP_INSTANCE);
    exit(-1);
}

int
main(argc, argv)
int             argc;
char          **argv;
{
    int             i;
    Dimension       infoWidth,
                    labelHeight;
    Arg             args[10];
    char            buf[BUF_SIZE],
                   *audioServerString = NULL;
    GlobalDataRec   globalData,
                   *globals;
    Position        infoX,
                    barX;
    XtAppContext    appContext;
    Widget          w;

    /* static          XtActionsRec Actions[] = {"Ok", okAction}; */

    progname = argv[0];

    globals = &globalData;

    globals->topLevel = XtVaAppInitialize(&appContext, APP_CLASS, NULL, ZERO,
                                &argc, argv, defaultResources,
                                NULL, 0);

    XtVaSetValues(globals->topLevel, XtNinput, True, NULL);

    globals->volume = DEFAULT_VOLUME;
    globals->playing = False;
    globals->dpy = XtDisplay(globals->topLevel);
    globals->filename = NULL;

    while (argc > 1)
    {
      argv++;
      argc--;

      if (!strcmp("-a", *argv) || !strcmp("-audio", *argv))
      {
          if (argv[1])
            audioServerString = argv[1];
          else
            usage();
          argv++;
          argc--;
      }
      else if (!strcmp("-v", *argv) || !strcmp("-volume", *argv))
      {
          if (argv[1])
            globals->volume = atoi(argv[1]);
          else
            usage();
          argv++;
          argc--;
      }
      else if (**argv == '-')
      {
          usage();
      }
      else
          globals->filename = *argv;
    }
    if (!globals->filename)
      fatalError("No sound file to play");


    if (!(globals->aud = AuOpenServer(audioServerString, 0, NULL, 0, NULL,
                              NULL)))
      fatalError("Can't connect to audio server");

    for (i = 0; i < AuServerNumDevices(globals->aud); i++)
      if ((AuDeviceKind(AuServerDevice(globals->aud, i)) ==
           AuComponentKindPhysicalInput))
      {
          globals->inputDeviceId =
            AuDeviceIdentifier(AuServerDevice(globals->aud, i));
          break;
      }
    /* XtAppAddActions(appContext, Actions, XtNumber(Actions)); */

    globals->form = XtCreateManagedWidget("form", formWidgetClass,
                                globals->topLevel, NULL, 0);

    MakeCommandButton(globals->play, globals->form, "Play", NULL, NULL, playCB);
    MakeCommandButton(globals->stop, globals->form, "Stop", globals->play,
                  NULL, stopCB);
    MakeCommandButton(globals->quit, globals->form, "Quit", globals->stop,
                  NULL, quitCB);

    sprintf(buf, "NAS %d.%d", AuServerProtocolMajorVersion(globals->aud),
          AuServerProtocolMinorVersion(globals->aud));
    MakeLabel(w, globals->form, buf, globals->quit, NULL);

    i = 0;
    Anchor();
    makeArg(XtNfromVert, globals->play);
    sprintf(buf, VOLUME_FORMAT, globals->volume);
    makeArg(XtNlabel, buf);
    globals->volumeLabel = XtCreateManagedWidget("VolumeLabel",
                                     labelWidgetClass,
                                     globals->form, args, i);

    i = 0;
    makeArg(XtNtop, XawChainTop);
    makeArg(XtNbottom, XawChainTop);
    makeArg(XtNleft, XawChainLeft);
    makeArg(XtNfromHoriz, globals->volumeLabel);
    makeArg(XtNfromVert, globals->play);
    makeArg(XtNorientation, XtorientHorizontal);
    makeArg(XtNresizable, True);
    globals->volumeBar = XtCreateManagedWidget("VolumeBar",
                                     scrollbarWidgetClass,
                                     globals->form, args, i);
    XawScrollbarSetThumb(globals->volumeBar,
                   ((float) globals->volume) / MAX_VOLUME, -1.0);
    XtAddCallback(globals->volumeBar, XtNscrollProc, scrollProcCB, globals);
    XtAddCallback(globals->volumeBar, XtNjumpProc, jumpProcCB, globals);

    i = 0;
    makeArg(XtNtop, XawChainTop);
    makeArg(XtNbottom, XawChainTop);
    makeArg(XtNscrollVertical, XawtextScrollWhenNeeded);
    makeArg(XtNwrap, XawtextWrapWord);
    makeArg(XtNdisplayCaret, False);
    makeArg(XtNfromVert, globals->volumeLabel);
    globals->info = XtCreateManagedWidget("info", asciiTextWidgetClass,
                                globals->form, args, i);

    i = 0;
    infoWidth = getFontCharWidth(globals->info) * INFO_COLS;
    makeArg(XtNwidth, infoWidth);
    makeArg(XtNheight, getFontCharHeight(globals->info) * INFO_ROWS);
    XtSetValues(globals->info, args, i);

    if (!showInfo(globals))
    {
      FILE           *fp;

      /* figure out why it failed */
      fp = fopen(globals->filename, "r");
      if (fp)
      {
          fprintf(stderr,
                "Cannot parse sound file \"%s\".\n", globals->filename);
      }
      else
      {
          perror(globals->filename);
      }
      fclose(fp);
      exit(-1);
    }
    XtRealizeWidget(globals->topLevel);

    XtVaGetValues(globals->info, XtNx, &infoX, NULL);
    XtVaGetValues(globals->volumeBar, XtNx, &barX, NULL);
    XtVaGetValues(globals->volumeLabel, XtNheight, &labelHeight, NULL);
    XtVaSetValues(globals->volumeBar, XtNwidth, infoX + infoWidth - barX,
              XtNheight, labelHeight, NULL);

    AuXtAppAddAudioHandler(appContext, globals->aud);
    playCB(globals->play, (XtPointer) globals, (XtPointer) 0);
    XtAppMainLoop(appContext);
    return 0;
}

static void
fatalError(message, arg)
char           *message,
               *arg;
{
    fprintf(stderr, message, arg);
    fprintf(stderr, ".\n");
    exit(1);
}

Generated by  Doxygen 1.6.0   Back to index