diff options
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/pabrowse.c | 4 | ||||
| -rw-r--r-- | src/utils/pacat.c | 717 | ||||
| -rw-r--r-- | src/utils/pacmd.c | 26 | ||||
| -rw-r--r-- | src/utils/pactl.c | 262 | ||||
| -rw-r--r-- | src/utils/paplay.c | 435 | ||||
| -rw-r--r-- | src/utils/pasuspender.c | 5 | 
6 files changed, 651 insertions, 798 deletions
diff --git a/src/utils/pabrowse.c b/src/utils/pabrowse.c index 288d44a9..a6487b88 100644 --- a/src/utils/pabrowse.c +++ b/src/utils/pabrowse.c @@ -30,6 +30,8 @@  #include <pulse/pulseaudio.h>  #include <pulse/browser.h> +#include <pulsecore/core-util.h> +  static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {      fprintf(stderr, "Got signal, exiting\n");      m->quit(m, 0); @@ -127,7 +129,7 @@ int main(int argc, char *argv[]) {      assert(r == 0);      pa_signal_new(SIGINT, exit_signal_callback, NULL);      pa_signal_new(SIGTERM, exit_signal_callback, NULL); -    signal(SIGPIPE, SIG_IGN); +    pa_disable_sigpipe();      if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) {          fprintf(stderr, "pa_browse_new_full(): %s\n", s); diff --git a/src/utils/pacat.c b/src/utils/pacat.c index 15e842f3..0b6df3d8 100644 --- a/src/utils/pacat.c +++ b/src/utils/pacat.c @@ -35,9 +35,16 @@  #include <fcntl.h>  #include <locale.h> +#include <sndfile.h> +  #include <pulse/i18n.h>  #include <pulse/pulseaudio.h> +#include <pulsecore/macro.h> +#include <pulsecore/core-util.h> +#include <pulsecore/log.h> +#include <pulsecore/sndfile-util.h> +  #define TIME_EVENT_USEC 50000  #define CLEAR_LINE "\x1B[K" @@ -53,35 +60,92 @@ static size_t buffer_length = 0, buffer_index = 0;  static pa_io_event* stdio_event = NULL; -static char *stream_name = NULL, *client_name = NULL, *device = NULL; +static pa_proplist *proplist = NULL; +static char *device = NULL; + +static SNDFILE* sndfile = NULL; -static int verbose = 0; +static pa_bool_t verbose = FALSE;  static pa_volume_t volume = PA_VOLUME_NORM; -static int volume_is_set = 0; +static pa_bool_t volume_is_set = FALSE;  static pa_sample_spec sample_spec = {      .format = PA_SAMPLE_S16LE,      .rate = 44100,      .channels = 2  }; +static pa_bool_t sample_spec_set = FALSE;  static pa_channel_map channel_map; -static int channel_map_set = 0; +static pa_bool_t channel_map_set = FALSE; + +static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL; +static sf_count_t (*writef_function)(SNDFILE *_sndfile, const void *ptr, sf_count_t frames) = NULL;  static pa_stream_flags_t flags = 0; -static size_t latency = 0, process_time=0; +static size_t latency = 0, process_time = 0; + +static pa_bool_t raw = TRUE; +static int file_format = -1;  /* A shortcut for terminating the application */  static void quit(int ret) { -    assert(mainloop_api); +    pa_assert(mainloop_api);      mainloop_api->quit(mainloop_api, ret);  } +/* Connection draining complete */ +static void context_drain_complete(pa_context*c, void *userdata) { +    pa_context_disconnect(c); +} + +/* Stream draining complete */ +static void stream_drain_complete(pa_stream*s, int success, void *userdata) { + +    if (!success) { +        pa_log(_("Failed to drain stream: %s\n"), pa_strerror(pa_context_errno(context))); +        quit(1); +    } + +    if (verbose) +        pa_log(_("Playback stream drained.\n")); + +    pa_stream_disconnect(stream); +    pa_stream_unref(stream); +    stream = NULL; + +    if (!pa_context_drain(context, context_drain_complete, NULL)) +        pa_context_disconnect(context); +    else { +        if (verbose) +            pa_log(_("Draining connection to server.\n")); +    } +} + +/* Start draining */ +static void start_drain(void) { + +    if (stream) { +        pa_operation *o; + +        pa_stream_set_write_callback(stream, NULL, NULL); + +        if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { +            pa_log(_("pa_stream_drain(): %s\n"), pa_strerror(pa_context_errno(context))); +            quit(1); +            return; +        } + +        pa_operation_unref(o); +    } else +        quit(0); +} +  /* Write some data to the stream */  static void do_stream_write(size_t length) {      size_t l; -    assert(length); +    pa_assert(length);      if (!buffer || !buffer_length)          return; @@ -91,7 +155,7 @@ static void do_stream_write(size_t length) {          l = buffer_length;      if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) { -        fprintf(stderr, _("pa_stream_write() failed: %s\n"), pa_strerror(pa_context_errno(context))); +        pa_log(_("pa_stream_write() failed: %s\n"), pa_strerror(pa_context_errno(context)));          quit(1);          return;      } @@ -108,53 +172,121 @@ static void do_stream_write(size_t length) {  /* This is called whenever new data may be written to the stream */  static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { -    assert(s); -    assert(length > 0); +    pa_assert(s); +    pa_assert(length > 0); -    if (stdio_event) -        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); +    if (raw) { +        pa_assert(!sndfile); -    if (!buffer) -        return; +        if (stdio_event) +            mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); + +        if (!buffer) +            return; + +        do_stream_write(length); + +    } else { +        sf_count_t bytes; +        void *data; + +        pa_assert(sndfile); + +        data = pa_xmalloc(length); + +        if (readf_function) { +            size_t k = pa_frame_size(&sample_spec); -    do_stream_write(length); +            if ((bytes = readf_function(sndfile, data, (sf_count_t) (length/k))) > 0) +                bytes *= (sf_count_t) k; + +        } else +            bytes = sf_read_raw(sndfile, data, (sf_count_t) length); + +        if (bytes > 0) +            pa_stream_write(s, data, (size_t) bytes, pa_xfree, 0, PA_SEEK_RELATIVE); +        else +            pa_xfree(data); + +        if (bytes < (sf_count_t) length) +            start_drain(); +    }  }  /* This is called whenever new data may is available */  static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { -    const void *data; -    assert(s); -    assert(length > 0); -    if (stdio_event) -        mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); +    pa_assert(s); +    pa_assert(length > 0); -    if (pa_stream_peek(s, &data, &length) < 0) { -        fprintf(stderr, _("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(context))); -        quit(1); -        return; -    } +    if (raw) { +        pa_assert(!sndfile); -    assert(data); -    assert(length > 0); +        if (stdio_event) +            mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); + + +        while (pa_stream_readable_size(s) > 0) { +            const void *data; + +            if (pa_stream_peek(s, &data, &length) < 0) { +                pa_log(_("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(context))); +                quit(1); +                return; +            } + +            pa_assert(data); +            pa_assert(length > 0); + +            if (buffer) { +                buffer = pa_xrealloc(buffer, buffer_length + length); +                memcpy((uint8_t*) buffer + buffer_length, data, length); +                buffer_length += length; +            } else { +                buffer = pa_xmalloc(length); +                memcpy(buffer, data, length); +                buffer_length = length; +                buffer_index = 0; +            } +            pa_stream_drop(s); +        } -    if (buffer) { -        buffer = pa_xrealloc(buffer, buffer_length + length); -        memcpy((uint8_t*) buffer + buffer_length, data, length); -        buffer_length += length;      } else { -        buffer = pa_xmalloc(length); -        memcpy(buffer, data, length); -        buffer_length = length; -        buffer_index = 0; -    } +        pa_assert(sndfile); + +        while (pa_stream_readable_size(s) > 0) { +            sf_count_t bytes; +            const void *data; + +            if (pa_stream_peek(s, &data, &length) < 0) { +                pa_log(_("pa_stream_peek() failed: %s\n"), pa_strerror(pa_context_errno(context))); +                quit(1); +                return; +            } + +            pa_assert(data); +            pa_assert(length > 0); + +            if (writef_function) { +                size_t k = pa_frame_size(&sample_spec); -    pa_stream_drop(s); +                if ((bytes = writef_function(sndfile, data, (sf_count_t) (length/k))) > 0) +                    bytes *= (sf_count_t) k; + +            } else +                bytes = sf_write_raw(sndfile, data, (sf_count_t) length); + +            if (bytes < (sf_count_t) length) +                quit(1); + +            pa_stream_drop(s); +        } +    }  }  /* This routine is called whenever the stream state changes */  static void stream_state_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      switch (pa_stream_get_state(s)) {          case PA_STREAM_CREATING: @@ -162,29 +294,30 @@ static void stream_state_callback(pa_stream *s, void *userdata) {              break;          case PA_STREAM_READY: +              if (verbose) {                  const pa_buffer_attr *a;                  char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; -                fprintf(stderr, _("Stream successfully created.\n")); +                pa_log(_("Stream successfully created.\n"));                  if (!(a = pa_stream_get_buffer_attr(s))) -                    fprintf(stderr, _("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); +                    pa_log(_("pa_stream_get_buffer_attr() failed: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));                  else {                      if (mode == PLAYBACK) -                        fprintf(stderr, _("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"), a->maxlength, a->tlength, a->prebuf, a->minreq); +                        pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u\n"), a->maxlength, a->tlength, a->prebuf, a->minreq);                      else { -                        assert(mode == RECORD); -                        fprintf(stderr, _("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize); +                        pa_assert(mode == RECORD); +                        pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u\n"), a->maxlength, a->fragsize);                      }                  } -                fprintf(stderr, _("Using sample spec '%s', channel map '%s'.\n"), +                pa_log(_("Using sample spec '%s', channel map '%s'.\n"),                          pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)),                          pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); -                fprintf(stderr, _("Connected to device %s (%u, %ssuspended).\n"), +                pa_log(_("Connected to device %s (%u, %ssuspended).\n"),                          pa_stream_get_device_name(s),                          pa_stream_get_device_index(s),                          pa_stream_is_suspended(s) ? "" : "not "); @@ -194,72 +327,72 @@ static void stream_state_callback(pa_stream *s, void *userdata) {          case PA_STREAM_FAILED:          default: -            fprintf(stderr, _("Stream error: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); +            pa_log(_("Stream error: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));              quit(1);      }  }  static void stream_suspended_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) {          if (pa_stream_is_suspended(s)) -            fprintf(stderr, _("Stream device suspended.%s \n"), CLEAR_LINE); +            pa_log(_("Stream device suspended.%s \n"), CLEAR_LINE);          else -            fprintf(stderr, _("Stream device resumed.%s \n"), CLEAR_LINE); +            pa_log(_("Stream device resumed.%s \n"), CLEAR_LINE);      }  }  static void stream_underflow_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) -        fprintf(stderr, _("Stream underrun.%s \n"),  CLEAR_LINE); +        pa_log(_("Stream underrun.%s \n"),  CLEAR_LINE);  }  static void stream_overflow_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) -        fprintf(stderr, _("Stream overrun.%s \n"), CLEAR_LINE); +        pa_log(_("Stream overrun.%s \n"), CLEAR_LINE);  }  static void stream_started_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) -        fprintf(stderr, _("Stream started.%s \n"), CLEAR_LINE); +        pa_log(_("Stream started.%s \n"), CLEAR_LINE);  }  static void stream_moved_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) -        fprintf(stderr, _("Stream moved to device %s (%u, %ssuspended).%s \n"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "),  CLEAR_LINE); +        pa_log(_("Stream moved to device %s (%u, %ssuspended).%s \n"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "),  CLEAR_LINE);  }  static void stream_buffer_attr_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      if (verbose) -        fprintf(stderr, _("Stream buffer attributes changed.%s \n"),  CLEAR_LINE); +        pa_log(_("Stream buffer attributes changed.%s \n"),  CLEAR_LINE);  }  static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *pl, void *userdata) {      char *t; -    assert(s); -    assert(name); -    assert(pl); +    pa_assert(s); +    pa_assert(name); +    pa_assert(pl);      t = pa_proplist_to_string_sep(pl, ", "); -    fprintf(stderr, "Got event '%s', properties '%s'\n", name, t); +    pa_log("Got event '%s', properties '%s'\n", name, t);      pa_xfree(t);  }  /* This is called whenever the context status changes */  static void context_state_callback(pa_context *c, void *userdata) { -    assert(c); +    pa_assert(c);      switch (pa_context_get_state(c)) {          case PA_CONTEXT_CONNECTING: @@ -271,14 +404,14 @@ static void context_state_callback(pa_context *c, void *userdata) {              int r;              pa_buffer_attr buffer_attr; -            assert(c); -            assert(!stream); +            pa_assert(c); +            pa_assert(!stream);              if (verbose) -                fprintf(stderr, _("Connection established.%s \n"), CLEAR_LINE); +                pa_log(_("Connection established.%s \n"), CLEAR_LINE); -            if (!(stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL))) { -                fprintf(stderr, _("pa_stream_new() failed: %s\n"), pa_strerror(pa_context_errno(c))); +            if (!(stream = pa_stream_new_with_proplist(c, NULL, &sample_spec, &channel_map, proplist))) { +                pa_log(_("pa_stream_new() failed: %s\n"), pa_strerror(pa_context_errno(c)));                  goto fail;              } @@ -306,13 +439,13 @@ static void context_state_callback(pa_context *c, void *userdata) {              if (mode == PLAYBACK) {                  pa_cvolume cv;                  if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) { -                    fprintf(stderr, _("pa_stream_connect_playback() failed: %s\n"), pa_strerror(pa_context_errno(c))); +                    pa_log(_("pa_stream_connect_playback() failed: %s\n"), pa_strerror(pa_context_errno(c)));                      goto fail;                  }              } else {                  if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags)) < 0) { -                    fprintf(stderr, _("pa_stream_connect_record() failed: %s\n"), pa_strerror(pa_context_errno(c))); +                    pa_log(_("pa_stream_connect_record() failed: %s\n"), pa_strerror(pa_context_errno(c)));                      goto fail;                  }              } @@ -326,7 +459,7 @@ static void context_state_callback(pa_context *c, void *userdata) {          case PA_CONTEXT_FAILED:          default: -            fprintf(stderr, _("Connection failure: %s\n"), pa_strerror(pa_context_errno(c))); +            pa_log(_("Connection failure: %s\n"), pa_strerror(pa_context_errno(c)));              goto fail;      } @@ -337,42 +470,14 @@ fail:  } -/* Connection draining complete */ -static void context_drain_complete(pa_context*c, void *userdata) { -    pa_context_disconnect(c); -} - -/* Stream draining complete */ -static void stream_drain_complete(pa_stream*s, int success, void *userdata) { - -    if (!success) { -        fprintf(stderr, _("Failed to drain stream: %s\n"), pa_strerror(pa_context_errno(context))); -        quit(1); -    } - -    if (verbose) -        fprintf(stderr, _("Playback stream drained.\n")); - -    pa_stream_disconnect(stream); -    pa_stream_unref(stream); -    stream = NULL; - -    if (!pa_context_drain(context, context_drain_complete, NULL)) -        pa_context_disconnect(context); -    else { -        if (verbose) -            fprintf(stderr, _("Draining connection to server.\n")); -    } -} -  /* New data on STDIN **/  static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {      size_t l, w = 0;      ssize_t r; -    assert(a == mainloop_api); -    assert(e); -    assert(stdio_event == e); +    pa_assert(a == mainloop_api); +    pa_assert(e); +    pa_assert(stdio_event == e);      if (buffer) {          mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); @@ -387,23 +492,12 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even      if ((r = read(fd, buffer, l)) <= 0) {          if (r == 0) {              if (verbose) -                fprintf(stderr, _("Got EOF.\n")); - -            if (stream) { -                pa_operation *o; - -                if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { -                    fprintf(stderr, _("pa_stream_drain(): %s\n"), pa_strerror(pa_context_errno(context))); -                    quit(1); -                    return; -                } +                pa_log(_("Got EOF.\n")); -                pa_operation_unref(o); -            } else -                quit(0); +            start_drain();          } else { -            fprintf(stderr, _("read() failed: %s\n"), strerror(errno)); +            pa_log(_("read() failed: %s\n"), strerror(errno));              quit(1);          } @@ -423,19 +517,19 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even  static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {      ssize_t r; -    assert(a == mainloop_api); -    assert(e); -    assert(stdio_event == e); +    pa_assert(a == mainloop_api); +    pa_assert(e); +    pa_assert(stdio_event == e);      if (!buffer) {          mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL);          return;      } -    assert(buffer_length); +    pa_assert(buffer_length);      if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) { -        fprintf(stderr, _("write() failed: %s\n"), strerror(errno)); +        pa_log(_("write() failed: %s\n"), strerror(errno));          quit(1);          mainloop_api->io_free(stdio_event); @@ -456,7 +550,7 @@ static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_eve  /* UNIX signal to quit recieved */  static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {      if (verbose) -        fprintf(stderr, _("Got signal, exiting.\n")); +        pa_log(_("Got signal, exiting.\n"));      quit(0);  } @@ -465,17 +559,17 @@ static void stream_update_timing_callback(pa_stream *s, int success, void *userd      pa_usec_t l, usec;      int negative = 0; -    assert(s); +    pa_assert(s);      if (!success ||          pa_stream_get_time(s, &usec) < 0 ||          pa_stream_get_latency(s, &l, &negative) < 0) { -        fprintf(stderr, _("Failed to get latency: %s\n"), pa_strerror(pa_context_errno(context))); +        pa_log(_("Failed to get latency: %s\n"), pa_strerror(pa_context_errno(context)));          quit(1);          return;      } -    fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec.  \r"), +    pa_log(_("Time: %0.3f sec; Latency: %0.0f usec.  \r"),              (float) usec / 1000000,              (float) l * (negative?-1.0f:1.0f));  } @@ -495,7 +589,7 @@ static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struc      if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) {          pa_operation *o;          if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) -            fprintf(stderr, _("pa_stream_update_timing_info() failed: %s\n"), pa_strerror(pa_context_errno(context))); +            pa_log(_("pa_stream_update_timing_info() failed: %s\n"), pa_strerror(pa_context_errno(context)));          else              pa_operation_unref(o);      } @@ -509,34 +603,38 @@ static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struc  static void help(const char *argv0) {      printf(_("%s [options]\n\n" -           "  -h, --help                            Show this help\n" -           "      --version                         Show version\n\n" -           "  -r, --record                          Create a connection for recording\n" -           "  -p, --playback                        Create a connection for playback\n\n" -           "  -v, --verbose                         Enable verbose operations\n\n" -           "  -s, --server=SERVER                   The name of the server to connect to\n" -           "  -d, --device=DEVICE                   The name of the sink/source to connect to\n" -           "  -n, --client-name=NAME                How to call this client on the server\n" -           "      --stream-name=NAME                How to call this stream on the server\n" -           "      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n" -           "      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n" -           "      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n" -           "                                        float32be, ulaw, alaw, s32le, s32be (defaults to s16ne)\n" -           "      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n" -           "                                        (defaults to 2)\n" -           "      --channel-map=CHANNELMAP          Channel map to use instead of the default\n" -           "      --fix-format                      Take the sample format from the sink the stream is\n" -           "                                        being connected to.\n" -           "      --fix-rate                        Take the sampling rate from the sink the stream is\n" -           "                                        being connected to.\n" -           "      --fix-channels                    Take the number of channels and the channel map\n" -           "                                        from the sink the stream is being connected to.\n" -           "      --no-remix                        Don't upmix or downmix channels.\n" -           "      --no-remap                        Map channels by index instead of name.\n" -           "      --latency=BYTES                   Request the specified latency in bytes.\n" -           "      --process-time=BYTES              Request the specified process time per request in bytes.\n") -           , -           argv0); +             "  -h, --help                            Show this help\n" +             "      --version                         Show version\n\n" +             "  -r, --record                          Create a connection for recording\n" +             "  -p, --playback                        Create a connection for playback\n\n" +             "  -v, --verbose                         Enable verbose operations\n\n" +             "  -s, --server=SERVER                   The name of the server to connect to\n" +             "  -d, --device=DEVICE                   The name of the sink/source to connect to\n" +             "  -n, --client-name=NAME                How to call this client on the server\n" +             "      --stream-name=NAME                How to call this stream on the server\n" +             "      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n" +             "      --rate=SAMPLERATE                 The sample rate in Hz (defaults to 44100)\n" +             "      --format=SAMPLEFORMAT             The sample type, one of s16le, s16be, u8, float32le,\n" +             "                                        float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n" +             "                                        s24-32le, s24-32be (defaults to s16ne)\n" +             "      --channels=CHANNELS               The number of channels, 1 for mono, 2 for stereo\n" +             "                                        (defaults to 2)\n" +             "      --channel-map=CHANNELMAP          Channel map to use instead of the default\n" +             "      --fix-format                      Take the sample format from the sink the stream is\n" +             "                                        being connected to.\n" +             "      --fix-rate                        Take the sampling rate from the sink the stream is\n" +             "                                        being connected to.\n" +             "      --fix-channels                    Take the number of channels and the channel map\n" +             "                                        from the sink the stream is being connected to.\n" +             "      --no-remix                        Don't upmix or downmix channels.\n" +             "      --no-remap                        Map channels by index instead of name.\n" +             "      --latency=BYTES                   Request the specified latency in bytes.\n" +             "      --process-time=BYTES              Request the specified process time per request in bytes.\n" +             "      --property=PROPERTY=VALUE         Set the specified property to the specified value.\n" +             "      --raw                             Record/play raw PCM data.\n" +             "      --file-format=FFORMAT             Record/play formatted PCM data.\n" +             "      --list-file-formats               List available file formats.\n") +           , argv0);  }  enum { @@ -553,14 +651,19 @@ enum {      ARG_NO_REMAP,      ARG_NO_REMIX,      ARG_LATENCY, -    ARG_PROCESS_TIME +    ARG_PROCESS_TIME, +    ARG_RAW, +    ARG_PROPERTY, +    ARG_FILE_FORMAT, +    ARG_LIST_FILE_FORMATS  };  int main(int argc, char *argv[]) {      pa_mainloop* m = NULL; -    int ret = 1, r, c; +    int ret = 1, c;      char *bn, *server = NULL;      pa_time_event *time_event = NULL; +    const char *filename = NULL;      static const struct option long_options[] = {          {"record",       0, NULL, 'r'}, @@ -584,21 +687,33 @@ int main(int argc, char *argv[]) {          {"no-remix",     0, NULL, ARG_NO_REMIX},          {"latency",      1, NULL, ARG_LATENCY},          {"process-time", 1, NULL, ARG_PROCESS_TIME}, +        {"property",     1, NULL, ARG_PROPERTY}, +        {"raw",          0, NULL, ARG_RAW}, +        {"file-format",  2, NULL, ARG_FILE_FORMAT}, +        {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS},          {NULL,           0, NULL, 0}      };      setlocale(LC_ALL, "");      bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); -    if (!(bn = strrchr(argv[0], '/'))) -        bn = argv[0]; -    else -        bn++; +    bn = pa_path_get_filename(argv[0]); -    if (strstr(bn, "rec") || strstr(bn, "mon")) +    if (strstr(bn, "play")) { +        mode = PLAYBACK; +        raw = FALSE; +    } else if (strstr(bn, "record")) {          mode = RECORD; -    else if (strstr(bn, "cat") || strstr(bn, "play")) +        raw = FALSE; +    } else if (strstr(bn, "cat")) {          mode = PLAYBACK; +        raw = TRUE; +    } if (strstr(bn, "rec") || strstr(bn, "mon")) { +        mode = RECORD; +        raw = TRUE; +    } + +    proplist = pa_proplist_new();      while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) { @@ -609,7 +724,12 @@ int main(int argc, char *argv[]) {                  goto quit;              case ARG_VERSION: -                printf(_("pacat %s\nCompiled with libpulse %s\nLinked with libpulse %s\n"), PACKAGE_VERSION, pa_get_headers_version(), pa_get_library_version()); +                printf(_("pacat %s\n" +                         "Compiled with libpulse %s\n" +                         "Linked with libpulse %s\n"), +                       PACKAGE_VERSION, +                       pa_get_headers_version(), +                       pa_get_library_version());                  ret = 0;                  goto quit; @@ -631,15 +751,36 @@ int main(int argc, char *argv[]) {                  server = pa_xstrdup(optarg);                  break; -            case 'n': -                pa_xfree(client_name); -                client_name = pa_xstrdup(optarg); +            case 'n': { +                char *t; + +                if (!(t = pa_locale_to_utf8(optarg)) || +                    pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) { + +                    pa_log(_("Invalid client name '%s'\n"), t ? t : optarg); +                    pa_xfree(t); +                    goto quit; +                } + +                pa_xfree(t);                  break; +            } + +            case ARG_STREAM_NAME: { +                char *t; +                t = pa_locale_to_utf8(optarg); -            case ARG_STREAM_NAME: -                pa_xfree(stream_name); -                stream_name = pa_xstrdup(optarg); +                if (!(t = pa_locale_to_utf8(optarg)) || +                    pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) { + +                    pa_log(_("Invalid stream name '%s'\n"), t ? t : optarg); +                    pa_xfree(t); +                    goto quit; +                } + +                pa_xfree(t);                  break; +            }              case 'v':                  verbose = 1; @@ -648,29 +789,32 @@ int main(int argc, char *argv[]) {              case ARG_VOLUME: {                  int v = atoi(optarg);                  volume = v < 0 ? 0U : (pa_volume_t) v; -                volume_is_set = 1; +                volume_is_set = TRUE;                  break;              }              case ARG_CHANNELS:                  sample_spec.channels = (uint8_t) atoi(optarg); +                sample_spec_set = TRUE;                  break;              case ARG_SAMPLEFORMAT:                  sample_spec.format = pa_parse_sample_format(optarg); +                sample_spec_set = TRUE;                  break;              case ARG_SAMPLERATE:                  sample_spec.rate = (uint32_t) atoi(optarg); +                sample_spec_set = TRUE;                  break;              case ARG_CHANNELMAP:                  if (!pa_channel_map_parse(&channel_map, optarg)) { -                    fprintf(stderr, _("Invalid channel map '%s'\n"), optarg); +                    pa_log(_("Invalid channel map '%s'\n"), optarg);                      goto quit;                  } -                channel_map_set = 1; +                channel_map_set = TRUE;                  break;              case ARG_FIX_CHANNELS: @@ -695,17 +839,54 @@ int main(int argc, char *argv[]) {              case ARG_LATENCY:                  if (((latency = (size_t) atoi(optarg))) <= 0) { -                    fprintf(stderr, _("Invalid latency specification '%s'\n"), optarg); +                    pa_log(_("Invalid latency specification '%s'\n"), optarg);                      goto quit;                  }                  break;              case ARG_PROCESS_TIME:                  if (((process_time = (size_t) atoi(optarg))) <= 0) { -                    fprintf(stderr, _("Invalid process time specification '%s'\n"), optarg); +                    pa_log(_("Invalid process time specification '%s'\n"), optarg); +                    goto quit; +                } +                break; + +            case ARG_PROPERTY: { +                char *t; + +                if (!(t = pa_locale_to_utf8(optarg)) || +                    pa_proplist_setp(proplist, t) < 0) { + +                    pa_xfree(t); +                    pa_log(_("Invalid property '%s'\n"), optarg);                      goto quit;                  } + +                pa_xfree(t);                  break; +            } + +            case ARG_RAW: +                raw = TRUE; +                break; + +            case ARG_FILE_FORMAT: +                raw = FALSE; + +                if (optarg) { +                    if ((file_format = pa_sndfile_format_from_string(optarg)) < 0) { +                        pa_log(_("Unknown file format %s."), optarg); +                        goto quit; +                    } +                } + +                raw = FALSE; +                break; + +            case ARG_LIST_FILE_FORMATS: +                pa_sndfile_dump_formats(); +                ret = 0; +                goto quit;              default:                  goto quit; @@ -713,82 +894,168 @@ int main(int argc, char *argv[]) {      }      if (!pa_sample_spec_valid(&sample_spec)) { -        fprintf(stderr, _("Invalid sample specification\n")); +        pa_log(_("Invalid sample specification\n"));          goto quit;      } -    if (channel_map_set && pa_channel_map_compatible(&channel_map, &sample_spec)) { -        fprintf(stderr, _("Channel map doesn't match sample specification\n")); -        goto quit; -    } +    if (optind+1 == argc) { +        int fd; -    if (verbose) { -        char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; -        pa_sample_spec_snprint(t, sizeof(t), &sample_spec); -        fprintf(stderr, _("Opening a %s stream with sample specification '%s'.\n"), mode == RECORD ? _("recording") : _("playback"), t); +        filename = argv[optind]; + +        if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { +            pa_log(_("open(): %s\n"), strerror(errno)); +            goto quit; +        } + +        if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) { +            pa_log(_("dup2(): %s\n"), strerror(errno)); +            goto quit; +        } + +        pa_close(fd); + +    } else if (optind+1 <= argc) { +        pa_log(_("Too many arguments.\n")); +        goto quit;      } -    if (!(optind >= argc)) { -        if (optind+1 == argc) { -            int fd; +    if (!raw) { +        SF_INFO sfi; +        pa_zero(sfi); -            if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { -                fprintf(stderr, _("open(): %s\n"), strerror(errno)); +        if (mode == RECORD) { +            /* This might patch up the sample spec */ +            if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) { +                pa_log(_("Failed to generate sample specification for file.\n"));                  goto quit;              } -            if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) { -                fprintf(stderr, _("dup2(): %s\n"), strerror(errno)); +            /* Transparently upgrade classic .wav to wavex for multichannel audio */ +            if (file_format <= 0) { +                if ((sample_spec.channels == 2 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_LEFT && +                                                                        channel_map.map[1] == PA_CHANNEL_POSITION_RIGHT))) || +                    (sample_spec.channels == 1 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_MONO)))) +                    file_format = SF_FORMAT_WAV; +                else +                    file_format = SF_FORMAT_WAVEX; +            } + +            sfi.format |= file_format; +        } + +        if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO, +                                   mode == RECORD ? SFM_WRITE : SFM_READ, +                                   &sfi, 0))) { +            pa_log(_("Failed to open audio file.\n")); +            goto quit; +        } + +        if (mode == PLAYBACK) { +            if (sample_spec_set) +                pa_log(_("Warning: specified sample specification will be overwritten with specification from file.\n")); + +            if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) { +                pa_log(_("Failed to determine sample specification from file.\n"));                  goto quit;              } +            sample_spec_set = TRUE; + +            if (!channel_map_set) { +                /* Allow the user to overwrite the channel map on the command line */ +                if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) { +                    if (sample_spec.channels > 2) +                        pa_log(_("Warning: Failed to determine channel map from file.\n")); +                } else +                    channel_map_set = TRUE; +            } +        } +    } -            close(fd); +    if (!channel_map_set) +        pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); -            if (!stream_name) -                stream_name = pa_xstrdup(argv[optind]); +    if (!pa_channel_map_compatible(&channel_map, &sample_spec)) { +        pa_log(_("Channel map doesn't match sample specification\n")); +        goto quit; +    } -        } else { -            fprintf(stderr, _("Too many arguments.\n")); -            goto quit; +    if (!raw) { +        pa_proplist *sfp; + +        if (mode == PLAYBACK) +            readf_function = pa_sndfile_readf_function(&sample_spec); +        else { +            if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0) +                pa_log(_("Warning: failed to write channel map to file.\n")); + +            writef_function = pa_sndfile_writef_function(&sample_spec);          } + +        /* Fill in libsndfile prop list data */ +        sfp = pa_proplist_new(); +        pa_sndfile_init_proplist(sndfile, sfp); +        pa_proplist_update(proplist, PA_UPDATE_MERGE, sfp); +        pa_proplist_free(sfp);      } -    if (!client_name) -        client_name = pa_xstrdup(bn); +    if (verbose) { +        char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX]; + +        pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'.\n"), +                mode == RECORD ? _("recording") : _("playback"), +                pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec), +                pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map)); +    } -    if (!stream_name) -        stream_name = pa_xstrdup(client_name); +    /* Fill in client name if none was set */ +    if (!pa_proplist_contains(proplist, PA_PROP_APPLICATION_NAME)) { +        char *t; + +        if ((t = pa_locale_to_utf8(bn))) { +            pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t); +            pa_xfree(t); +        } +    } + +    /* Fill in media name if none was set */ +    if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) { +        const char *t; + +        if ((t = filename) || +            (t = pa_proplist_gets(proplist, PA_PROP_APPLICATION_NAME))) +            pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t); +    }      /* Set up a new main loop */      if (!(m = pa_mainloop_new())) { -        fprintf(stderr, _("pa_mainloop_new() failed.\n")); +        pa_log(_("pa_mainloop_new() failed.\n"));          goto quit;      }      mainloop_api = pa_mainloop_get_api(m); -    r = pa_signal_init(mainloop_api); -    assert(r == 0); +    pa_assert_se(pa_signal_init(mainloop_api) == 0);      pa_signal_new(SIGINT, exit_signal_callback, NULL);      pa_signal_new(SIGTERM, exit_signal_callback, NULL);  #ifdef SIGUSR1      pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);  #endif -#ifdef SIGPIPE -    signal(SIGPIPE, SIG_IGN); -#endif - -    if (!(stdio_event = mainloop_api->io_new(mainloop_api, -                                             mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, -                                             mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, -                                             mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { -        fprintf(stderr, _("io_new() failed.\n")); -        goto quit; +    pa_disable_sigpipe(); + +    if (raw) { +        if (!(stdio_event = mainloop_api->io_new(mainloop_api, +                                                 mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, +                                                 mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, +                                                 mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) { +            pa_log(_("io_new() failed.\n")); +            goto quit; +        }      }      /* Create a new connection context */ -    if (!(context = pa_context_new(mainloop_api, client_name))) { -        fprintf(stderr, _("pa_context_new() failed.\n")); +    if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) { +        pa_log(_("pa_context_new() failed.\n"));          goto quit;      } @@ -796,7 +1063,7 @@ int main(int argc, char *argv[]) {      /* Connect the context */      if (pa_context_connect(context, server, 0, NULL) < 0) { -        fprintf(stderr, _("pa_context_connect() failed: %s\n"), pa_strerror(pa_context_errno(context))); +        pa_log(_("pa_context_connect() failed: %s\n"), pa_strerror(pa_context_errno(context)));          goto quit;      } @@ -807,14 +1074,14 @@ int main(int argc, char *argv[]) {          pa_timeval_add(&tv, TIME_EVENT_USEC);          if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) { -            fprintf(stderr, _("time_new() failed.\n")); +            pa_log(_("time_new() failed.\n"));              goto quit;          }      }      /* Run the main loop */      if (pa_mainloop_run(m, &ret) < 0) { -        fprintf(stderr, _("pa_mainloop_run() failed.\n")); +        pa_log(_("pa_mainloop_run() failed.\n"));          goto quit;      } @@ -826,12 +1093,12 @@ quit:          pa_context_unref(context);      if (stdio_event) { -        assert(mainloop_api); +        pa_assert(mainloop_api);          mainloop_api->io_free(stdio_event);      }      if (time_event) { -        assert(mainloop_api); +        pa_assert(mainloop_api);          mainloop_api->time_free(time_event);      } @@ -844,8 +1111,12 @@ quit:      pa_xfree(server);      pa_xfree(device); -    pa_xfree(client_name); -    pa_xfree(stream_name); + +    if (sndfile) +        sf_close(sndfile); + +    if (proplist) +        pa_proplist_free(proplist);      return ret;  } diff --git a/src/utils/pacmd.c b/src/utils/pacmd.c index d94f2665..ac60a0bc 100644 --- a/src/utils/pacmd.c +++ b/src/utils/pacmd.c @@ -38,11 +38,13 @@  #include <pulse/xmalloc.h>  #include <pulse/i18n.h> +#include <pulsecore/macro.h>  #include <pulsecore/core-util.h>  #include <pulsecore/log.h>  #include <pulsecore/pid.h>  int main(int argc, char*argv[]) { +      pid_t pid ;      int fd = -1;      int ret = 1, i; @@ -56,7 +58,7 @@ int main(int argc, char*argv[]) {      bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);      if (pa_pid_file_check_running(&pid, "pulseaudio") < 0) { -        pa_log("No PulseAudio daemon running, or not running as session daemon."); +        pa_log(_("No PulseAudio daemon running, or not running as session daemon."));          goto fail;      } @@ -65,7 +67,7 @@ int main(int argc, char*argv[]) {          goto fail;      } -    memset(&sa, 0, sizeof(sa)); +    pa_zero(sa);      sa.sun_family = AF_UNIX;      if (!(cli = pa_runtime_path("cli"))) @@ -147,9 +149,9 @@ int main(int argc, char*argv[]) {          if (FD_ISSET(0, &ifds)) {              ssize_t r; -            assert(!ibuf_length); +            pa_assert(!ibuf_length); -            if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) { +            if ((r = pa_read(0, ibuf, sizeof(ibuf), NULL)) <= 0) {                  if (r < 0) {                      pa_log(_("read(): %s"), strerror(errno));                      goto fail; @@ -164,9 +166,9 @@ int main(int argc, char*argv[]) {          if (FD_ISSET(fd, &ifds)) {              ssize_t r; -            assert(!obuf_length); +            pa_assert(!obuf_length); -            if ((r = read(fd, obuf, sizeof(obuf))) <= 0) { +            if ((r = pa_read(fd, obuf, sizeof(obuf), NULL)) <= 0) {                  if (r < 0) {                      pa_log(_("read(): %s"), strerror(errno));                      goto fail; @@ -181,9 +183,9 @@ int main(int argc, char*argv[]) {          if (FD_ISSET(1, &ofds)) {              ssize_t r; -            assert(obuf_length); +            pa_assert(obuf_length); -            if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) { +            if ((r = pa_write(1, obuf + obuf_index, obuf_length, NULL)) < 0) {                  pa_log(_("write(): %s"), strerror(errno));                  goto fail;              } @@ -195,9 +197,9 @@ int main(int argc, char*argv[]) {          if (FD_ISSET(fd, &ofds)) {              ssize_t r; -            assert(ibuf_length); +            pa_assert(ibuf_length); -            if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) { +            if ((r = pa_write(fd, ibuf + ibuf_index, ibuf_length, NULL)) < 0) {                  pa_log(_("write(): %s"), strerror(errno));                  goto fail;              } @@ -207,14 +209,14 @@ int main(int argc, char*argv[]) {          }          if (ibuf_length <= 0 && ibuf_eof && !ibuf_closed) { -            close(0); +            pa_close(0);              shutdown(fd, SHUT_WR);              ibuf_closed = TRUE;          }          if (obuf_length <= 0 && obuf_eof && !obuf_closed) {              shutdown(fd, SHUT_RD); -            close(1); +            pa_close(1);              obuf_closed = TRUE;          }      } diff --git a/src/utils/pactl.c b/src/utils/pactl.c index de1c6d3d..6608c01e 100644 --- a/src/utils/pactl.c +++ b/src/utils/pactl.c @@ -38,9 +38,13 @@  #include <pulse/i18n.h>  #include <pulse/pulseaudio.h> + +#include <pulsecore/macro.h>  #include <pulsecore/core-util.h> +#include <pulsecore/log.h> +#include <pulsecore/sndfile-util.h> -#define BUFSIZE 1024 +#define BUFSIZE (16*1024)  static pa_context *context = NULL;  static pa_mainloop_api *mainloop_api = NULL; @@ -48,16 +52,19 @@ static pa_mainloop_api *mainloop_api = NULL;  static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL, *card_name = NULL, *profile_name = NULL;  static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;  static uint32_t module_index; -static int suspend; +static pa_bool_t suspend; + +static pa_proplist *proplist = NULL;  static SNDFILE *sndfile = NULL;  static pa_stream *sample_stream = NULL;  static pa_sample_spec sample_spec; +static pa_channel_map channel_map;  static size_t sample_length = 0;  static int actions = 1; -static int nl = 0; +static pa_bool_t nl = FALSE;  static enum {      NONE, @@ -77,11 +84,10 @@ static enum {  } action = NONE;  static void quit(int ret) { -    assert(mainloop_api); +    pa_assert(mainloop_api);      mainloop_api->quit(mainloop_api, ret);  } -  static void context_drain_complete(pa_context *c, void *userdata) {      pa_context_disconnect(c);  } @@ -94,9 +100,8 @@ static void drain(void) {          pa_operation_unref(o);  } -  static void complete_action(void) { -    assert(actions > 0); +    pa_assert(actions > 0);      if (!(--actions))          drain(); @@ -105,7 +110,7 @@ static void complete_action(void) {  static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) {      char s[128];      if (!i) { -        fprintf(stderr, _("Failed to get statistics: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get statistics: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -126,7 +131,7 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi      char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];      if (!i) { -        fprintf(stderr, _("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -175,7 +180,7 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get sink information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get sink information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -185,11 +190,11 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE;      printf(_("Sink #%u\n"               "\tState: %s\n" @@ -255,7 +260,7 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get source information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get source information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -265,11 +270,11 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE;      printf(_("Source #%u\n"               "\tState: %s\n" @@ -321,7 +326,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get module information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get module information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -331,13 +336,13 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE; -    snprintf(t, sizeof(t), "%u", i->n_used); +    pa_snprintf(t, sizeof(t), "%u", i->n_used);      printf(_("Module #%u\n"               "\tName: %s\n" @@ -358,7 +363,7 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get client information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get client information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -368,13 +373,13 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE; -    snprintf(t, sizeof(t), "%u", i->owner_module); +    pa_snprintf(t, sizeof(t), "%u", i->owner_module);      printf(_("Client #%u\n"               "\tDriver: %s\n" @@ -393,7 +398,7 @@ static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c)));          complete_action();          return;      } @@ -403,13 +408,13 @@ static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE; -    snprintf(t, sizeof(t), "%u", i->owner_module); +    pa_snprintf(t, sizeof(t), "%u", i->owner_module);      printf(_("Card #%u\n"               "\tName: %s\n" @@ -442,7 +447,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get sink input information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get sink input information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -452,14 +457,14 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE; -    snprintf(t, sizeof(t), "%u", i->owner_module); -    snprintf(k, sizeof(k), "%u", i->client); +    pa_snprintf(t, sizeof(t), "%u", i->owner_module); +    pa_snprintf(k, sizeof(k), "%u", i->client);      printf(_("Sink Input #%u\n"               "\tDriver: %s\n" @@ -500,7 +505,7 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get source output information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get source output information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -510,15 +515,15 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE; -    snprintf(t, sizeof(t), "%u", i->owner_module); -    snprintf(k, sizeof(k), "%u", i->client); +    pa_snprintf(t, sizeof(t), "%u", i->owner_module); +    pa_snprintf(k, sizeof(k), "%u", i->client);      printf(_("Source Output #%u\n"               "\tDriver: %s\n" @@ -551,7 +556,7 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int      char *pl;      if (is_last < 0) { -        fprintf(stderr, _("Failed to get sample information: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failed to get sample information: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -561,11 +566,11 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int          return;      } -    assert(i); +    pa_assert(i);      if (nl)          printf("\n"); -    nl = 1; +    nl = TRUE;      pa_bytes_snprint(t, sizeof(t), i->bytes); @@ -599,7 +604,7 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int  static void simple_callback(pa_context *c, int success, void *userdata) {      if (!success) { -        fprintf(stderr, _("Failure: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -609,7 +614,7 @@ static void simple_callback(pa_context *c, int success, void *userdata) {  static void index_callback(pa_context *c, uint32_t idx, void *userdata) {      if (idx == PA_INVALID_INDEX) { -        fprintf(stderr, _("Failure: %s\n"), pa_strerror(pa_context_errno(c))); +        pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));          quit(1);          return;      } @@ -620,7 +625,7 @@ static void index_callback(pa_context *c, uint32_t idx, void *userdata) {  }  static void stream_state_callback(pa_stream *s, void *userdata) { -    assert(s); +    pa_assert(s);      switch (pa_stream_get_state(s)) {          case PA_STREAM_CREATING: @@ -633,7 +638,7 @@ static void stream_state_callback(pa_stream *s, void *userdata) {          case PA_STREAM_FAILED:          default: -            fprintf(stderr, _("Failed to upload sample: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); +            pa_log(_("Failed to upload sample: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));              quit(1);      }  } @@ -641,16 +646,16 @@ static void stream_state_callback(pa_stream *s, void *userdata) {  static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {      sf_count_t l;      float *d; -    assert(s && length && sndfile); +    pa_assert(s && length && sndfile);      d = pa_xmalloc(length); -    assert(sample_length >= length); +    pa_assert(sample_length >= length);      l = (sf_count_t) (length/pa_frame_size(&sample_spec));      if ((sf_readf_float(sndfile, d, l)) != l) {          pa_xfree(d); -        fprintf(stderr, _("Premature end of file\n")); +        pa_log(_("Premature end of file\n"));          quit(1);          return;      } @@ -666,7 +671,7 @@ static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {  }  static void context_state_callback(pa_context *c, void *userdata) { -    assert(c); +    pa_assert(c);      switch (pa_context_get_state(c)) {          case PA_CONTEXT_CONNECTING:          case PA_CONTEXT_AUTHORIZING: @@ -691,7 +696,7 @@ static void context_state_callback(pa_context *c, void *userdata) {                  case UPLOAD_SAMPLE:                      sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL); -                    assert(sample_stream); +                    pa_assert(sample_stream);                      pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);                      pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL); @@ -749,7 +754,7 @@ static void context_state_callback(pa_context *c, void *userdata) {                      break;                  default: -                    assert(0); +                    pa_assert_not_reached();              }              break; @@ -759,13 +764,13 @@ static void context_state_callback(pa_context *c, void *userdata) {          case PA_CONTEXT_FAILED:          default: -            fprintf(stderr, _("Connection failure: %s\n"), pa_strerror(pa_context_errno(c))); +            pa_log(_("Connection failure: %s\n"), pa_strerror(pa_context_errno(c)));              quit(1);      }  }  static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) { -    fprintf(stderr, _("Got SIGINT, exiting.\n")); +    pa_log(_("Got SIGINT, exiting.\n"));      quit(0);  } @@ -791,13 +796,14 @@ static void help(const char *argv0) {             argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);  } -enum { ARG_VERSION = 256 }; +enum { +    ARG_VERSION = 256 +};  int main(int argc, char *argv[]) {      pa_mainloop* m = NULL; -    char tmp[PATH_MAX]; -    int ret = 1, r, c; -    char *server = NULL, *client_name = NULL, *bn; +    int ret = 1, c; +    char *server = NULL, *bn;      static const struct option long_options[] = {          {"server",      1, NULL, 's'}, @@ -810,10 +816,9 @@ int main(int argc, char *argv[]) {      setlocale(LC_ALL, "");      bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); -    if (!(bn = strrchr(argv[0], '/'))) -        bn = argv[0]; -    else -        bn++; +    bn = pa_path_get_filename(argv[0]); + +    proplist = pa_proplist_new();      while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) {          switch (c) { @@ -837,66 +842,74 @@ int main(int argc, char *argv[]) {                  server = pa_xstrdup(optarg);                  break; -            case 'n': -                pa_xfree(client_name); -                client_name = pa_xstrdup(optarg); +            case 'n': { +                char *t; + +                if (!(t = pa_locale_to_utf8(optarg)) || +                    pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) { + +                    pa_log(_("Invalid client name '%s'\n"), t ? t : optarg); +                    pa_xfree(t); +                    goto quit; +                } + +                pa_xfree(t);                  break; +            }              default:                  goto quit;          }      } -    if (!client_name) -        client_name = pa_xstrdup(bn); -      if (optind < argc) { -        if (!strcmp(argv[optind], "stat")) +        if (pa_streq(argv[optind], "stat"))              action = STAT; -        else if (!strcmp(argv[optind], "exit")) +        else if (pa_streq(argv[optind], "exit"))              action = EXIT; -        else if (!strcmp(argv[optind], "list")) +        else if (pa_streq(argv[optind], "list"))              action = LIST; -        else if (!strcmp(argv[optind], "upload-sample")) { -            struct SF_INFO sfinfo; +        else if (pa_streq(argv[optind], "upload-sample")) { +            struct SF_INFO sfi;              action = UPLOAD_SAMPLE;              if (optind+1 >= argc) { -                fprintf(stderr, _("Please specify a sample file to load\n")); +                pa_log(_("Please specify a sample file to load\n"));                  goto quit;              }              if (optind+2 < argc)                  sample_name = pa_xstrdup(argv[optind+2]);              else { -                char *f = strrchr(argv[optind+1], '/'); -                size_t n; -                if (f) -                    f++; -                else -                    f = argv[optind]; - -                n = strcspn(f, "."); -                strncpy(tmp, f, n); -                tmp[n] = 0; -                sample_name = pa_xstrdup(tmp); +                char *f = pa_path_get_filename(argv[optind+1]); +                sample_name = pa_xstrndup(f, strcspn(f, "."));              } -            memset(&sfinfo, 0, sizeof(sfinfo)); -            if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) { -                fprintf(stderr, _("Failed to open sound file.\n")); +            pa_zero(sfi); +            if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfi))) { +                pa_log(_("Failed to open sound file.\n"));                  goto quit;              } +            if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) { +                pa_log(_("Failed to determine sample specification from file.\n")); +                goto quit; +            }              sample_spec.format = PA_SAMPLE_FLOAT32; -            sample_spec.rate = (uint32_t) sfinfo.samplerate; -            sample_spec.channels = (uint8_t) sfinfo.channels; -            sample_length = (size_t)sfinfo.frames*pa_frame_size(&sample_spec); -        } else if (!strcmp(argv[optind], "play-sample")) { +            if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) { +                if (sample_spec.channels > 2) +                     pa_log(_("Warning: Failed to determine sample specification from file.\n")); +                pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); +            } + +            pa_assert(pa_channel_map_compatible(&channel_map, &sample_spec)); +            sample_length = (size_t) sfi.frames*pa_frame_size(&sample_spec); + +        } else if (pa_streq(argv[optind], "play-sample")) {              action = PLAY_SAMPLE;              if (argc != optind+2 && argc != optind+3) { -                fprintf(stderr, _("You have to specify a sample name to play\n")); +                pa_log(_("You have to specify a sample name to play\n"));                  goto quit;              } @@ -905,33 +918,36 @@ int main(int argc, char *argv[]) {              if (optind+2 < argc)                  device = pa_xstrdup(argv[optind+2]); -        } else if (!strcmp(argv[optind], "remove-sample")) { +        } else if (pa_streq(argv[optind], "remove-sample")) {              action = REMOVE_SAMPLE;              if (argc != optind+2) { -                fprintf(stderr, _("You have to specify a sample name to remove\n")); +                pa_log(_("You have to specify a sample name to remove\n"));                  goto quit;              }              sample_name = pa_xstrdup(argv[optind+1]); -        } else if (!strcmp(argv[optind], "move-sink-input")) { + +        } else if (pa_streq(argv[optind], "move-sink-input")) {              action = MOVE_SINK_INPUT;              if (argc != optind+3) { -                fprintf(stderr, _("You have to specify a sink input index and a sink\n")); +                pa_log(_("You have to specify a sink input index and a sink\n"));                  goto quit;              }              sink_input_idx = (uint32_t) atoi(argv[optind+1]);              sink_name = pa_xstrdup(argv[optind+2]); -        } else if (!strcmp(argv[optind], "move-source-output")) { + +        } else if (pa_streq(argv[optind], "move-source-output")) {              action = MOVE_SOURCE_OUTPUT;              if (argc != optind+3) { -                fprintf(stderr, _("You have to specify a source output index and a source\n")); +                pa_log(_("You have to specify a source output index and a source\n"));                  goto quit;              }              source_output_idx = (uint32_t) atoi(argv[optind+1]);              source_name = pa_xstrdup(argv[optind+2]); -        } else if (!strcmp(argv[optind], "load-module")) { + +        } else if (pa_streq(argv[optind], "load-module")) {              int i;              size_t n = 0;              char *p; @@ -939,7 +955,7 @@ int main(int argc, char *argv[]) {              action = LOAD_MODULE;              if (argc <= optind+1) { -                fprintf(stderr, _("You have to specify a module name and arguments.\n")); +                pa_log(_("You have to specify a module name and arguments.\n"));                  goto quit;              } @@ -955,21 +971,21 @@ int main(int argc, char *argv[]) {                      p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]);              } -        } else if (!strcmp(argv[optind], "unload-module")) { +        } else if (pa_streq(argv[optind], "unload-module")) {              action = UNLOAD_MODULE;              if (argc != optind+2) { -                fprintf(stderr, _("You have to specify a module index\n")); +                pa_log(_("You have to specify a module index\n"));                  goto quit;              }              module_index = (uint32_t) atoi(argv[optind+1]); -        } else if (!strcmp(argv[optind], "suspend-sink")) { +        } else if (pa_streq(argv[optind], "suspend-sink")) {              action = SUSPEND_SINK;              if (argc > optind+3 || optind+1 >= argc) { -                fprintf(stderr, _("You may not specify more than one sink. You have to specify a boolean value.\n")); +                pa_log(_("You may not specify more than one sink. You have to specify a boolean value.\n"));                  goto quit;              } @@ -978,11 +994,11 @@ int main(int argc, char *argv[]) {              if (argc > optind+2)                  sink_name = pa_xstrdup(argv[optind+1]); -        } else if (!strcmp(argv[optind], "suspend-source")) { +        } else if (pa_streq(argv[optind], "suspend-source")) {              action = SUSPEND_SOURCE;              if (argc > optind+3 || optind+1 >= argc) { -                fprintf(stderr, _("You may not specify more than one source. You have to specify a boolean value.\n")); +                pa_log(_("You may not specify more than one source. You have to specify a boolean value.\n"));                  goto quit;              } @@ -990,18 +1006,18 @@ int main(int argc, char *argv[]) {              if (argc > optind+2)                  source_name = pa_xstrdup(argv[optind+1]); -        } else if (!strcmp(argv[optind], "set-card-profile")) { +        } else if (pa_streq(argv[optind], "set-card-profile")) {              action = SET_CARD_PROFILE;              if (argc != optind+3) { -                fprintf(stderr, _("You have to specify a card name/index and a profile name\n")); +                pa_log(_("You have to specify a card name/index and a profile name\n"));                  goto quit;              }              card_name = pa_xstrdup(argv[optind+1]);              profile_name = pa_xstrdup(argv[optind+2]); -        } else if (!strcmp(argv[optind], "help")) { +        } else if (pa_streq(argv[optind], "help")) {              help(bn);              ret = 0;              goto quit; @@ -1009,37 +1025,35 @@ int main(int argc, char *argv[]) {      }      if (action == NONE) { -        fprintf(stderr, _("No valid command specified.\n")); +        pa_log(_("No valid command specified.\n"));          goto quit;      }      if (!(m = pa_mainloop_new())) { -        fprintf(stderr, _("pa_mainloop_new() failed.\n")); +        pa_log(_("pa_mainloop_new() failed.\n"));          goto quit;      }      mainloop_api = pa_mainloop_get_api(m); -    r = pa_signal_init(mainloop_api); -    assert(r == 0); +    pa_assert_se(pa_signal_init(mainloop_api) == 0);      pa_signal_new(SIGINT, exit_signal_callback, NULL); -#ifdef SIGPIPE -    signal(SIGPIPE, SIG_IGN); -#endif +    pa_signal_new(SIGTERM, exit_signal_callback, NULL); +    pa_disable_sigpipe(); -    if (!(context = pa_context_new(mainloop_api, client_name))) { -        fprintf(stderr, _("pa_context_new() failed.\n")); +    if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) { +        pa_log(_("pa_context_new() failed.\n"));          goto quit;      }      pa_context_set_state_callback(context, context_state_callback, NULL);      if (pa_context_connect(context, server, 0, NULL) < 0) { -        fprintf(stderr, _("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); +        pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));          goto quit;      }      if (pa_mainloop_run(m, &ret) < 0) { -        fprintf(stderr, _("pa_mainloop_run() failed.\n")); +        pa_log(_("pa_mainloop_run() failed.\n"));          goto quit;      } @@ -1055,18 +1069,20 @@ quit:          pa_mainloop_free(m);      } -    if (sndfile) -        sf_close(sndfile); -      pa_xfree(server);      pa_xfree(device);      pa_xfree(sample_name);      pa_xfree(sink_name);      pa_xfree(source_name);      pa_xfree(module_args); -    pa_xfree(client_name);      pa_xfree(card_name);      pa_xfree(profile_name); +    if (sndfile) +        sf_close(sndfile); + +    if (proplist) +        pa_proplist_free(proplist); +      return ret;  } diff --git a/src/utils/paplay.c b/src/utils/paplay.c deleted file mode 100644 index f6ba6f6d..00000000 --- a/src/utils/paplay.c +++ /dev/null @@ -1,435 +0,0 @@ -/*** -  This file is part of PulseAudio. - -  Copyright 2004-2006 Lennart Poettering -  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB - -  PulseAudio is free software; you can redistribute it and/or modify -  it under the terms of the GNU Lesser General Public License as published -  by the Free Software Foundation; either version 2.1 of the License, -  or (at your option) any later version. - -  PulseAudio is distributed in the hope that it will be useful, but -  WITHOUT ANY WARRANTY; without even the implied warranty of -  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -  General Public License for more details. - -  You should have received a copy of the GNU Lesser General Public License -  along with PulseAudio; if not, write to the Free Software -  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -  USA. -***/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <signal.h> -#include <string.h> -#include <errno.h> -#include <unistd.h> -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <getopt.h> -#include <locale.h> - -#include <sndfile.h> - -#include <pulse/pulseaudio.h> -#include <pulse/i18n.h> - -static pa_context *context = NULL; -static pa_stream *stream = NULL; -static pa_mainloop_api *mainloop_api = NULL; - -static char *stream_name = NULL, *client_name = NULL, *device = NULL; - -static int verbose = 0; -static pa_volume_t volume = PA_VOLUME_NORM; - -static SNDFILE* sndfile = NULL; - -static pa_sample_spec sample_spec = { 0, 0, 0 }; -static pa_channel_map channel_map; -static int channel_map_set = 0; - -static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL; - -/* A shortcut for terminating the application */ -static void quit(int ret) { -    assert(mainloop_api); -    mainloop_api->quit(mainloop_api, ret); -} - -/* Connection draining complete */ -static void context_drain_complete(pa_context*c, void *userdata) { -    pa_context_disconnect(c); -} - -/* Stream draining complete */ -static void stream_drain_complete(pa_stream*s, int success, void *userdata) { -    pa_operation *o; - -    if (!success) { -        fprintf(stderr, _("Failed to drain stream: %s\n"), pa_strerror(pa_context_errno(context))); -        quit(1); -    } - -    if (verbose) -        fprintf(stderr, _("Playback stream drained.\n")); - -    pa_stream_disconnect(stream); -    pa_stream_unref(stream); -    stream = NULL; - -    if (!(o = pa_context_drain(context, context_drain_complete, NULL))) -        pa_context_disconnect(context); -    else { -        pa_operation_unref(o); - -        if (verbose) -            fprintf(stderr, _("Draining connection to server.\n")); -    } -} - -/* This is called whenever new data may be written to the stream */ -static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { -    sf_count_t bytes; -    void *data; -    assert(s && length); - -    if (!sndfile) -        return; - -    data = pa_xmalloc(length); - -    if (readf_function) { -        size_t k = pa_frame_size(&sample_spec); - -        if ((bytes = readf_function(sndfile, data, (sf_count_t) (length/k))) > 0) -            bytes *= (sf_count_t) k; - -    } else -        bytes = sf_read_raw(sndfile, data, (sf_count_t) length); - -    if (bytes > 0) -        pa_stream_write(s, data, (size_t) bytes, pa_xfree, 0, PA_SEEK_RELATIVE); -    else -        pa_xfree(data); - -    if (bytes < (sf_count_t) length) { -        sf_close(sndfile); -        sndfile = NULL; -        pa_operation_unref(pa_stream_drain(s, stream_drain_complete, NULL)); -    } -} - -/* This routine is called whenever the stream state changes */ -static void stream_state_callback(pa_stream *s, void *userdata) { -    assert(s); - -    switch (pa_stream_get_state(s)) { -        case PA_STREAM_CREATING: -        case PA_STREAM_TERMINATED: -            break; - -        case PA_STREAM_READY: -            if (verbose) -                fprintf(stderr, _("Stream successfully created\n")); -            break; - -        case PA_STREAM_FAILED: -        default: -            fprintf(stderr, _("Stream errror: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); -            quit(1); -    } -} - -/* This is called whenever the context status changes */ -static void context_state_callback(pa_context *c, void *userdata) { -    assert(c); - -    switch (pa_context_get_state(c)) { -        case PA_CONTEXT_CONNECTING: -        case PA_CONTEXT_AUTHORIZING: -        case PA_CONTEXT_SETTING_NAME: -            break; - -        case PA_CONTEXT_READY: { -            pa_cvolume cv; - -            assert(c && !stream); - -            if (verbose) -                fprintf(stderr, _("Connection established.\n")); - -            stream = pa_stream_new(c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL); -            assert(stream); - -            pa_stream_set_state_callback(stream, stream_state_callback, NULL); -            pa_stream_set_write_callback(stream, stream_write_callback, NULL); -            pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL); - -            break; -        } - -        case PA_CONTEXT_TERMINATED: -            quit(0); -            break; - -        case PA_CONTEXT_FAILED: -        default: -            fprintf(stderr, _("Connection failure: %s\n"), pa_strerror(pa_context_errno(c))); -            quit(1); -    } -} - -/* UNIX signal to quit recieved */ -static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { -    if (verbose) -        fprintf(stderr, _("Got SIGINT, exiting.\n")); -    quit(0); - -} - -static void help(const char *argv0) { - -    printf(_("%s [options] [FILE]\n\n" -           "  -h, --help                            Show this help\n" -           "      --version                         Show version\n\n" -           "  -v, --verbose                         Enable verbose operation\n\n" -           "  -s, --server=SERVER                   The name of the server to connect to\n" -           "  -d, --device=DEVICE                   The name of the sink to connect to\n" -           "  -n, --client-name=NAME                How to call this client on the server\n" -           "      --stream-name=NAME                How to call this stream on the server\n" -           "      --volume=VOLUME                   Specify the initial (linear) volume in range 0...65536\n" -             "      --channel-map=CHANNELMAP          Set the channel map to the use\n"), -           argv0); -} - -enum { -    ARG_VERSION = 256, -    ARG_STREAM_NAME, -    ARG_VOLUME, -    ARG_CHANNELMAP -}; - -int main(int argc, char *argv[]) { -    pa_mainloop* m = NULL; -    int ret = 1, r, c; -    char *bn, *server = NULL; -    const char *filename; -    SF_INFO sfinfo; - -    static const struct option long_options[] = { -        {"device",      1, NULL, 'd'}, -        {"server",      1, NULL, 's'}, -        {"client-name", 1, NULL, 'n'}, -        {"stream-name", 1, NULL, ARG_STREAM_NAME}, -        {"version",     0, NULL, ARG_VERSION}, -        {"help",        0, NULL, 'h'}, -        {"verbose",     0, NULL, 'v'}, -        {"volume",      1, NULL, ARG_VOLUME}, -        {"channel-map", 1, NULL, ARG_CHANNELMAP}, -        {NULL,          0, NULL, 0} -    }; - -    setlocale(LC_ALL, ""); -    bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); - -    if (!(bn = strrchr(argv[0], '/'))) -        bn = argv[0]; -    else -        bn++; - -    while ((c = getopt_long(argc, argv, "d:s:n:hv", long_options, NULL)) != -1) { - -        switch (c) { -            case 'h' : -                help(bn); -                ret = 0; -                goto quit; - -            case ARG_VERSION: -                printf(_("paplay %s\nCompiled with libpulse %s\n" -                        "Linked with libpulse %s\n"), PACKAGE_VERSION, pa_get_headers_version(), pa_get_library_version()); -                ret = 0; -                goto quit; - -            case 'd': -                pa_xfree(device); -                device = pa_xstrdup(optarg); -                break; - -            case 's': -                pa_xfree(server); -                server = pa_xstrdup(optarg); -                break; - -            case 'n': -                pa_xfree(client_name); -                client_name = pa_xstrdup(optarg); -                break; - -            case ARG_STREAM_NAME: -                pa_xfree(stream_name); -                stream_name = pa_xstrdup(optarg); -                break; - -            case 'v': -                verbose = 1; -                break; - -            case ARG_VOLUME: { -                int v = atoi(optarg); -                volume = v < 0 ? 0U : (pa_volume_t) v; -                break; -            } - -            case ARG_CHANNELMAP: -                if (!pa_channel_map_parse(&channel_map, optarg)) { -                    fprintf(stderr, _("Invalid channel map\n")); -                    goto quit; -                } - -                channel_map_set = 1; -                break; - -            default: -                goto quit; -        } -    } - -    filename = optind < argc ? argv[optind] : "STDIN"; - -    memset(&sfinfo, 0, sizeof(sfinfo)); - -    if (optind < argc) -        sndfile = sf_open(filename, SFM_READ, &sfinfo); -    else -        sndfile = sf_open_fd(STDIN_FILENO, SFM_READ, &sfinfo, 0); - -    if (!sndfile) { -        fprintf(stderr, _("Failed to open file '%s'\n"), filename); -        goto quit; -    } - -    sample_spec.rate = (uint32_t) sfinfo.samplerate; -    sample_spec.channels = (uint8_t) sfinfo.channels; - -    readf_function = NULL; - -    switch (sfinfo.format & 0xFF) { -        case SF_FORMAT_PCM_16: -        case SF_FORMAT_PCM_U8: -        case SF_FORMAT_PCM_S8: -            sample_spec.format = PA_SAMPLE_S16NE; -            readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short; -            break; - -        case SF_FORMAT_ULAW: -            sample_spec.format = PA_SAMPLE_ULAW; -            break; - -        case SF_FORMAT_ALAW: -            sample_spec.format = PA_SAMPLE_ALAW; -            break; - -        case SF_FORMAT_FLOAT: -        case SF_FORMAT_DOUBLE: -        default: -            sample_spec.format = PA_SAMPLE_FLOAT32NE; -            readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_float; -            break; -    } - -    assert(pa_sample_spec_valid(&sample_spec)); - -    if (channel_map_set && channel_map.channels != sample_spec.channels) { -        fprintf(stderr, _("Channel map doesn't match file.\n")); -        goto quit; -    } - -    if (!client_name) { -        client_name = pa_locale_to_utf8(bn); -        if (!client_name) -            client_name = pa_utf8_filter(bn); -    } - -    if (!stream_name) { -        const char *n; - -        n = sf_get_string(sndfile, SF_STR_TITLE); - -        if (!n) -            n = filename; - -        stream_name = pa_locale_to_utf8(n); -        if (!stream_name) -            stream_name = pa_utf8_filter(n); -    } - -    if (verbose) { -        char t[PA_SAMPLE_SPEC_SNPRINT_MAX]; -        pa_sample_spec_snprint(t, sizeof(t), &sample_spec); -        fprintf(stderr, _("Using sample spec '%s'\n"), t); -    } - -    /* Set up a new main loop */ -    if (!(m = pa_mainloop_new())) { -        fprintf(stderr, _("pa_mainloop_new() failed.\n")); -        goto quit; -    } - -    mainloop_api = pa_mainloop_get_api(m); - -    r = pa_signal_init(mainloop_api); -    assert(r == 0); -    pa_signal_new(SIGINT, exit_signal_callback, NULL); -#ifdef SIGPIPE -    signal(SIGPIPE, SIG_IGN); -#endif - -    /* Create a new connection context */ -    if (!(context = pa_context_new(mainloop_api, client_name))) { -        fprintf(stderr, _("pa_context_new() failed.\n")); -        goto quit; -    } - -    pa_context_set_state_callback(context, context_state_callback, NULL); - -    /* Connect the context */ -    if (pa_context_connect(context, server, 0, NULL) < 0) { -        fprintf(stderr, _("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); -        goto quit; -    } - -    /* Run the main loop */ -    if (pa_mainloop_run(m, &ret) < 0) { -        fprintf(stderr, _("pa_mainloop_run() failed.\n")); -        goto quit; -    } - -quit: -    if (stream) -        pa_stream_unref(stream); - -    if (context) -        pa_context_unref(context); - -    if (m) { -        pa_signal_done(); -        pa_mainloop_free(m); -    } - -    pa_xfree(server); -    pa_xfree(device); -    pa_xfree(client_name); -    pa_xfree(stream_name); - -    if (sndfile) -        sf_close(sndfile); - -    return ret; -} diff --git a/src/utils/pasuspender.c b/src/utils/pasuspender.c index b4bccd56..c327ee41 100644 --- a/src/utils/pasuspender.c +++ b/src/utils/pasuspender.c @@ -235,10 +235,7 @@ int main(int argc, char *argv[]) {      setlocale(LC_ALL, "");      bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); -    if (!(bn = strrchr(argv[0], '/'))) -        bn = argv[0]; -    else -        bn++; +    bn = pa_path_get_filename(argv[0]);      while ((c = getopt_long(argc, argv, "s:h", long_options, NULL)) != -1) {          switch (c) {  | 
