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

yplay.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <signal.h>

#include "../include/Y2/Y.h"
#include "../include/Y2/Ylib.h"

#include "../include/string.h"
#include "../include/disk.h"


static void handle_signal(int s);
static void print_help(void);

static Boolean interrupted;
static Boolean verbose;
static Boolean allow_change_mode;


#define MIN(a,b)        ((a) < (b) ? (a) : (b))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define ABSOLUTE(x)     (((x) < 0) ? ((x) * -1) : (x))


/*
 *    Signal handler.
 */
static void handle_signal(int s)
{
      switch(s)
      {
#ifdef SIGINT
        case SIGINT:
          interrupted = True;
          break;
#endif
#ifdef SIGTERM
        case SIGTERM:
            interrupted = True;
            break; 
#endif
#ifdef SIGPIPE
          case SIGPIPE:
            break;
#endif
#ifdef SIGHUP
          case SIGHUP:
            break;
#endif
#ifdef SIGCONT
          case SIGCONT:
            break;
#endif
      }
}


/*
 *    Prints help message.
 */
static void print_help(void)
{
      printf("\
Usage: yplay [options] <file1> [file2] ...\n\
\n\
    [options] can be any of the following:\n\
\n\
        -m                           Allow change Audio mode as needed\n\
                                     (may cause sound objects played by\n\
                                     other applications to be killed).\n\
      -s <samplerate>              Applied sample rate in Hz.\n\
        -r <n>                       Repeat n times (-1 for infinate).\n\
        -vol <left> <right>          Specify volume coefficients.\n\
        -v                           Print verbose status messages.\n\
        --recorder <address:port>    Specify which Y server to connect to.\n\
\n\
    <file1> [file2] ... are a list of files to be played. Their paths must\n\
    be relative to the server, not your current directory on your computer.\n\
\n\
    To interrupt the play at any time, press ctrl+c.\n\
\n\
    Return values:\n\
\n\
        0       Success.\n\
        1       General error.\n\
        2       Cannot connect to Y server error.\n\
        3       Systems error.\n\
\n"
      );
}



int main(int argc, char *argv[])
{
      int i;
      const char *arg_ptr;

      const char *con_arg = NULL;

      Boolean playing;
      long cycle;

      int total_repeats = 1;
      char **file = NULL;
      int total_files = 0;

      YConnection *con = NULL;
      YEvent event;
      YEventSoundObjectAttributes au_stats;

      YID         play_id = YIDNULL;
      Coefficient vol_left = 1.0,
                  vol_right = 1.0;
      int         applied_sample_rate = 0;
      YEventSoundPlay   value;

      char tmp_path[PATH_MAX + NAME_MAX];


      /* Reset globals. */
      interrupted = False;
      verbose = False;
      allow_change_mode = False;

      /* Set up signals to watch for. */
#ifdef SIGINT
      signal(SIGINT, handle_signal);
#endif
#ifdef SIGTERM
        signal(SIGTERM, handle_signal);
#endif
#ifdef SIGPIPE
        signal(SIGPIPE, handle_signal);
#endif
#ifdef SIGHUP
      signal(SIGHUP, handle_signal);
#endif
#ifdef SIGCONT
        signal(SIGCONT, handle_signal);
#endif

      /* If there are not enough arguments given then print the help
       * message.
       */
      if(argc < 2)
      {
          print_help();
            return(1);
      }

      /* Parse arguments. */
      for(i = 1; i < argc; i++)
      {
          arg_ptr = argv[i];
          if(arg_ptr == NULL)
            continue;

          /* Help. */
          if(strcasepfx(arg_ptr, "--h") ||
               strcasepfx(arg_ptr, "-h") ||
               !strcmp(arg_ptr, "?")
          )
          {
            print_help();
            return(0);
          }
          /* Connect address. */
          else if(strcasepfx(arg_ptr, "--rec") ||
                    strcasepfx(arg_ptr, "-rec")
          )
          {
            i++;
            arg_ptr = (i < argc) ? argv[i] : NULL;
            if(arg_ptr != NULL)
            {
                con_arg = arg_ptr;
            }
            else
            {
                fprintf(
                  stderr,
                  "%s: Requires argument.\n",
                  argv[i - 1]
                );
                    continue;
            }
          }
          /* Repeat. */
            else if(!strcasecmp(arg_ptr, "-r"))
            {
                i++;
                arg_ptr = (i < argc) ? argv[i] : NULL;
                if(arg_ptr != NULL)
                {
                total_repeats = atoi(arg_ptr);
                    if(total_repeats == 0)
                        fprintf(
                      stderr,
                            "%s: Warning: Value must be non-zero.\n",
                            argv[i - 1]
                        );
            }
            else
            {
                    fprintf(
                  stderr,
                  "%s: Requires argument.\n",
                  argv[i - 1]
                    );
                continue;
            }
            }
            /* Change mode. */
            else if(!strcasecmp(arg_ptr, "-m"))
            {
                allow_change_mode = True;
            }
          /* Volume. */
          else if(!strcasecmp(argv[i], "-vol"))
            {
            i++;
                arg_ptr = (i < argc) ? argv[i] : NULL;
                if(arg_ptr != NULL)
                {
                    vol_left = atof(arg_ptr);
                }
                else
                {
                    fprintf(
                  stderr,
                        "%s: Requires at least 2 arguments.\n",
                        argv[i - 1]
                    );
                continue;
                }

                i++;
                arg_ptr = (i < argc) ? argv[i] : NULL;
                if(arg_ptr != NULL)
                {
                    vol_right = atof(arg_ptr);
                }
                else
                {
                    fprintf(
                  stderr,
                        "%s: Requires at least 2 arguments.\n",
                        argv[i - 1]
                    );
                continue;
                }
            }
          /* Applied sample rate. */
            else if(!strcasecmp(arg_ptr, "-s"))
            {
                i++;
                arg_ptr = (i < argc) ? argv[i] : NULL;
                if(arg_ptr != NULL)
                {   
                    applied_sample_rate = MAX(atoi(arg_ptr), 0);
                }
            else
                {
                    fprintf(
                  stderr,
                        "%s: Requires argument.\n",
                        argv[i - 1]
                    );
                continue;
                }
          }
            /* Verbose. */
            else if(!strcasecmp(arg_ptr, "-v"))
            {
                verbose = True;
            }
          /* All else assume argument to be a file. */
          else if((*arg_ptr != '\0') &&
                    (*arg_ptr != '-') &&
                    (*arg_ptr != '+')
          )
          {
            int n = total_files;
            total_files = n + 1;

            file = (char **)realloc(
                file,
                total_files * sizeof(char *)
            );
            if(file == NULL)
            {
                total_files = 0;
                continue;
            }
            else
            {
                file[n] = strdup(arg_ptr);
            }
          }
      }


        /* Connect to Y server. */
        con = YOpenConnection(
            NULL,               /* No start argument. */
            con_arg
        );          
        if(con == NULL)
        {
            fprintf(stderr, "Cannot connect to Y server");
            if(con_arg == NULL)
                con_arg = getenv("RECORDER");
            if(con_arg == NULL)
                fprintf(stderr, ".\n");
            else
                fprintf(stderr, ": %s\n", con_arg);

          /* Free list of files to be played. */
            StringFreeArray(file, total_files);
            file = NULL;
            total_files = 0;

            return(2);
        }


      /* Begin playing. */
      if(True)
      {
          /* Warn if repeating infinatly. */
          if(total_repeats < 0)
            printf(
 "Infinatly repeating, press ctrl+c or send SIGINT to stop play.\n"
            );

          /* Go through each file. */
          for(i = 0; i < total_files; i++)
          {
            if(file[i] == NULL)
                continue;

            /* Get sound object attributes. */
                if(YGetSoundObjectAttributes(
                    con,
                    file[i],
                    &au_stats
                ))
            {
                    fprintf( 
                        stderr,
 "%s: Cannot get object attributes.\n",
                        file[i]
                    );
                    fprintf(
                        stderr,
 "Check path notation and object's format.\n"
                    );
                continue;
            }

            /* Change audio mode as needed. */
            if((au_stats.format == SndObjTypeDSP) &&
                   allow_change_mode
            )
            {
                /* Get listing of Audio modes available. */
                int mc, mt;
                YAudioModeValuesStruct **m, *mp, *matched_mode = NULL;

                m = YGetAudioModes(con, &mt);
                for(mc = 0; mc < mt; mc++)
                {
                  mp = m[mc];
                  if(mp == NULL)
                      continue;

                  if((mp->sample_rate == au_stats.sample_rate) &&
                           (mp->channels == au_stats.channels) &&
                     (mp->sample_size == au_stats.sample_size)
                  )
                  {
                      matched_mode = mp;
                      break;
                  }
                }
                if(matched_mode == NULL)
                {
                  /* No Audio mode matched. */
                  cycle = YCalculateCycle(
                      con,
                      au_stats.sample_rate,     /* Sample rate. */
                      au_stats.channels,        /* Channels. */
                      au_stats.sample_size,     /* Bits. */
                      4096                /* Fragment size. */
                    );
                    if(cycle < 100)
                      cycle = 100;

                  YSetAudioModeValues(
                      con,
                      au_stats.sample_size,     /* Bits. */
                      au_stats.channels,        /* Channels. */
                      au_stats.sample_rate,     /* Sample rate. */
                      0,                        /* Play/record. */
                      1,                        /* Allow fragmenting. */
                      2,                        /* Num fragments. */
                      4096
                    );
                  YSyncAll(con, True);
                  YSetCycle(con, cycle);
                }
                else
                {
                  /* Matched mode. */
                  YChangeAudioModePreset(con, matched_mode->name);
                }

                YFreeAudioModesList(m, mt);
            }


            /* Begin playing this sound object. */
            value.flags = YPlayValuesFlagPosition |
                              YPlayValuesFlagTotalRepeats |
                              YPlayValuesFlagVolume |
                              YPlayValuesFlagSampleRate;
            value.position = 0;
            value.total_repeats = total_repeats;
            value.left_volume = vol_left;
            value.right_volume = vol_right;
            value.sample_rate = applied_sample_rate;
            play_id = YStartPlaySoundObject(con, file[i], &value);
            if(play_id == YIDNULL)
            {
                fprintf(
                  stderr,
                  "%s: Cannot play.\n",
                  file[i]
                );
                continue;
            }

            /* Print info about this sound object as needed. */
                if(verbose)
                {
                    strncpy(
                        tmp_path,
                        file[i],
                        PATH_MAX + NAME_MAX
                    );
                    tmp_path[PATH_MAX + NAME_MAX - 1] = '\0';
                    StringShortenFL(tmp_path, 24);

                    switch(au_stats.format)
                    {
                      case SndObjTypeDSP:
                        printf(
"ID: %ld  Type: DSP  SmpRate: %i Hz  Bits: %i  Ch: %i  %s\n",
                            play_id,
                            au_stats.sample_rate,
                            au_stats.sample_size,
                            au_stats.channels,
                            tmp_path
                        );
                        break;
                     
                      case SndObjTypeMIDI:
                        printf(
 "ID: %ld  Type: MIDI  %s\n",
                            play_id,
                            tmp_path
                        );
                        break;
                        
                      default:
                        printf(
 "ID: %ld  Type: *Unknown*  %s\n",
                            play_id,
                            tmp_path
                        );
                    }
                }

            /* Wait untill audio is done playing. */
            playing = True;
            while(playing && !interrupted)
            {
                if(YGetNextEvent(
                  con,
                  &event,
                  False       /* Nonblocking. */
                ) > 0)
                {
                      switch(event.type)
                    {
                      case YSoundObjectKill:
                      if(event.kill.yid == play_id)
                      {
                        /* Current sound object no longer playing. */
                          playing = False;
                      }
                      else
                      {
                        /* Some other YID has stopped playing,
                         * notify about this abnormality.
                         */
                          fprintf(
                            stderr,
         "Warning: Unmanaged play ID %ld has stopped.\n",
                            event.kill.yid
                          );
                      }
                      break;

                    case YDisconnect:
                    case YShutdown:
                      /* Free list of files to be played. */
                            StringFreeArray(file, total_files);
                      file = NULL;
                      total_files = 0;

                      /* Consider disconnect/shutdown as an
                       * interrupt.
                       */
                      interrupted = True;

                      /* Current sound object no longer playing. */
                      playing = False;

                      /* Connection structure needs to be closed. */
                      YCloseConnection(con, False);
                      con = NULL;

                      break;
                  }
                }

                usleep(8000);
            }     /* Wait untill audio is done playing. */

            /* If interupted during play, then stop playing. */
            if(interrupted)
            {
                if(verbose)
                    printf("Playback interrupted.\n");
                break;
            }
          }
      }


        /* Disconnect from Y server. */
        YCloseConnection(con, False);
        con = NULL;

      /* Free list of files to be played. */
      StringFreeArray(file, total_files);
        file = NULL;
        total_files = 0;

      return(0);
}

Generated by  Doxygen 1.6.0   Back to index