static GstJackAudioConnection *
gst_jack_audio_get_connection (const gchar * id, const gchar * server,
    jack_client_t * jclient, jack_status_t * status)
{
  GstJackAudioConnection *conn;
  GList *found;
  FindData data;

  GST_DEBUG ("getting connection for id %s, server %s", id,
      GST_STR_NULL (server));

  data.id = id;
  data.server = server;

  G_LOCK (connections_lock);
  found =
      g_list_find_custom (connections, &data, (GCompareFunc) connection_find);
  if (found != NULL && jclient != NULL) {
    /* we found it, increase refcount and return it */
    conn = (GstJackAudioConnection *) found->data;
    conn->refcount++;

    GST_DEBUG ("found connection %p", conn);
  } else {
    /* make new connection */
    conn = gst_jack_audio_make_connection (id, server, jclient, status);
    if (conn != NULL) {
      GST_DEBUG ("created connection %p", conn);
      /* add to list on success */
      connections = g_list_prepend (connections, conn);
    } else {
      GST_WARNING ("could not create connection");
    }
  }
  G_UNLOCK (connections_lock);

  return conn;
}
static void
print_plugin (const gchar * marker, GstRegistry * registry, GstPlugin * plugin)
{
  const gchar *name;
  GList *features, *f;

  name = gst_plugin_get_name (plugin);

  GST_DEBUG ("%s: plugin %p %d %s file: %s", marker, plugin,
      GST_OBJECT_REFCOUNT (plugin), name,
      GST_STR_NULL (gst_plugin_get_filename (plugin)));

  features = gst_registry_get_feature_list_by_plugin (registry, name);
  for (f = features; f != NULL; f = f->next) {
    GstPluginFeature *feature;

    feature = GST_PLUGIN_FEATURE (f->data);

    GST_LOG ("%s:    feature: %p %s", marker, feature,
        GST_OBJECT_NAME (feature));
  }
  gst_plugin_feature_list_free (features);
}
/**
 * gst_element_factory_make:
 * @factoryname: a named factory to instantiate
 * @name: (allow-none): name of new element, or NULL to automatically create
 *    a unique name
 *
 * Create a new element of the type defined by the given element factory.
 * If name is NULL, then the element will receive a guaranteed unique name,
 * consisting of the element factory name and a number.
 * If name is given, it will be given the name supplied.
 *
 * Returns: (transfer full): new #GstElement or NULL if unable to create element
 */
GstElement *
gst_element_factory_make (const gchar * factoryname, const gchar * name)
{
  GstElementFactory *factory;
  GstElement *element;

  g_return_val_if_fail (factoryname != NULL, NULL);
  g_return_val_if_fail (gst_is_initialized (), NULL);

  GST_LOG ("gstelementfactory: make \"%s\" \"%s\"",
      factoryname, GST_STR_NULL (name));

  factory = gst_element_factory_find (factoryname);
  if (factory == NULL)
    goto no_factory;

  GST_LOG_OBJECT (factory, "found factory %p", factory);
  element = gst_element_factory_create (factory, name);
  if (element == NULL)
    goto create_failed;

  gst_object_unref (factory);
  return element;

  /* ERRORS */
no_factory:
  {
    GST_INFO ("no such element factory \"%s\"!", factoryname);
    return NULL;
  }
create_failed:
  {
    GST_INFO_OBJECT (factory, "couldn't create instance!");
    gst_object_unref (factory);
    return NULL;
  }
}
static void
jack_shutdown_cb (void *arg)
{
  GstJackAudioConnection *conn = (GstJackAudioConnection *) arg;
  GList *walk;

  GST_DEBUG ("disconnect client %s from server %s", conn->id,
      GST_STR_NULL (conn->server));

  g_mutex_lock (conn->lock);
  for (walk = conn->src_clients; walk; walk = g_list_next (walk)) {
    GstJackAudioClient *client = (GstJackAudioClient *) walk->data;

    if (client->shutdown)
      client->shutdown (client->user_data);
  }
  for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) {
    GstJackAudioClient *client = (GstJackAudioClient *) walk->data;

    if (client->shutdown)
      client->shutdown (client->user_data);
  }
  g_mutex_unlock (conn->lock);
}
Beispiel #5
0
static gboolean
gst_mms_do_seek (GstBaseSrc * src, GstSegment * segment)
{
  mms_off_t start;
  GstMMS *mmssrc = GST_MMS (src);

  if (segment->format == GST_FORMAT_TIME) {
    if (!mmsx_time_seek (NULL, mmssrc->connection,
            (double) segment->start / GST_SECOND)) {
      GST_LOG_OBJECT (mmssrc, "mmsx_time_seek() failed");
      return FALSE;
    }
    start = mmsx_get_current_pos (mmssrc->connection);
    GST_INFO_OBJECT (mmssrc, "sought to %" GST_TIME_FORMAT ", offset after "
        "seek: %" G_GINT64_FORMAT, GST_TIME_ARGS (segment->start), start);
  } else if (segment->format == GST_FORMAT_BYTES) {
    start = mmsx_seek (NULL, mmssrc->connection, segment->start, SEEK_SET);
    /* mmsx_seek will close and reopen the connection when seeking with the
       mmsh protocol, if the reopening fails this is indicated with -1 */
    if (start == -1) {
      GST_DEBUG_OBJECT (mmssrc, "connection broken during seek");
      return FALSE;
    }
    GST_INFO_OBJECT (mmssrc, "sought to: %" G_GINT64_FORMAT " bytes, "
        "result: %" G_GINT64_FORMAT, segment->start, start);
  } else {
    GST_DEBUG_OBJECT (mmssrc, "unsupported seek segment format: %s",
        GST_STR_NULL (gst_format_get_name (segment->format)));
    return FALSE;
  }
  gst_segment_init (segment, GST_FORMAT_BYTES);
  gst_segment_set_seek (segment, segment->rate, GST_FORMAT_BYTES,
      segment->flags, GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_NONE,
      segment->stop, NULL);
  return TRUE;
}
Beispiel #6
0
void
totem_gst_message_print (GstMessage *msg,
			 GstElement *play,
			 const char *filename)
{
  GError *err = NULL;
  char *dbg = NULL;

  g_return_if_fail (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR);

  if (play != NULL) {
    g_return_if_fail (filename != NULL);

    GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN_CAST (play),
			       GST_DEBUG_GRAPH_SHOW_ALL ^ GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS,
			       filename);
  }

  gst_message_parse_error (msg, &err, &dbg);
  if (err) {
    char *uri;

    g_object_get (play, "uri", &uri, NULL);
    GST_ERROR ("message = %s", GST_STR_NULL (err->message));
    GST_ERROR ("domain  = %d (%s)", err->domain,
        GST_STR_NULL (g_quark_to_string (err->domain)));
    GST_ERROR ("code    = %d", err->code);
    GST_ERROR ("debug   = %s", GST_STR_NULL (dbg));
    GST_ERROR ("source  = %" GST_PTR_FORMAT, msg->src);
    GST_ERROR ("uri     = %s", GST_STR_NULL (uri));
    g_free (uri);

    g_message ("Error: %s\n%s\n", GST_STR_NULL (err->message),
        GST_STR_NULL (dbg));

    g_error_free (err);
  }
  g_free (dbg);
}
Beispiel #7
0
static gboolean
gst_rtp_g722_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstRtpG722Depay *rtpg722depay;
  gint clock_rate, payload, samplerate;
  gint channels;
  GstCaps *srccaps;
  gboolean res;
  const gchar *channel_order;
  const GstRTPChannelOrder *order;

  rtpg722depay = GST_RTP_G722_DEPAY (depayload);

  structure = gst_caps_get_structure (caps, 0);

  payload = 96;
  gst_structure_get_int (structure, "payload", &payload);
  switch (payload) {
    case GST_RTP_PAYLOAD_G722:
      channels = 1;
      clock_rate = 8000;
      samplerate = 16000;
      break;
    default:
      /* no fixed mapping, we need clock-rate */
      channels = 0;
      clock_rate = 0;
      samplerate = 0;
      break;
  }

  /* caps can overwrite defaults */
  clock_rate =
      gst_rtp_g722_depay_parse_int (structure, "clock-rate", clock_rate);
  if (clock_rate == 0)
    goto no_clockrate;

  if (clock_rate == 8000)
    samplerate = 16000;

  if (samplerate == 0)
    samplerate = clock_rate;

  channels =
      gst_rtp_g722_depay_parse_int (structure, "encoding-params", channels);
  if (channels == 0) {
    channels = gst_rtp_g722_depay_parse_int (structure, "channels", channels);
    if (channels == 0) {
      /* channels defaults to 1 otherwise */
      channels = 1;
    }
  }

  depayload->clock_rate = clock_rate;
  rtpg722depay->rate = samplerate;
  rtpg722depay->channels = channels;

  srccaps = gst_caps_new_simple ("audio/G722",
      "rate", G_TYPE_INT, samplerate, "channels", G_TYPE_INT, channels, NULL);

  /* add channel positions */
  channel_order = gst_structure_get_string (structure, "channel-order");

  order = gst_rtp_channels_get_by_order (channels, channel_order);
  if (order) {
    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0),
        order->pos);
  } else {
    GstAudioChannelPosition *pos;

    GST_ELEMENT_WARNING (rtpg722depay, STREAM, DECODE,
        (NULL), ("Unknown channel order '%s' for %d channels",
            GST_STR_NULL (channel_order), channels));
    /* create default NONE layout */
    pos = gst_rtp_channels_create_default (channels);
    gst_audio_set_channel_positions (gst_caps_get_structure (srccaps, 0), pos);
    g_free (pos);
  }

  res = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return res;

  /* ERRORS */
no_clockrate:
  {
    GST_ERROR_OBJECT (depayload, "no clock-rate specified");
    return FALSE;
  }
}
static gboolean
gst_gsettings_audio_sink_change_child (GstGSettingsAudioSink * sink)
{
  const gchar *key = NULL;
  gchar *new_string;
  GError *err = NULL;
  GstElement *new_kid;

  GST_OBJECT_LOCK (sink);
  switch (sink->profile) {
    case GST_GSETTINGS_AUDIOSINK_PROFILE_SOUNDS:
      key = GST_GSETTINGS_KEY_SOUNDS_AUDIOSINK;
      break;
    case GST_GSETTINGS_AUDIOSINK_PROFILE_MUSIC:
      key = GST_GSETTINGS_KEY_MUSIC_AUDIOSINK;
      break;
    case GST_GSETTINGS_AUDIOSINK_PROFILE_CHAT:
      key = GST_GSETTINGS_KEY_CHAT_AUDIOSINK;
      break;
    default:
      break;
  }

  new_string = g_settings_get_string (sink->settings, key);

  if (new_string != NULL && sink->gsettings_str != NULL &&
      (strlen (new_string) == 0 ||
          strcmp (sink->gsettings_str, new_string) == 0)) {
    g_free (new_string);
    GST_DEBUG_OBJECT (sink,
        "GSettings key was updated, but it didn't change. Ignoring");
    GST_OBJECT_UNLOCK (sink);
    return TRUE;
  }
  GST_OBJECT_UNLOCK (sink);

  GST_DEBUG_OBJECT (sink, "GSettings key changed from '%s' to '%s'",
      GST_STR_NULL (sink->gsettings_str), GST_STR_NULL (new_string));

  if (new_string) {
    new_kid = gst_parse_bin_from_description (new_string, TRUE, &err);
    if (err) {
      GST_ERROR_OBJECT (sink, "error creating bin '%s': %s", new_string,
          err->message);
      g_error_free (err);
    }
  } else {
    new_kid = NULL;
  }

  if (new_kid == NULL) {
    GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
        ("Failed to render audio sink from GSettings"));
    goto fail;
  }

  if (!gst_switch_sink_set_child (GST_SWITCH_SINK (sink), new_kid)) {
    GST_WARNING_OBJECT (sink, "Failed to update child element");
    goto fail;
  }

  g_free (sink->gsettings_str);
  sink->gsettings_str = new_string;

  return TRUE;

fail:
  g_free (new_string);
  return FALSE;
}
Beispiel #9
0
static gboolean
gst_pulsesrc_open (GstAudioSrc * asrc)
{
  GstPulseSrc *pulsesrc = GST_PULSESRC_CAST (asrc);
  gchar *name = gst_pulse_client_name ();

  pa_threaded_mainloop_lock (pulsesrc->mainloop);

  g_assert (!pulsesrc->context);
  g_assert (!pulsesrc->stream);

  GST_DEBUG_OBJECT (pulsesrc, "opening device");

  if (!(pulsesrc->context =
          pa_context_new (pa_threaded_mainloop_get_api (pulsesrc->mainloop),
              name))) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to create context"),
        (NULL));
    goto unlock_and_fail;
  }

  pa_context_set_state_callback (pulsesrc->context,
      gst_pulsesrc_context_state_cb, pulsesrc);

  GST_DEBUG_OBJECT (pulsesrc, "connect to server %s",
      GST_STR_NULL (pulsesrc->server));

  if (pa_context_connect (pulsesrc->context, pulsesrc->server, 0, NULL) < 0) {
    GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
            pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
    goto unlock_and_fail;
  }

  for (;;) {
    pa_context_state_t state;

    state = pa_context_get_state (pulsesrc->context);

    if (!PA_CONTEXT_IS_GOOD (state)) {
      GST_ELEMENT_ERROR (pulsesrc, RESOURCE, FAILED, ("Failed to connect: %s",
              pa_strerror (pa_context_errno (pulsesrc->context))), (NULL));
      goto unlock_and_fail;
    }

    if (state == PA_CONTEXT_READY)
      break;

    /* Wait until the context is ready */
    pa_threaded_mainloop_wait (pulsesrc->mainloop);
  }
  GST_DEBUG_OBJECT (pulsesrc, "connected");

  pa_threaded_mainloop_unlock (pulsesrc->mainloop);

  g_free (name);
  return TRUE;

  /* ERRORS */
unlock_and_fail:
  {
    gst_pulsesrc_destroy_context (pulsesrc);

    pa_threaded_mainloop_unlock (pulsesrc->mainloop);

    g_free (name);
    return FALSE;
  }
}
/* make a connection with @id and @server. Returns NULL on failure with the
 * status set. */
static GstJackAudioConnection *
gst_jack_audio_make_connection (const gchar * id, const gchar * server,
    jack_client_t * jclient, jack_status_t * status)
{
  GstJackAudioConnection *conn;
  jack_options_t options;
  gint res;

  *status = 0;

  GST_DEBUG ("new client %s, connecting to server %s", id,
      GST_STR_NULL (server));

  /* never start a server */
  options = JackNoStartServer;
  /* if we have a servername, use it */
  if (server != NULL)
    options |= JackServerName;
  /* open the client */
  if (jclient == NULL)
    jclient = jack_client_open (id, options, status, server);
  if (jclient == NULL)
    goto could_not_open;

  /* now create object */
  conn = g_new (GstJackAudioConnection, 1);
  conn->refcount = 1;
  g_mutex_init (&conn->lock);
  g_cond_init (&conn->flush_cond);
  conn->id = g_strdup (id);
  conn->server = g_strdup (server);
  conn->client = jclient;
  conn->n_clients = 0;
  conn->src_clients = NULL;
  conn->sink_clients = NULL;
  conn->cur_ts = -1;
  conn->transport_state = GST_STATE_VOID_PENDING;

  /* set our callbacks  */
  jack_set_process_callback (jclient, jack_process_cb, conn);
  /* these callbacks cause us to error */
  jack_set_buffer_size_callback (jclient, jack_buffer_size_cb, conn);
  jack_set_sample_rate_callback (jclient, jack_sample_rate_cb, conn);
  jack_on_shutdown (jclient, jack_shutdown_cb, conn);

  /* all callbacks are set, activate the client */
  GST_INFO ("activate jack_client %p", jclient);
  if ((res = jack_activate (jclient)))
    goto could_not_activate;

  GST_DEBUG ("opened connection %p", conn);

  return conn;

  /* ERRORS */
could_not_open:
  {
    GST_DEBUG ("failed to open jack client, %d", *status);
    return NULL;
  }
could_not_activate:
  {
    GST_ERROR ("Could not activate client (%d)", res);
    *status = JackFailure;
    g_mutex_clear (&conn->lock);
    g_free (conn->id);
    g_free (conn->server);
    g_free (conn);
    return NULL;
  }
}
Beispiel #11
0
int
main (int argc, char **argv)
{
  GstBus *bus;
  GOptionContext *ctx;
  GIOChannel *io_stdin;
  GError *err = NULL;
  gboolean res;
  GOptionEntry options[] = {
    {NULL}
  };
  GThread *rthread;

  /* Clear application state */
  memset (state, 0, sizeof (*state));
  state->animate = TRUE;

  /* must initialise the threading system before using any other GLib funtion */
  if (!g_thread_supported ())
    g_thread_init (NULL);

  ctx = g_option_context_new ("[ADDITIONAL ARGUMENTS]");
  g_option_context_add_main_entries (ctx, options, NULL);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
    exit (1);
  }
  g_option_context_free (ctx);

  if (argc != 2) {
    g_print ("Usage: %s <URI> or <PIPELINE-DESCRIPTION>\n", argv[0]);
    exit (1);
  }

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* initialize inter thread comunnication */
  init_intercom (state);

  TRACE_VC_MEMORY ("state 0");

  if (!(rthread = g_thread_new ("render", (GThreadFunc) render_func, NULL))) {
    g_print ("Render thread create failed\n");
    exit (1);
  }

  /* Initialize player */
  if (gst_uri_is_valid (argv[1])) {
    res = init_playbin_player (state, argv[1]);
  } else {
    res = init_parse_launch_player (state, argv[1]);
  }

  if (!res)
    goto done;

  /* Create a GLib Main Loop and set it to run */
  state->main_loop = g_main_loop_new (NULL, FALSE);

  /* Add a keyboard watch so we get notified of keystrokes */
  io_stdin = g_io_channel_unix_new (fileno (stdin));
  g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, state);
  g_io_channel_unref (io_stdin);

  /* *INDENT-OFF* */
  g_print ("Available commands: \n"
      "  a - Toggle animation \n"
      "  p - Pause playback \n"
      "  r - Resume playback \n"
      "  l - Query position/duration\n"
      "  f - Seek 30 seconds forward \n"
      "  b - Seek 30 seconds backward \n"
      "  q - Quit \n");
  /* *INDENT-ON* */

  /* Connect the bus handlers */
  bus = gst_element_get_bus (state->pipeline);

  gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, state,
      NULL);

  gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH);
  gst_bus_enable_sync_message_emission (bus);

  g_signal_connect (G_OBJECT (bus), "message::error", (GCallback) error_cb,
      state);
  g_signal_connect (G_OBJECT (bus), "message::buffering",
      (GCallback) buffering_cb, state);
  g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback) eos_cb, state);
  g_signal_connect (G_OBJECT (bus), "message::qos", (GCallback) qos_cb, state);
  g_signal_connect (G_OBJECT (bus), "message::state-changed",
      (GCallback) state_changed_cb, state);
  gst_object_unref (bus);

  /* Make player start playing */
  gst_element_set_state (state->pipeline, GST_STATE_PLAYING);

  /* Start the mainloop */
  state->main_loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (state->main_loop);

done:
  /* Release pipeline */
  if (state->pipeline) {
    gst_element_set_state (state->pipeline, GST_STATE_NULL);
    if (state->vsink) {
      gst_object_unref (state->vsink);
      state->vsink = NULL;
    }

    gst_object_unref (state->pipeline);
  }

  /* Unref the mainloop */
  if (state->main_loop) {
    g_main_loop_unref (state->main_loop);
  }

  /* Stop rendering thread */
  state->running = FALSE;
  g_thread_join (rthread);

  terminate_intercom (state);

  TRACE_VC_MEMORY ("at exit");
  return 0;
}
static gboolean
gst_rtp_L16_depay_setcaps (GstRTPBaseDepayload * depayload, GstCaps * caps)
{
  GstStructure *structure;
  GstRtpL16Depay *rtpL16depay;
  gint clock_rate, payload;
  gint channels;
  GstCaps *srccaps;
  gboolean res;
  const gchar *channel_order;
  const GstRTPChannelOrder *order;
  GstAudioInfo *info;

  rtpL16depay = GST_RTP_L16_DEPAY (depayload);

  structure = gst_caps_get_structure (caps, 0);

  payload = 96;
  gst_structure_get_int (structure, "payload", &payload);
  switch (payload) {
    case GST_RTP_PAYLOAD_L16_STEREO:
      channels = 2;
      clock_rate = 44100;
      break;
    case GST_RTP_PAYLOAD_L16_MONO:
      channels = 1;
      clock_rate = 44100;
      break;
    default:
      /* no fixed mapping, we need clock-rate */
      channels = 0;
      clock_rate = 0;
      break;
  }

  /* caps can overwrite defaults */
  clock_rate =
      gst_rtp_L16_depay_parse_int (structure, "clock-rate", clock_rate);
  if (clock_rate == 0)
    goto no_clockrate;

  channels =
      gst_rtp_L16_depay_parse_int (structure, "encoding-params", channels);
  if (channels == 0) {
    channels = gst_rtp_L16_depay_parse_int (structure, "channels", channels);
    if (channels == 0) {
      /* channels defaults to 1 otherwise */
      channels = 1;
    }
  }

  depayload->clock_rate = clock_rate;

  info = &rtpL16depay->info;
  gst_audio_info_init (info);
  info->finfo = gst_audio_format_get_info (GST_AUDIO_FORMAT_S16BE);
  info->rate = clock_rate;
  info->channels = channels;
  info->bpf = (info->finfo->width / 8) * channels;

  /* add channel positions */
  channel_order = gst_structure_get_string (structure, "channel-order");

  order = gst_rtp_channels_get_by_order (channels, channel_order);
  rtpL16depay->order = order;
  if (order) {
    memcpy (info->position, order->pos,
        sizeof (GstAudioChannelPosition) * channels);
    gst_audio_channel_positions_to_valid_order (info->position, info->channels);
  } else {
    GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE,
        (NULL), ("Unknown channel order '%s' for %d channels",
            GST_STR_NULL (channel_order), channels));
    /* create default NONE layout */
    gst_rtp_channels_create_default (channels, info->position);
  }

  srccaps = gst_audio_info_to_caps (info);
  res = gst_pad_set_caps (depayload->srcpad, srccaps);
  gst_caps_unref (srccaps);

  return res;

  /* ERRORS */
no_clockrate:
  {
    GST_ERROR_OBJECT (depayload, "no clock-rate specified");
    return FALSE;
  }
}
static gboolean
gst_amc_audio_dec_set_format (GstAudioDecoder * decoder, GstCaps * caps)
{
  GstAmcAudioDec *self;
  GstStructure *s;
  GstAmcFormat *format;
  const gchar *mime;
  gboolean is_format_change = FALSE;
  gboolean needs_disable = FALSE;
  gchar *format_string;
  gint rate, channels;
  GError *err = NULL;

  self = GST_AMC_AUDIO_DEC (decoder);

  GST_DEBUG_OBJECT (self, "Setting new caps %" GST_PTR_FORMAT, caps);

  /* Check if the caps change is a real format change or if only irrelevant
   * parts of the caps have changed or nothing at all.
   */
  is_format_change |= (!self->input_caps
      || !gst_caps_is_equal (self->input_caps, caps));

  needs_disable = self->started;

  /* If the component is not started and a real format change happens
   * we have to restart the component. If no real format change
   * happened we can just exit here.
   */
  if (needs_disable && !is_format_change) {
    /* Framerate or something minor changed */
    self->input_caps_changed = TRUE;
    GST_DEBUG_OBJECT (self,
        "Already running and caps did not change the format");
    return TRUE;
  }

  if (needs_disable && is_format_change) {
    gst_amc_audio_dec_drain (self);
    GST_AUDIO_DECODER_STREAM_UNLOCK (self);
    gst_amc_audio_dec_stop (GST_AUDIO_DECODER (self));
    GST_AUDIO_DECODER_STREAM_LOCK (self);
    gst_amc_audio_dec_close (GST_AUDIO_DECODER (self));
    if (!gst_amc_audio_dec_open (GST_AUDIO_DECODER (self))) {
      GST_ERROR_OBJECT (self, "Failed to open codec again");
      return FALSE;
    }

    if (!gst_amc_audio_dec_start (GST_AUDIO_DECODER (self))) {
      GST_ERROR_OBJECT (self, "Failed to start codec again");
    }
  }
  /* srcpad task is not running at this point */

  mime = caps_to_mime (caps);
  if (!mime) {
    GST_ERROR_OBJECT (self, "Failed to convert caps to mime");
    return FALSE;
  }

  s = gst_caps_get_structure (caps, 0);
  if (!gst_structure_get_int (s, "rate", &rate) ||
      !gst_structure_get_int (s, "channels", &channels)) {
    GST_ERROR_OBJECT (self, "Failed to get rate/channels");
    return FALSE;
  }

  format = gst_amc_format_new_audio (mime, rate, channels, &err);
  if (!format) {
    GST_ELEMENT_ERROR_FROM_ERROR (self, err);
    return FALSE;
  }

  /* FIXME: These buffers needs to be valid until the codec is stopped again */
  g_list_foreach (self->codec_datas, (GFunc) gst_buffer_unref, NULL);
  g_list_free (self->codec_datas);
  self->codec_datas = NULL;
  if (gst_structure_has_field (s, "codec_data")) {
    const GValue *h = gst_structure_get_value (s, "codec_data");
    GstBuffer *codec_data = gst_value_get_buffer (h);
    GstMapInfo minfo;
    guint8 *data;

    gst_buffer_map (codec_data, &minfo, GST_MAP_READ);
    data = g_memdup (minfo.data, minfo.size);
    self->codec_datas = g_list_prepend (self->codec_datas, data);
    gst_amc_format_set_buffer (format, "csd-0", data, minfo.size, &err);
    if (err)
      GST_ELEMENT_WARNING_FROM_ERROR (self, err);
    gst_buffer_unmap (codec_data, &minfo);
  } else if (gst_structure_has_field (s, "streamheader")) {
    const GValue *sh = gst_structure_get_value (s, "streamheader");
    gint nsheaders = gst_value_array_get_size (sh);
    GstBuffer *buf;
    const GValue *h;
    gint i, j;
    gchar *fname;
    GstMapInfo minfo;
    guint8 *data;

    for (i = 0, j = 0; i < nsheaders; i++) {
      h = gst_value_array_get_value (sh, i);
      buf = gst_value_get_buffer (h);

      if (strcmp (mime, "audio/vorbis") == 0) {
        guint8 header_type;

        gst_buffer_extract (buf, 0, &header_type, 1);

        /* Only use the identification and setup packets */
        if (header_type != 0x01 && header_type != 0x05)
          continue;
      }

      fname = g_strdup_printf ("csd-%d", j);
      gst_buffer_map (buf, &minfo, GST_MAP_READ);
      data = g_memdup (minfo.data, minfo.size);
      self->codec_datas = g_list_prepend (self->codec_datas, data);
      gst_amc_format_set_buffer (format, fname, data, minfo.size, &err);
      if (err)
        GST_ELEMENT_WARNING_FROM_ERROR (self, err);
      gst_buffer_unmap (buf, &minfo);
      g_free (fname);
      j++;
    }
  }

  format_string = gst_amc_format_to_string (format, &err);
  if (err)
    GST_ELEMENT_WARNING_FROM_ERROR (self, err);
  GST_DEBUG_OBJECT (self, "Configuring codec with format: %s",
      GST_STR_NULL (format_string));
  g_free (format_string);

  if (!gst_amc_codec_configure (self->codec, format, 0, &err)) {
    GST_ERROR_OBJECT (self, "Failed to configure codec");
    GST_ELEMENT_ERROR_FROM_ERROR (self, err);
    return FALSE;
  }

  gst_amc_format_free (format);

  if (!gst_amc_codec_start (self->codec, &err)) {
    GST_ERROR_OBJECT (self, "Failed to start codec");
    GST_ELEMENT_ERROR_FROM_ERROR (self, err);
    return FALSE;
  }

  self->spf = -1;
  /* TODO: Implement for other codecs too */
  if (gst_structure_has_name (s, "audio/mpeg")) {
    gint mpegversion = -1;

    gst_structure_get_int (s, "mpegversion", &mpegversion);
    if (mpegversion == 1) {
      gint layer = -1, mpegaudioversion = -1;

      gst_structure_get_int (s, "layer", &layer);
      gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion);
      if (layer == 1)
        self->spf = 384;
      else if (layer == 2)
        self->spf = 1152;
      else if (layer == 3 && mpegaudioversion != -1)
        self->spf = (mpegaudioversion == 1 ? 1152 : 576);
    }
  }

  self->started = TRUE;
  self->input_caps_changed = TRUE;

  /* Start the srcpad loop again */
  self->flushing = FALSE;
  self->downstream_flow_ret = GST_FLOW_OK;
  gst_pad_start_task (GST_AUDIO_DECODER_SRC_PAD (self),
      (GstTaskFunction) gst_amc_audio_dec_loop, decoder, NULL);

  return TRUE;
}
Beispiel #14
0
static gboolean
do_toggle_element (GstGConfVideoSink * sink)
{
  GstPad *targetpad;
  gchar *new_gconf_str;
  GstState cur, next;

  new_gconf_str = gst_gconf_get_string (GST_GCONF_VIDEOSINK_KEY);
  if (new_gconf_str != NULL && sink->gconf_str != NULL &&
      (strlen (new_gconf_str) == 0 ||
          strcmp (sink->gconf_str, new_gconf_str) == 0)) {
    g_free (new_gconf_str);
    GST_DEBUG_OBJECT (sink, "GConf key was updated, but it didn't change");
    return TRUE;
  }

  /* Sometime, it would be lovely to allow sink changes even when
   * already running, but this involves sending an appropriate new-segment
   * and possibly prerolling etc */
  GST_OBJECT_LOCK (sink);
  cur = GST_STATE (sink);
  next = GST_STATE_PENDING (sink);
  GST_OBJECT_UNLOCK (sink);

  if (cur > GST_STATE_READY || next == GST_STATE_PAUSED) {
    GST_DEBUG_OBJECT (sink,
        "Auto-sink is already running. Ignoring GConf change");
    g_free (new_gconf_str);
    return TRUE;
  }

  GST_DEBUG_OBJECT (sink, "GConf key changed: '%s' to '%s'",
      GST_STR_NULL (sink->gconf_str), GST_STR_NULL (new_gconf_str));

  g_free (sink->gconf_str);
  sink->gconf_str = new_gconf_str;

  /* kill old element */
  if (sink->kid) {
    GST_DEBUG_OBJECT (sink, "Removing old kid");
    gst_element_set_state (sink->kid, GST_STATE_NULL);
    gst_bin_remove (GST_BIN (sink), sink->kid);
    sink->kid = NULL;
  }

  GST_DEBUG_OBJECT (sink, "Creating new kid");
  if (!(sink->kid = gst_gconf_get_default_video_sink ())) {
    GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
        ("Failed to render video sink from GConf"));
    return FALSE;
  }
  gst_element_set_state (sink->kid, GST_STATE (sink));
  gst_bin_add (GST_BIN (sink), sink->kid);

  /* re-attach ghostpad */
  GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
  targetpad = gst_element_get_static_pad (sink->kid, "sink");
  gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
  gst_object_unref (targetpad);
  GST_DEBUG_OBJECT (sink, "done changing gconf video sink");

  return TRUE;
}
GstMixerOptions *
gst_sunaudiomixer_options_new (GstSunAudioMixerCtrl * mixer, gint track_num)
{
    GstMixerOptions *opts;
    GstSunAudioMixerOptions *sun_opts;
    GstMixerTrack *track;
    const gchar *label;
    gint i;
    struct audio_info audioinfo;

    if ((mixer == NULL) || (mixer->mixer_fd == -1)) {
        g_warning ("mixer not initialized");
        return NULL;
    }

    if (track_num != GST_SUNAUDIO_TRACK_RECSRC) {
        g_warning ("invalid options track");
        return (NULL);
    }

    label = N_("Record Source");

    opts = g_object_new (GST_TYPE_SUNAUDIO_MIXER_OPTIONS,
                         "untranslated-label", label, NULL);
    sun_opts = GST_SUNAUDIO_MIXER_OPTIONS (opts);
    track = GST_MIXER_TRACK (opts);

    GST_DEBUG_OBJECT (opts, "New mixer options, track %d: %s",
                      track_num, GST_STR_NULL (label));

    /* save off names for the record sources */
    sun_opts->names[0] = g_quark_from_string (_("Microphone"));
    sun_opts->names[1] = g_quark_from_string (_("Line In"));
    sun_opts->names[2] = g_quark_from_string (_("Internal CD"));
    sun_opts->names[3] = g_quark_from_string (_("SPDIF In"));
    sun_opts->names[4] = g_quark_from_string (_("AUX 1 In"));
    sun_opts->names[5] = g_quark_from_string (_("AUX 2 In"));
    sun_opts->names[6] = g_quark_from_string (_("Codec Loopback"));
    sun_opts->names[7] = g_quark_from_string (_("SunVTS Loopback"));

    /* set basic information */
    track->label = g_strdup (_(label));
    track->num_channels = 0;
    track->min_volume = 0;
    track->max_volume = 0;
    track->flags =
        GST_MIXER_TRACK_INPUT | GST_MIXER_TRACK_WHITELIST |
        GST_MIXER_TRACK_NO_RECORD;

    if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
        g_warning ("Error getting audio device settings");
        g_object_unref (G_OBJECT (sun_opts));
        return NULL;
    }

    sun_opts->avail = audioinfo.record.avail_ports;
    sun_opts->track_num = track_num;

    for (i = 0; i < 8; i++) {
        if ((1 << i) & audioinfo.record.avail_ports) {
            const char *s = g_quark_to_string (sun_opts->names[i]);
            opts->values = g_list_append (opts->values, g_strdup (s));
            GST_DEBUG_OBJECT (opts, "option for track %d: %s",
                              track_num, GST_STR_NULL (s));
        }
    }

    return opts;
}
Beispiel #16
0
/* returns TRUE if there was an error or we caught a keyboard interrupt. */
static gboolean
event_loop (GstElement * pipeline, gboolean blocking, GstState target_state)
{
  GstBus *bus;
  GstMessage *message = NULL;
  gboolean res = FALSE;
  gboolean buffering = FALSE;

  bus = gst_element_get_bus (GST_ELEMENT (pipeline));

#ifndef DISABLE_FAULT_HANDLER
  g_timeout_add (50, (GSourceFunc) check_intr, pipeline);
#endif

  while (TRUE) {
    message = gst_bus_poll (bus, GST_MESSAGE_ANY, blocking ? -1 : 0);

    /* if the poll timed out, only when !blocking */
    if (message == NULL)
      goto exit;

    switch (GST_MESSAGE_TYPE (message)) {
      case GST_MESSAGE_NEW_CLOCK:
      {
        GstClock *clock;

        gst_message_parse_new_clock (message, &clock);

        g_print ("New clock: %s\n", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
        break;
      }
      case GST_MESSAGE_EOS:
        g_print ("Got EOS from element \"%s\".\n",
            GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
        goto exit;
      case GST_MESSAGE_TAG:
        if (tags) {
          GstTagList *tags;

          gst_message_parse_tag (message, &tags);
          g_print ("FOUND TAG      : found by element \"%s\".\n",
              GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))));
          gst_tag_list_foreach (tags, print_tag, NULL);
          gst_tag_list_free (tags);
        }
        break;
      case GST_MESSAGE_INFO:{
        GError *gerror;
        gchar *debug;
        gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));

        gst_message_parse_info (message, &gerror, &debug);
        if (debug) {
          g_print ("INFO:\n%s\n", debug);
        }
        g_error_free (gerror);
        g_free (debug);
        g_free (name);
        break;
      }
      case GST_MESSAGE_WARNING:{
        GError *gerror;
        gchar *debug;
        gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC (message));

        /* dump graph on warning */
        GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
            GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.warning");

        gst_message_parse_warning (message, &gerror, &debug);
        g_print ("WARNING: from element %s: %s\n", name, gerror->message);
        if (debug) {
          g_print ("Additional debug info:\n%s\n", debug);
        }
        g_error_free (gerror);
        g_free (debug);
        g_free (name);
        break;
      }
      case GST_MESSAGE_ERROR:{
        GError *gerror;
        gchar *debug;

        /* dump graph on error */
        GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
            GST_DEBUG_GRAPH_SHOW_ALL, "gst-launch.error");

        gst_message_parse_error (message, &gerror, &debug);
        gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
        g_error_free (gerror);
        g_free (debug);
        /* we have an error */
        res = TRUE;
        goto exit;
      }
      case GST_MESSAGE_STATE_CHANGED:{
        GstState old, newX, pending;

        gst_message_parse_state_changed (message, &old, &newX, &pending);

        /* we only care about pipeline state change messages */
        if (GST_MESSAGE_SRC (message) != GST_OBJECT_CAST (pipeline))
          break;

        /* dump graph for pipeline state changes */
        {
          gchar *dump_name = g_strdup_printf ("gst-launch.%s_%s",
              gst_element_state_get_name (old),
              gst_element_state_get_name (newX));
          GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline),
              GST_DEBUG_GRAPH_SHOW_ALL, dump_name);
          g_free (dump_name);
        }

        /* ignore when we are buffering since then we mess with the states
         * ourselves. */
        if (buffering) {
          fprintf (stderr,
              "Prerolled, waiting for buffering to finish...\n");
          break;
        }

        /* if we reached the final target state, exit */
        if (target_state == GST_STATE_PAUSED && newX == target_state)
          goto exit;

        /* else not an interesting message */
        break;
      }
      case GST_MESSAGE_BUFFERING:{
        gint percent;

        gst_message_parse_buffering (message, &percent);
        fprintf (stderr, "%s %d%%  \r", "buffering...", percent);

        /* no state management needed for live pipelines */
        if (is_live)
          break;

        if (percent == 100) {
          /* a 100% message means buffering is done */
          buffering = FALSE;
          /* if the desired state is playing, go back */
          if (target_state == GST_STATE_PLAYING) {
            fprintf (stderr,
                "Done buffering, setting pipeline to PLAYING ...\n");
            gst_element_set_state (pipeline, GST_STATE_PLAYING);
          } else
            goto exit;
        } else {
          /* buffering busy */
          if (buffering == FALSE && target_state == GST_STATE_PLAYING) {
            /* we were not buffering but PLAYING, PAUSE  the pipeline. */
            fprintf (stderr, "Buffering, setting pipeline to PAUSED ...\n");
            gst_element_set_state (pipeline, GST_STATE_PAUSED);
          }
          buffering = TRUE;
        }
        break;
      }
      case GST_MESSAGE_LATENCY:
      {
        fprintf (stderr, "Redistribute latency...\n");
        gst_bin_recalculate_latency (GST_BIN (pipeline));
        break;
      }
      case GST_MESSAGE_APPLICATION:{
        const GstStructure *s;

        s = gst_message_get_structure (message);

        if (gst_structure_has_name (s, "GstLaunchInterrupt")) {
          /* this application message is posted when we caught an interrupt and
           * we need to stop the pipeline. */
          fprintf (stderr, "Interrupt: Stopping pipeline ...\n");
          /* return TRUE when we caught an interrupt */
          res = TRUE;
          goto exit;
        }
      }
      default:
        /* just be quiet by default */
        break;
    }
    if (message)
      gst_message_unref (message);
  }
  g_assert_not_reached ();

exit:
  {
    if (message)
      gst_message_unref (message);
    gst_object_unref (bus);
    return res;
  }
}
static gboolean
gst_cd_paranoia_src_open (GstAudioCdSrc * audiocdsrc, const gchar * device)
{
  GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (audiocdsrc);
  gint i, cache_size;

  GST_DEBUG_OBJECT (src, "trying to open device %s (generic-device=%s) ...",
      device, GST_STR_NULL (src->generic_device));

  /* find the device */
  if (src->generic_device != NULL) {
    src->d = cdda_identify_scsi (src->generic_device, device, FALSE, NULL);
  } else {
    if (device != NULL) {
      src->d = cdda_identify (device, FALSE, NULL);
    } else {
      src->d = cdda_identify ("/dev/cdrom", FALSE, NULL);
    }
  }

  /* fail if the device couldn't be found */
  if (src->d == NULL)
    goto no_device;

  /* set verbosity mode */
  cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT);

  /* open the disc */
  if (cdda_open (src->d))
    goto open_failed;

  GST_INFO_OBJECT (src, "set read speed to %d", src->read_speed);
  cdda_speed_set (src->d, src->read_speed);

  for (i = 1; i < src->d->tracks + 1; i++) {
    GstAudioCdSrcTrack track = { 0, };

    track.num = i;
    track.is_audio = IS_AUDIO (src->d, i - 1);
    track.start = cdda_track_firstsector (src->d, i);
    track.end = cdda_track_lastsector (src->d, i);
    track.tags = NULL;

    gst_audio_cd_src_add_track (GST_AUDIO_CD_SRC (src), &track);
  }

  /* create the paranoia struct and set it up */
  src->p = paranoia_init (src->d);
  if (src->p == NULL)
    goto init_failed;

  paranoia_modeset (src->p, src->paranoia_mode);
  GST_INFO_OBJECT (src, "set paranoia mode to 0x%02x", src->paranoia_mode);

  if (src->search_overlap != -1) {
    paranoia_overlapset (src->p, src->search_overlap);
    GST_INFO_OBJECT (src, "search overlap set to %u", src->search_overlap);
  }

  cache_size = src->cache_size;
  if (cache_size == -1) {
    /* if paranoia mode is low (the default), assume we're doing playback */
    if (src->paranoia_mode <= PARANOIA_MODE_FRAGMENT)
      cache_size = 150;
    else
      cache_size = paranoia_cachemodel_size (src->p, -1);
  }
  paranoia_cachemodel_size (src->p, cache_size);
  GST_INFO_OBJECT (src, "set cachemodel size to %u", cache_size);

  src->next_sector = -1;

  return TRUE;

  /* ERRORS */
no_device:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("Could not open CD device for reading.")), ("cdda_identify failed"));
    return FALSE;
  }
open_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("Could not open CD device for reading.")), ("cdda_open failed"));
    cdda_close (src->d);
    src->d = NULL;
    return FALSE;
  }
init_failed:
  {
    GST_ELEMENT_ERROR (src, LIBRARY, INIT,
        ("failed to initialize paranoia"), ("failed to initialize paranoia"));
    return FALSE;
  }
}
Beispiel #18
0
int main (int argc, char *argv[])
{
        HTTPMgmt *httpmgmt;
        HTTPStreaming *httpstreaming;
        GMainLoop *loop;
        GOptionContext *ctx;
        GError *err = NULL;
        gboolean foreground;
        struct rlimit rlim;
        GDateTime *datetime;
        gchar exe_path[512], *date;

        ctx = g_option_context_new (NULL);
        g_option_context_add_main_entries (ctx, options, NULL);
        g_option_context_add_group (ctx, gst_init_get_option_group ());
        if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
                g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
                exit (1);
        }
        g_option_context_free (ctx);
        GST_DEBUG_CATEGORY_INIT (GSTREAMILL, "gstreamill", 0, "gstreamill log");

        if (version) {
                print_version_info ();
                exit (0);
        }

        /* stop gstreamill. */
        if (stop) {
                gchar *pid_str;
                gint pid;

                g_file_get_contents (PID_FILE, &pid_str, NULL, NULL);
                if (pid_str == NULL) {
                        g_print ("File %s not found, check if gstreamill is running.\n", PID_FILE);
                        exit (1);
                }
                pid = atoi (pid_str);
                g_free (pid_str);
                g_print ("stoping gstreamill with pid %d ...\n", pid);
                kill (pid, SIGTERM);
                exit (0);
        }

        /* readlink exe path before setuid, on CentOS, readlink exe path after setgid/setuid failure on permission denied */
        memset (exe_path, '\0', sizeof (exe_path));
        if (readlink ("/proc/self/exe", exe_path, sizeof (exe_path)) == -1) {
                g_print ("Read /proc/self/exe error: %s", g_strerror (errno));
                exit (2);
        }

        if (prepare_gstreamill_run_dir () != 0) {
                g_print ("Can't create gstreamill run directory\n");
                exit (3);
        }
/*
        if (set_user_and_group () != 0) {
                g_print ("set user and group failure\n");
                exit (4);
        }
*/
        if (job_file != NULL) {
                /* gstreamill command with job, run in foreground */
                foreground = TRUE;

        } else {
                /* gstreamill command without job, run in background */
                foreground = FALSE;
        }

        if (gst_debug_get_default_threshold () < GST_LEVEL_WARNING) {
                gst_debug_set_default_threshold (GST_LEVEL_WARNING);
        }

        /* initialize ts segment static plugin */
        if (!gst_plugin_register_static (GST_VERSION_MAJOR,
                                         GST_VERSION_MINOR,
                                         "tssegment",
                                         "ts segment plugin",
                                         ts_segment_plugin_init,
                                         "0.1.0",
                                         "GPL",
                                         "GStreamer",
                                         "GStreamer",
                                         "http://gstreamer.net/")) {
                GST_ERROR ("registe tssegment error");
                exit (17);
        }

        /* subprocess, create_job_process */
        if (shm_name != NULL) {
                gint fd;
                gchar *job_desc, *p;
                Job *job;
                gchar *log_path, *name;
                gint ret;

                /* set subprocess maximum of core file */
                rlim.rlim_cur = 0;
                rlim.rlim_max = 0;
                if (setrlimit (RLIMIT_CORE, &rlim) == -1) {
                        GST_ERROR ("setrlimit error: %s", g_strerror (errno));
                }

                /* read job description from share memory */
                job_desc = NULL;
                fd = shm_open (shm_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
                if (ftruncate (fd, job_length) == -1) {
                        exit (5);
                }
                p = mmap (NULL, job_length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
                job_desc = g_strdup (p);

                if ((job_desc != NULL) && (!jobdesc_is_valid (job_desc))) {
                        exit (6);
                }

                /* initialize log */
                name = (gchar *)jobdesc_get_name (job_desc);
                if (!jobdesc_is_live (job_desc)) {
                        gchar *p;

                        p = jobdesc_get_log_path (job_desc);
                        log_path = g_build_filename (p, "gstreamill.log", NULL);
                        g_free (p);

                } else {
                        log_path = g_build_filename (log_dir, name, "gstreamill.log", NULL);
                }
                ret = init_log (log_path);
                g_free (log_path);
                if (ret != 0) {
                        exit (7);
                }

                /* launch a job. */
                datetime = g_date_time_new_now_local ();
                date = g_date_time_format (datetime, "%b %d %H:%M:%S");
                fprintf (_log->log_hd, "\n*** %s : job %s starting ***\n\n", date, name);
                g_date_time_unref (datetime);
                g_free (date);
                job = job_new ("name", name, "job", job_desc, NULL);
                job->is_live = jobdesc_is_live (job_desc);
                job->eos = FALSE;
                loop = g_main_loop_new (NULL, FALSE);

                GST_INFO ("Initializing job ...");
                if (job_initialize (job, TRUE) != 0) {
                        GST_ERROR ("initialize job failure, exit");
                        exit (8);
                }
                GST_INFO ("Initializing job done");

                GST_INFO ("Initializing job's encoders output ...");
                if (job_encoders_output_initialize (job) != 0) {
                        GST_ERROR ("initialize job encoders' output failure, exit");
                        exit (8);
                }
                GST_INFO ("Initializing job's encoders output done");

                GST_INFO ("Starting job ...");
                if (job_start (job) != 0) {
                        GST_ERROR ("start livejob failure, exit");
                        exit (9);
                }
                datetime = g_date_time_new_now_local ();
                date = g_date_time_format (datetime, "%b %d %H:%M:%S");
                fprintf (_log->log_hd, "\n*** %s : job %s started ***\n\n", date, name);
                g_date_time_unref (datetime);
                g_free (date);
                g_free (name);
                g_free (job_desc);

                signal (SIGPIPE, SIG_IGN);
                signal (SIGUSR1, sighandler);
                signal (SIGTERM, stop_job);

                g_main_loop_run (loop);

        } else {
                /* set parent process maximum of core file */
                rlim.rlim_cur = RLIM_INFINITY;
                rlim.rlim_max = RLIM_INFINITY;
                if (setrlimit (RLIMIT_CORE, &rlim) == -1) {
                        GST_ERROR ("setrlimit error: %s", g_strerror (errno));
                }
        }

        /* run in background? */
        if (!foreground) {
                gchar *path;
                gint ret;

                /* pid file exist? */
                if (g_file_test (PID_FILE, G_FILE_TEST_EXISTS)) {
                        g_print ("file %s found, gstreamill already running !!!\n", PID_FILE);
                        exit (10);
                }

                /* media directory */
                path = g_strdup_printf ("%s/dvr", MEDIA_LOCATION);
                if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
                        g_printf ("Create DVR directory: %s", path);
                        if (g_mkdir_with_parents (path, 0755) != 0) {
                                g_printf ("Create DVR directory failure: %s", path);
                        }
                }
                g_free (path);
                path = g_strdup_printf ("%s/transcode/in", MEDIA_LOCATION);
                if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
                        g_printf ("Create transcode directory: %s", path);
                        if (g_mkdir_with_parents (path, 0755) != 0) {
                                g_printf ("Create transcode directory failure: %s", path);
                        }
                }
                g_free (path);
                path = g_strdup_printf ("%s/transcode/out", MEDIA_LOCATION);
                if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
                        g_printf ("Create transcode directory: %s", path);
                        if (g_mkdir_with_parents (path, 0755) != 0) {
                                g_printf ("Create transcode directory failure: %s", path);
                        }
                }
                g_free (path);

                /* log to file */
                path = g_build_filename (log_dir, "gstreamill.log", NULL);
                ret = init_log (path);
                g_free (path);
                if (ret != 0) {
                        g_print ("Init log error, ret %d.\n", ret);
                        exit (11);
                }

                /* daemonize */
                if (daemon (0, 0) != 0) {
                        fprintf (_log->log_hd, "Failed to daemonize");
                        remove_pid_file ();
                        exit (1);
                }

                /* create pid file */
                if (create_pid_file () != 0) {
                        exit (1);
                }

                /* customize signal */
                signal (SIGUSR1, sighandler);
                signal (SIGTERM, stop_gstreamill);

                datetime = g_date_time_new_now_local ();
                date = g_date_time_format (datetime, "%b %d %H:%M:%S");
                fprintf (_log->log_hd, "\n*** %s : gstreamill started ***\n\n", date);
                g_free (date);
                g_date_time_unref (datetime);
        }

        /* ignore SIGPIPE */
        signal (SIGPIPE, SIG_IGN);

        loop = g_main_loop_new (NULL, FALSE);

        /* gstreamill */
        gstreamill = gstreamill_new ("daemon", !foreground, "log_dir", log_dir, "exe_path", exe_path, NULL);
        if (gstreamill_start (gstreamill) != 0) {
                GST_ERROR ("start gstreamill error, exit.");
                remove_pid_file ();
                exit (12);
        }

        /* httpstreaming, pull */
        httpstreaming = httpstreaming_new ("gstreamill", gstreamill, "address", http_streaming, NULL);
        if (httpstreaming_start (httpstreaming, 10) != 0) {
                GST_ERROR ("start httpstreaming error, exit.");
                remove_pid_file ();
                exit (13);
        }

        if (!foreground) {
                /* run in background, management via http */
                httpmgmt = httpmgmt_new ("gstreamill", gstreamill, "address", http_mgmt, NULL);
                if (httpmgmt_start (httpmgmt) != 0) {
                        GST_ERROR ("start http mangment error, exit.");
                        remove_pid_file ();
                        exit (14);
                }

        } else {
                /* run in foreground, start job */
                gchar *job, *p, *result;
                JSON_Value *val;
                JSON_Object *obj;

                /* ctrl-c, stop gstreamill */
                signal (SIGINT, stop_gstreamill);

                /* ctrl-\, stop gstreamill */
                signal (SIGQUIT, stop_gstreamill);

                if (!g_file_get_contents (job_file, &job, NULL, NULL)) {
                        GST_ERROR ("Read job file %s error.", job_file);
                        exit (15);
                }
                p = gstreamill_job_start (gstreamill, job);
                val = json_parse_string (p);
                obj = json_value_get_object (val);
                result = (gchar *)json_object_get_string (obj, "result");
                GST_INFO ("start job result: %s.", result);
                if (g_strcmp0 (result, "success") != 0) {
                        exit (16);
                }
                json_value_free (val);
                g_free (p);
        }

        g_main_loop_run (loop);

        return 0;
}
int
main (int argc, char **argv)
{
  GPtrArray *files;
  gchar **args = NULL;
  guint num, i;
  GError *err = NULL;
  GOptionContext *ctx;
  GOptionEntry options[] = {
    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL},
    {NULL}
  };
  GTimer *timer;

  if (!g_thread_supported ())
    g_thread_init (NULL);

  ctx = g_option_context_new ("FILES OR DIRECTORIES WITH AUDIO FILES");
  g_option_context_add_main_entries (ctx, options, NULL);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
    exit (1);
  }
  g_option_context_free (ctx);

  if (args == NULL || *args == NULL) {
    g_print ("Please provide one or more directories with audio files\n\n");
    return 1;
  }

  files = g_ptr_array_new ();

  num = g_strv_length (args);
  for (i = 0; i < num; ++i) {
    if (g_path_is_absolute (args[i])) {
      check_arg (files, args[i]);
    } else {
      g_warning ("Argument '%s' is not an absolute file path", args[i]);
    }
  }

  if (files->len == 0) {
    g_print ("Did not find any files\n\n");
    return 1;
  }

  timer = g_timer_new ();

  while (g_timer_elapsed (timer, NULL) < TEST_RUNTIME) {
    gint32 idx;

    idx = g_random_int_range (0, files->len);
    play_file ((const gchar *) g_ptr_array_index (files, idx));
  }

  g_strfreev (args);
  g_timer_destroy (timer);

  return 0;
}
static GstFlowReturn
gst_test_http_src_create (GstBaseSrc * basesrc, guint64 offset,
    guint length, GstBuffer ** retbuf)
{
  GstTestHTTPSrc *src = GST_TEST_HTTP_SRC (basesrc);
  guint bytes_read;
  GstFlowReturn ret = GST_FLOW_OK;
  guint blocksize;

  fail_unless (gst_test_http_src_callbacks != NULL);
  fail_unless (gst_test_http_src_callbacks->src_create != NULL);

  GST_OBJECT_LOCK (src);
  blocksize = basesrc->blocksize;
  GST_OBJECT_UNLOCK (src);

  g_mutex_lock (&src->mutex);
  GST_DEBUG ("gst_test_http_src_create feeding from %" G_GUINT64_FORMAT,
      src->position);
  if (src->uri == NULL) {
    GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
    g_mutex_unlock (&src->mutex);
    return GST_FLOW_ERROR;
  }
  if (src->input.status_code < 200 || src->input.status_code >= 300) {
    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s",
            "Generated requested error"), ("%s (%d), URL: %s, Redirect to: %s",
            "Generated requested error", src->input.status_code, src->uri,
            GST_STR_NULL (NULL)));
    g_mutex_unlock (&src->mutex);
    return GST_FLOW_ERROR;
  }
  if (src->http_method == METHOD_INVALID) {
    GST_ELEMENT_ERROR (src, RESOURCE, READ, ("%s",
            "Invalid HTTP method"), ("%s (%s), URL: %s",
            "Invalid HTTP method", src->http_method_name, src->uri));
    g_mutex_unlock (&src->mutex);
    return GST_FLOW_ERROR;
  } else if (src->http_method == METHOD_HEAD) {
    ret = GST_FLOW_EOS;
    goto http_events;
  }
  fail_unless_equals_uint64 (offset, src->position);
  bytes_read = MIN ((src->segment_end - src->position), blocksize);
  if (bytes_read == 0) {
    ret = GST_FLOW_EOS;
    goto http_events;
  }
  ret = gst_test_http_src_callbacks->src_create (src,
      offset, bytes_read, retbuf,
      src->input.context, gst_test_http_src_callback_user_data);
  if (ret != GST_FLOW_OK) {
    goto http_events;
  }

  GST_BUFFER_OFFSET (*retbuf) = src->position;
  GST_BUFFER_OFFSET_END (*retbuf) = src->position + bytes_read;

  src->position += bytes_read;
http_events:
  if (src->http_headers_event) {
    gst_pad_push_event (GST_BASE_SRC_PAD (src), src->http_headers_event);
    src->http_headers_event = NULL;
  }
  if (src->duration_changed) {
    src->duration_changed = FALSE;
    gst_element_post_message (GST_ELEMENT (src),
        gst_message_new_duration_changed (GST_OBJECT (src)));
  }

  g_mutex_unlock (&src->mutex);
  return ret;
}
Beispiel #21
0
gint
main (gint argc, gchar * argv[])
{
  GstStateChangeReturn ret;
  GstElement *pipeline;
  GstElement *filter, *sink;
  GstElement *sourcebin;
  GError *error = NULL;

  GtkWidget *window;
  GtkWidget *screen;
  GtkWidget *vbox, *combo;
  GtkWidget *hbox;
  GtkWidget *play, *pause, *null, *ready;

  gchar **source_desc_array = NULL;
  gchar *source_desc = NULL;

  GOptionContext *context;
  GOptionEntry options[] = {
    {"source-bin", 's', 0, G_OPTION_ARG_STRING_ARRAY, &source_desc_array,
        "Use a custom source bin description (gst-launch style)", NULL}
    ,
    {NULL}
  };

  context = g_option_context_new (NULL);
  g_option_context_add_main_entries (context, options, NULL);
  g_option_context_add_group (context, gst_init_get_option_group ());
  g_option_context_add_group (context, gtk_get_option_group (TRUE));
  if (!g_option_context_parse (context, &argc, &argv, &error)) {
    g_print ("Inizialization error: %s\n", GST_STR_NULL (error->message));
    return -1;
  }
  g_option_context_free (context);

  if (source_desc_array != NULL) {
    source_desc = g_strjoinv (" ", source_desc_array);
    g_strfreev (source_desc_array);
  }
  if (source_desc == NULL) {
    source_desc =
        g_strdup
        ("videotestsrc ! video/x-raw, width=352, height=288 ! identity");
  }

  sourcebin =
      gst_parse_bin_from_description (g_strdup (source_desc), TRUE, &error);
  g_free (source_desc);
  if (error) {
    g_print ("Error while parsing source bin description: %s\n",
        GST_STR_NULL (error->message));
    return -1;
  }

  g_set_application_name ("gst-gl-effects test app");

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_container_set_border_width (GTK_CONTAINER (window), 3);

  pipeline = gst_pipeline_new ("pipeline");

  filter = gst_element_factory_make ("gleffects", "flt");
  sink = gst_element_factory_make ("glimagesink", "glsink");

  gst_bin_add_many (GST_BIN (pipeline), sourcebin, filter, sink, NULL);

  if (!gst_element_link_many (sourcebin, filter, sink, NULL)) {
    g_print ("Failed to link one or more elements!\n");
    return -1;
  }

  g_signal_connect (G_OBJECT (window), "delete-event",
      G_CALLBACK (destroy_cb), pipeline);
  g_signal_connect (G_OBJECT (window), "destroy-event",
      G_CALLBACK (destroy_cb), pipeline);

  screen = gtk_drawing_area_new ();

  gtk_widget_set_size_request (screen, 640, 480);       // 500 x 376

  vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);

  gtk_box_pack_start (GTK_BOX (vbox), screen, TRUE, TRUE, 0);

  combo = gtk_combo_box_text_new ();

  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "identity");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "mirror");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "squeeze");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "stretch");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "fisheye");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "twirl");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "bulge");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "tunnel");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "square");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "heat");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "xpro");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "lumaxpro");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "sepia");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "xray");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "sin");
  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combo), "glow");

  g_signal_connect (G_OBJECT (combo), "changed", G_CALLBACK (apply_fx), filter);

  gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);

  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);

  play = gtk_button_new_with_label ("PLAY");

  g_signal_connect (G_OBJECT (play), "clicked", G_CALLBACK (play_cb), pipeline);

  pause = gtk_button_new_with_label ("PAUSE");

  g_signal_connect (G_OBJECT (pause), "clicked",
      G_CALLBACK (pause_cb), pipeline);

  null = gtk_button_new_with_label ("NULL");

  g_signal_connect (G_OBJECT (null), "clicked", G_CALLBACK (null_cb), pipeline);

  ready = gtk_button_new_with_label ("READY");

  g_signal_connect (G_OBJECT (ready), "clicked",
      G_CALLBACK (ready_cb), pipeline);

  gtk_box_pack_start (GTK_BOX (hbox), null, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), ready, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), play, TRUE, TRUE, 0);
  gtk_box_pack_start (GTK_BOX (hbox), pause, TRUE, TRUE, 0);

  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);

  gtk_container_add (GTK_CONTAINER (window), vbox);

  g_signal_connect (screen, "realize", G_CALLBACK (expose_cb), pipeline);

  ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_print ("Failed to start up pipeline!\n");
    return -1;
  }

  gtk_widget_show_all (GTK_WIDGET (window));

  gtk_main ();

  return 0;
}
Beispiel #22
0
/* open the file, necessary to go to RUNNING state */
static gboolean
gst_vcdsrc_start (GstBaseSrc * bsrc)
{
  int i;
  GstVCDSrc *src = GST_VCDSRC (bsrc);
  struct stat buf;

  /* open the device */
  src->fd = open (src->device, O_RDONLY);
  if (src->fd < 0)
    goto open_failed;

  if (fstat (src->fd, &buf) < 0)
    goto toc_failed;
  /* If it's not a block device, then we need to try and
   * parse the cue file if there is one
   * FIXME implement */
  if (!S_ISBLK (buf.st_mode)) {
    GST_DEBUG ("Reading CUE files not handled yet, cannot process %s",
        GST_STR_NULL (src->device));
    goto toc_failed;
  }

  /* read the table of contents */
  if (ioctl (src->fd, CDROMREADTOCHDR, &src->tochdr))
    goto toc_failed;

  /* allocate enough track structs for disk */
  src->numtracks = (src->tochdr.cdth_trk1 - src->tochdr.cdth_trk0) + 1;
  src->tracks = g_new (struct cdrom_tocentry, src->numtracks + 1);

  /* read each track entry */
  for (i = 0; i <= src->numtracks; i++) {
    src->tracks[i].cdte_track = i == src->numtracks ? CDROM_LEADOUT : i + 1;
    src->tracks[i].cdte_format = CDROM_MSF;
    if (ioctl (src->fd, CDROMREADTOCENTRY, &src->tracks[i]))
      goto toc_entry_failed;

    GST_DEBUG ("track %d begins at %d:%02d.%02d", i,
        src->tracks[i].cdte_addr.msf.minute,
        src->tracks[i].cdte_addr.msf.second,
        src->tracks[i].cdte_addr.msf.frame);
  }

  src->curoffset = 0;

  gst_vcdsrc_recalculate (src);

  return TRUE;

  /* ERRORS */
open_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
    return FALSE;
  }
toc_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
    close (src->fd);
    return FALSE;
  }
toc_entry_failed:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM);
    g_free (src->tracks);
    close (src->fd);
    return FALSE;
  }
}
Beispiel #23
0
GstElement *mmsGstLaunch(const char *pipeline_description) {
	GError *error = NULL;
	gint res = 0;

#ifdef ENABLE_NLS
	bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);
#endif

	if (!g_thread_supported ())
		g_thread_init (NULL);

	gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE);

#ifndef DISABLE_FAULT_HANDLER
	fault_setup ();

	sigint_setup ();
	play_signal_setup ();
#endif

	// parse the pipeline description
	pipeline = gst_parse_launch(pipeline_description, &error);

	if (!pipeline) {
		if (error) {
			fprintf (stderr, "ERROR: pipeline could not be constructed: %s.\n",
			GST_STR_NULL (error->message));
			g_error_free (error);
		} else {
			fprintf (stderr, "ERROR: pipeline could not be constructed.\n");
		}
		return NULL;
	} else if (error) {
		fprintf (stderr, "WARNING: erroneous pipeline: %s\n",
		GST_STR_NULL (error->message));
		g_error_free (error);
		return NULL;
	}


    GstState state;
    GstStateChangeReturn ret;

    /* If the top-level object is not a pipeline, place it in a pipeline. */
    if (!GST_IS_PIPELINE (pipeline)) {
      GstElement *real_pipeline = gst_element_factory_make ("pipeline", NULL);

      if (real_pipeline == NULL) {
        fprintf (stderr, "ERROR: the 'pipeline' element wasn't found.\n");
        return NULL;
      }
      gst_bin_add (GST_BIN (real_pipeline), pipeline);
      pipeline = real_pipeline;
    }
    fprintf (stderr, "Setting pipeline to PAUSED ...\n");
    ret = gst_element_set_state (pipeline, GST_STATE_PAUSED);

    switch (ret) {
    case GST_STATE_CHANGE_FAILURE:
		fprintf (stderr, "ERROR: Pipeline doesn't want to pause.\n");
		res = -1;
		event_loop (pipeline, FALSE, GST_STATE_VOID_PENDING);
		goto end;
    case GST_STATE_CHANGE_NO_PREROLL:
		fprintf (stderr, "Pipeline is live and does not need PREROLL ...\n");
		is_live = TRUE;
		break;
    case GST_STATE_CHANGE_ASYNC:
		fprintf (stderr, "Pipeline is PREROLLING ...\n");
		caught_error = event_loop (pipeline, TRUE, GST_STATE_PAUSED);
		if (caught_error) {
		  fprintf (stderr, "ERROR: pipeline doesn't want to preroll.\n");
		  goto end;
		}
		state = GST_STATE_PAUSED;
		// fallthrough
	case GST_STATE_CHANGE_SUCCESS:
		fprintf (stderr, "Pipeline is PREROLLED ...\n");
		break;
    }

    // pipe successfully created
    return pipeline;

end:
	mmsGstFree();

	return NULL;
}
Beispiel #24
0
static gboolean
wildmidi_open_config (void)
{
  gchar *path = g_strdup (g_getenv ("WILDMIDI_CFG"));
  gint ret;

  GST_DEBUG ("trying %s", GST_STR_NULL (path));
  if (path && (g_access (path, R_OK) == -1)) {
    g_free (path);
    path = NULL;
  }

  if (path == NULL) {
    path =
        g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".wildmidirc",
        NULL);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    path =
        g_build_path (G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S "etc",
        "wildmidi.cfg", NULL);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    path =
        g_build_path (G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S "etc", "wildmidi",
        "wildmidi.cfg", NULL);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    path = g_strdup (WILDMIDI_CFG);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    path =
        g_build_path (G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S "etc",
        "timidity.cfg", NULL);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    path =
        g_build_path (G_DIR_SEPARATOR_S, G_DIR_SEPARATOR_S "etc", "timidity",
        "timidity.cfg", NULL);
    GST_DEBUG ("trying %s", path);
    if (path && (g_access (path, R_OK) == -1)) {
      g_free (path);
      path = NULL;
    }
  }

  if (path == NULL) {
    /* I've created a symlink to get it playing
     * ln -s /usr/share/timidity/timidity.cfg /etc/wildmidi.cfg
     * we could make it use : WILDMIDI_CFG
     * but unfortunately it fails to create a proper filename if the config
     * has a redirect
     * http://sourceforge.net/tracker/index.php?func=detail&aid=1657358&group_id=42635&atid=433744
     */
    GST_WARNING ("no config file, can't initialise");
    return FALSE;
  }

  /* this also initializes a some filter and stuff and thus is slow */
  ret = WildMidi_Init (path, WILDMIDI_RATE, 0);
  g_free (path);

  return (ret == 0);
}
static GstFlowReturn
gst_rdt_manager_chain_rtcp (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  GstRDTManager *src;

#ifdef HAVE_RTCP
  gboolean valid;
  GstRTCPPacket packet;
  gboolean more;
#endif

  src = GST_RDT_MANAGER (parent);

  GST_DEBUG_OBJECT (src, "got rtcp packet");

#ifdef HAVE_RTCP
  valid = gst_rtcp_buffer_validate (buffer);
  if (!valid)
    goto bad_packet;

  /* position on first packet */
  more = gst_rtcp_buffer_get_first_packet (buffer, &packet);
  while (more) {
    switch (gst_rtcp_packet_get_type (&packet)) {
      case GST_RTCP_TYPE_SR:
      {
        guint32 ssrc, rtptime, packet_count, octet_count;
        guint64 ntptime;
        guint count, i;

        gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, &rtptime,
            &packet_count, &octet_count);

        GST_DEBUG_OBJECT (src,
            "got SR packet: SSRC %08x, NTP %" G_GUINT64_FORMAT
            ", RTP %u, PC %u, OC %u", ssrc, ntptime, rtptime, packet_count,
            octet_count);

        count = gst_rtcp_packet_get_rb_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc, exthighestseq, jitter, lsr, dlsr;
          guint8 fractionlost;
          gint32 packetslost;

          gst_rtcp_packet_get_rb (&packet, i, &ssrc, &fractionlost,
              &packetslost, &exthighestseq, &jitter, &lsr, &dlsr);

          GST_DEBUG_OBJECT (src, "got RB packet %d: SSRC %08x, FL %u"
              ", PL %u, HS %u, JITTER %u, LSR %u, DLSR %u", ssrc, fractionlost,
              packetslost, exthighestseq, jitter, lsr, dlsr);
        }
        break;
      }
      case GST_RTCP_TYPE_RR:
      {
        guint32 ssrc;
        guint count, i;

        ssrc = gst_rtcp_packet_rr_get_ssrc (&packet);

        GST_DEBUG_OBJECT (src, "got RR packet: SSRC %08x", ssrc);

        count = gst_rtcp_packet_get_rb_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc, exthighestseq, jitter, lsr, dlsr;
          guint8 fractionlost;
          gint32 packetslost;

          gst_rtcp_packet_get_rb (&packet, i, &ssrc, &fractionlost,
              &packetslost, &exthighestseq, &jitter, &lsr, &dlsr);

          GST_DEBUG_OBJECT (src, "got RB packet %d: SSRC %08x, FL %u"
              ", PL %u, HS %u, JITTER %u, LSR %u, DLSR %u", ssrc, fractionlost,
              packetslost, exthighestseq, jitter, lsr, dlsr);
        }
        break;
      }
      case GST_RTCP_TYPE_SDES:
      {
        guint chunks, i, j;
        gboolean more_chunks, more_items;

        chunks = gst_rtcp_packet_sdes_get_chunk_count (&packet);
        GST_DEBUG_OBJECT (src, "got SDES packet with %d chunks", chunks);

        more_chunks = gst_rtcp_packet_sdes_first_chunk (&packet);
        i = 0;
        while (more_chunks) {
          guint32 ssrc;

          ssrc = gst_rtcp_packet_sdes_get_ssrc (&packet);

          GST_DEBUG_OBJECT (src, "chunk %d, SSRC %08x", i, ssrc);

          more_items = gst_rtcp_packet_sdes_first_item (&packet);
          j = 0;
          while (more_items) {
            GstRTCPSDESType type;
            guint8 len;
            gchar *data;

            gst_rtcp_packet_sdes_get_item (&packet, &type, &len, &data);

            GST_DEBUG_OBJECT (src, "item %d, type %d, len %d, data %s", j,
                type, len, data);

            more_items = gst_rtcp_packet_sdes_next_item (&packet);
            j++;
          }
          more_chunks = gst_rtcp_packet_sdes_next_chunk (&packet);
          i++;
        }
        break;
      }
      case GST_RTCP_TYPE_BYE:
      {
        guint count, i;
        gchar *reason;

        reason = gst_rtcp_packet_bye_get_reason (&packet);
        GST_DEBUG_OBJECT (src, "got BYE packet (reason: %s)",
            GST_STR_NULL (reason));
        g_free (reason);

        count = gst_rtcp_packet_bye_get_ssrc_count (&packet);
        for (i = 0; i < count; i++) {
          guint32 ssrc;


          ssrc = gst_rtcp_packet_bye_get_nth_ssrc (&packet, i);

          GST_DEBUG_OBJECT (src, "SSRC: %08x", ssrc);
        }
        break;
      }
      case GST_RTCP_TYPE_APP:
        GST_DEBUG_OBJECT (src, "got APP packet");
        break;
      default:
        GST_WARNING_OBJECT (src, "got unknown RTCP packet");
        break;
    }
    more = gst_rtcp_packet_move_to_next (&packet);
  }
  gst_buffer_unref (buffer);
  return GST_FLOW_OK;

bad_packet:
  {
    GST_WARNING_OBJECT (src, "got invalid RTCP packet");
    return GST_FLOW_OK;
  }
#else
  return GST_FLOW_OK;
#endif
}
Beispiel #26
0
static void
test_taglib_id3mux_with_tags (GstTagList * tags, guint32 mask)
{
    GstMessage *msg;
    GstTagList *tags_read = NULL;
    GstElement *pipeline, *id3mux, *id3demux, *fakesrc, *identity, *fakesink;
    GstBus *bus;
    guint64 offset;
    GstBuffer *outbuf = NULL;
    GstBuffer *tagbuf = NULL;
    GstStateChangeReturn state_result;

    pipeline = gst_pipeline_new ("pipeline");
    g_assert (pipeline != NULL);

    fakesrc = gst_element_factory_make ("fakesrc", "fakesrc");
    g_assert (fakesrc != NULL);

    id3mux = gst_element_factory_make ("id3v2mux", "id3v2mux");
    g_assert (id3mux != NULL);

    identity = gst_element_factory_make ("identity", "identity");
    g_assert (identity != NULL);

    id3demux = gst_element_factory_make ("id3demux", "id3demux");
    g_assert (id3demux != NULL);

    fakesink = gst_element_factory_make ("fakesink", "fakesink");
    g_assert (fakesink != NULL);

    /* set up sink */
    outbuf = NULL;
    g_object_set (fakesink, "signal-handoffs", TRUE, NULL);
    g_signal_connect (fakesink, "handoff", G_CALLBACK (got_buffer), &outbuf);

    gst_bin_add (GST_BIN (pipeline), fakesrc);
    gst_bin_add (GST_BIN (pipeline), id3mux);
    gst_bin_add (GST_BIN (pipeline), identity);
    gst_bin_add (GST_BIN (pipeline), id3demux);
    gst_bin_add (GST_BIN (pipeline), fakesink);

    gst_tag_setter_merge_tags (GST_TAG_SETTER (id3mux), tags,
                               GST_TAG_MERGE_APPEND);

    gst_element_link_many (fakesrc, id3mux, identity, id3demux, fakesink, NULL);

    /* set up source */
    g_object_set (fakesrc, "signal-handoffs", TRUE, "can-activate-pull", FALSE,
                  "filltype", 2, "sizetype", 2, "sizemax", MP3_FRAME_SIZE,
                  "num-buffers", 16, NULL);

    offset = 0;
    g_signal_connect (fakesrc, "handoff", G_CALLBACK (fill_mp3_buffer), &offset);

    /* set up identity to catch tag buffer */
    g_signal_connect (identity, "handoff", G_CALLBACK (identity_cb), &tagbuf);

    GST_LOG ("setting and getting state ...");
    gst_element_set_state (pipeline, GST_STATE_PLAYING);
    state_result = gst_element_get_state (pipeline, NULL, NULL, -1);
    fail_unless (state_result == GST_STATE_CHANGE_SUCCESS,
                 "Unexpected result from get_state(). Expected success, got %d",
                 state_result);

    bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));

    GST_LOG ("Waiting for tag ...");
    msg =
        gst_bus_poll (bus, GST_MESSAGE_TAG | GST_MESSAGE_EOS | GST_MESSAGE_ERROR,
                      -1);
    if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        GError *err;
        gchar *dbg;

        gst_message_parse_error (msg, &err, &dbg);
        g_printerr ("ERROR from element %s: %s\n%s\n",
                    GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
        g_error_free (err);
        g_free (dbg);
    } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
        g_printerr ("EOS message, but were waiting for TAGS!\n");
    }
    fail_unless (msg->type == GST_MESSAGE_TAG);

    gst_message_parse_tag (msg, &tags_read);
    gst_message_unref (msg);

    GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags_read);
    test_taglib_id3mux_check_tags (tags_read, mask);
    gst_tag_list_unref (tags_read);

    fail_unless (tagbuf != NULL);
    test_taglib_id3mux_check_tag_buffer (tagbuf, mask);
    gst_buffer_unref (tagbuf);

    GST_LOG ("Waiting for EOS ...");
    msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1);
    if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        GError *err;
        gchar *dbg;

        gst_message_parse_error (msg, &err, &dbg);
        g_printerr ("ERROR from element %s: %s\n%s\n",
                    GST_OBJECT_NAME (msg->src), err->message, GST_STR_NULL (dbg));
        g_error_free (err);
        g_free (dbg);
    }
    fail_unless (msg->type == GST_MESSAGE_EOS);
    gst_message_unref (msg);

    gst_object_unref (bus);

    GST_LOG ("Got EOS, shutting down ...");
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);

    test_taglib_id3mux_check_output_buffer (outbuf);
    gst_buffer_unref (outbuf);

    GST_LOG ("Done");
}
static gboolean
gst_split_file_src_start (GstBaseSrc * basesrc)
{
  GstSplitFileSrc *src = GST_SPLIT_FILE_SRC (basesrc);
  GCancellable *cancel;
  gboolean ret = FALSE;
  guint64 offset;
  GError *err = NULL;
  gchar *basename = NULL;
  gchar *dirname = NULL;
  gchar **files;
  guint i;

  GST_OBJECT_LOCK (src);
  if (src->location != NULL && src->location[0] != '\0') {
    basename = g_path_get_basename (src->location);
    dirname = g_path_get_dirname (src->location);
  }
  GST_OBJECT_UNLOCK (src);

  files = gst_split_file_src_find_files (src, dirname, basename, &err);

  if (files == NULL || *files == NULL)
    goto no_files;

  src->num_parts = g_strv_length (files);
  src->parts = g_new0 (GstFilePart, src->num_parts);

  cancel = src->cancellable;

  offset = 0;
  for (i = 0; i < src->num_parts; ++i) {
    GFileInputStream *stream;
    GFileInfo *info;
    goffset size;
    GFile *file;

    file = g_file_new_for_path (files[i]);
    stream = g_file_read (file, cancel, &err);
    g_object_unref (file);

    if (err != NULL)
      goto open_read_error;

    info = g_file_input_stream_query_info (stream, "standard::*", NULL, &err);
    if (err != NULL) {
      g_object_unref (stream);
      goto query_info_error;
    }

    size = g_file_info_get_size (info);
    g_object_unref (info);

    src->parts[i].stream = stream;
    src->parts[i].path = g_strdup (files[i]);
    src->parts[i].start = offset;
    src->parts[i].stop = offset + size - 1;

    GST_DEBUG ("[%010" G_GUINT64_FORMAT "-%010" G_GUINT64_FORMAT "] %s",
        src->parts[i].start, src->parts[i].stop, src->parts[i].path);

    offset += size;
  }

  GST_INFO ("Successfully opened %u file parts for reading", src->num_parts);

  src->cur_part = 0;

  src->cancellable = g_cancellable_new ();

  ret = TRUE;

done:
  if (err != NULL)
    g_error_free (err);
  g_strfreev (files);
  g_free (basename);
  g_free (dirname);
  return ret;

/* ERRORS */
no_files:
  {
    if (err->code == G_IO_ERROR_CANCELLED)
      goto cancelled;

    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("%s", err->message),
        ("Failed to find files in '%s' for pattern '%s'",
            GST_STR_NULL (dirname), GST_STR_NULL (basename)));
    goto done;
  }
open_read_error:
  {
    if (err->code == G_IO_ERROR_CANCELLED)
      goto cancelled;

    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("%s", err->message),
        ("Failed to open file '%s' for reading", files[i]));
    goto done;
  }
query_info_error:
  {
    if (err->code == G_IO_ERROR_CANCELLED)
      goto cancelled;

    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, ("%s", err->message),
        ("Failed to query info for file '%s'", files[i]));
    goto done;
  }
cancelled:
  {
    GST_DEBUG_OBJECT (src, "I/O operation cancelled from another thread");
    goto done;
  }
}
Beispiel #28
0
/* First some utils, then the mixer implementation */
static gboolean
gst_alsa_mixer_open (GstAlsaMixer * mixer)
{
  gint err;
  snd_ctl_t *ctl;
  snd_ctl_card_info_t *card_info;

  g_return_val_if_fail (mixer->handle == NULL, FALSE);

  /* open and initialize the mixer device */
  err = snd_mixer_open (&mixer->handle, 0);
  if (err < 0 || mixer->handle == NULL)
    goto open_failed;

  if ((err = snd_mixer_attach (mixer->handle, mixer->device)) < 0) {
    GST_WARNING ("Cannot open mixer for sound device '%s': %s", mixer->device,
        snd_strerror (err));
    goto error;
  }

  if ((err = snd_mixer_selem_register (mixer->handle, NULL, NULL)) < 0) {
    GST_WARNING ("Cannot register mixer elements: %s", snd_strerror (err));
    goto error;
  }

  if ((err = snd_mixer_load (mixer->handle)) < 0) {
    GST_WARNING ("Cannot load mixer settings: %s", snd_strerror (err));
    goto error;
  }

  snd_mixer_set_callback_private (mixer->handle, mixer);
  snd_mixer_set_callback (mixer->handle, gst_alsa_mixer_handle_callback);

  /* now get the device name, any of this is not fatal */
  g_free (mixer->cardname);
  if ((err = snd_ctl_open (&ctl, mixer->device, 0)) < 0) {
    GST_WARNING ("Cannot open CTL: %s", snd_strerror (err));
    goto no_card_name;
  }

  snd_ctl_card_info_malloc (&card_info);
  if ((err = snd_ctl_card_info (ctl, card_info)) < 0) {
    GST_WARNING ("Cannot get card info: %s", snd_strerror (err));
    snd_ctl_close (ctl);
    goto no_card_name;
  }

  mixer->cardname = g_strdup (snd_ctl_card_info_get_name (card_info));
  GST_DEBUG ("Card name = %s", GST_STR_NULL (mixer->cardname));
  snd_ctl_card_info_free (card_info);
  snd_ctl_close (ctl);

no_card_name:
  if (mixer->cardname == NULL) {
    mixer->cardname = g_strdup ("Unknown");
    GST_DEBUG ("Cannot find card name");
  }

  GST_INFO ("Successfully opened mixer for device '%s'.", mixer->device);

  return TRUE;

  /* ERROR */
open_failed:
  {
    GST_WARNING ("Cannot open mixer: %s", snd_strerror (err));
    mixer->handle = NULL;
    return FALSE;
  }
error:
  {
    snd_mixer_close (mixer->handle);
    mixer->handle = NULL;
    return FALSE;
  }
}
int
main (int argc, char **argv)
{
  GstPlay *play;
  GPtrArray *playlist;
  gboolean verbose = FALSE;
  gboolean print_version = FALSE;
  gboolean interactive = TRUE;
  gboolean gapless = FALSE;
  gboolean shuffle = FALSE;
  gdouble volume = -1;
  gchar **filenames = NULL;
  gchar *audio_sink = NULL;
  gchar *video_sink = NULL;
  gchar **uris;
  gchar *flags = NULL;
  guint num, i;
  GError *err = NULL;
  GOptionContext *ctx;
  gchar *playlist_file = NULL;
  GOptionEntry options[] = {
    {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
        N_("Output status information and property notifications"), NULL},
    {"flags", 0, 0, G_OPTION_ARG_STRING, &flags,
          N_("Control playback behaviour setting playbin 'flags' property"),
        NULL},
    {"version", 0, 0, G_OPTION_ARG_NONE, &print_version,
        N_("Print version information and exit"), NULL},
    {"videosink", 0, 0, G_OPTION_ARG_STRING, &video_sink,
        N_("Video sink to use (default is autovideosink)"), NULL},
    {"audiosink", 0, 0, G_OPTION_ARG_STRING, &audio_sink,
        N_("Audio sink to use (default is autoaudiosink)"), NULL},
    {"gapless", 0, 0, G_OPTION_ARG_NONE, &gapless,
        N_("Enable gapless playback"), NULL},
    {"shuffle", 0, 0, G_OPTION_ARG_NONE, &shuffle,
        N_("Shuffle playlist"), NULL},
    {"no-interactive", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE,
          &interactive,
        N_("Disable interactive control via the keyboard"), NULL},
    {"volume", 0, 0, G_OPTION_ARG_DOUBLE, &volume,
        N_("Volume"), NULL},
    {"playlist", 0, 0, G_OPTION_ARG_FILENAME, &playlist_file,
        N_("Playlist file containing input media files"), NULL},
    {"quiet", 'q', 0, G_OPTION_ARG_NONE, &quiet,
        N_("Do not print any output (apart from errors)"), NULL},
    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
    {NULL}
  };

  setlocale (LC_ALL, "");

#ifdef ENABLE_NLS
  bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);
#endif

  g_set_prgname ("gst-play-" GST_API_VERSION);

  ctx = g_option_context_new ("FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ...");
  g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
    g_option_context_free (ctx);
    g_clear_error (&err);
    return 1;
  }
  g_option_context_free (ctx);

  GST_DEBUG_CATEGORY_INIT (play_debug, "play", 0, "gst-play");

  if (print_version) {
    gchar *version_str;

    version_str = gst_version_string ();
    g_print ("%s version %s\n", g_get_prgname (), PACKAGE_VERSION);
    g_print ("%s\n", version_str);
    g_print ("%s\n", GST_PACKAGE_ORIGIN);
    g_free (version_str);

    g_free (audio_sink);
    g_free (video_sink);
    g_free (playlist_file);

    return 0;
  }

  playlist = g_ptr_array_new ();

  if (playlist_file != NULL) {
    gchar *playlist_contents = NULL;
    gchar **lines = NULL;

    if (g_file_get_contents (playlist_file, &playlist_contents, NULL, &err)) {
      lines = g_strsplit (playlist_contents, "\n", 0);
      num = g_strv_length (lines);

      for (i = 0; i < num; i++) {
        if (lines[i][0] != '\0') {
          GST_LOG ("Playlist[%d]: %s", i + 1, lines[i]);
          add_to_playlist (playlist, lines[i]);
        }
      }
      g_strfreev (lines);
      g_free (playlist_contents);
    } else {
      g_printerr ("Could not read playlist: %s\n", err->message);
      g_clear_error (&err);
    }
    g_free (playlist_file);
    playlist_file = NULL;
  }

  if (playlist->len == 0 && (filenames == NULL || *filenames == NULL)) {
    g_printerr (_("Usage: %s FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ..."),
        "gst-play-" GST_API_VERSION);
    g_printerr ("\n\n"),
        g_printerr ("%s\n\n",
        _("You must provide at least one filename or URI to play."));
    /* No input provided. Free array */
    g_ptr_array_free (playlist, TRUE);

    g_free (audio_sink);
    g_free (video_sink);

    return 1;
  }

  /* fill playlist */
  if (filenames != NULL && *filenames != NULL) {
    num = g_strv_length (filenames);
    for (i = 0; i < num; ++i) {
      GST_LOG ("command line argument: %s", filenames[i]);
      add_to_playlist (playlist, filenames[i]);
    }
    g_strfreev (filenames);
  }

  num = playlist->len;
  g_ptr_array_add (playlist, NULL);

  uris = (gchar **) g_ptr_array_free (playlist, FALSE);

  if (shuffle)
    shuffle_uris (uris, num);

  /* prepare */
  play =
      play_new (uris, audio_sink, video_sink, gapless, volume, verbose, flags);

  if (play == NULL) {
    g_printerr
        ("Failed to create 'playbin' element. Check your GStreamer installation.\n");
    return EXIT_FAILURE;
  }

  if (interactive) {
    if (gst_play_kb_set_key_handler (keyboard_cb, play)) {
      g_print (_("Press 'k' to see a list of keyboard shortcuts.\n"));
      atexit (restore_terminal);
    } else {
      g_print ("Interactive keyboard handling in terminal not available.\n");
    }
  }

  /* play */
  do_play (play);

  /* clean up */
  play_free (play);

  g_free (audio_sink);
  g_free (video_sink);

  g_print ("\n");
  gst_deinit ();
  return 0;
}
Beispiel #30
0
int
main (int argc, char **argv)
{
  GstPlay *play;
  GPtrArray *playlist;
  gboolean print_version = FALSE;
  gboolean interactive = FALSE; /* FIXME: maybe enable by default? */
  gboolean shuffle = FALSE;
  gdouble volume = 1.0;
  gchar **filenames = NULL;
  gchar **uris;
  guint num, i;
  GError *err = NULL;
  GOptionContext *ctx;
  gchar *playlist_file = NULL;
  GOptionEntry options[] = {
    {"version", 0, 0, G_OPTION_ARG_NONE, &print_version,
        "Print version information and exit", NULL},
    {"shuffle", 0, 0, G_OPTION_ARG_NONE, &shuffle,
        "Shuffle playlist", NULL},
    {"interactive", 0, 0, G_OPTION_ARG_NONE, &interactive,
        "Interactive control via keyboard", NULL},
    {"volume", 0, 0, G_OPTION_ARG_DOUBLE, &volume,
        "Volume", NULL},
    {"playlist", 0, 0, G_OPTION_ARG_FILENAME, &playlist_file,
        "Playlist file containing input media files", NULL},
    {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
    {NULL}
  };

  g_set_prgname ("gst-play");

  ctx = g_option_context_new ("FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ...");
  g_option_context_add_main_entries (ctx, options, NULL);
  g_option_context_add_group (ctx, gst_init_get_option_group ());
  if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
    g_print ("Error initializing: %s\n", GST_STR_NULL (err->message));
    return 1;
  }
  g_option_context_free (ctx);

  GST_DEBUG_CATEGORY_INIT (play_debug, "play", 0, "gst-play");

  if (print_version) {
    gchar *version_str;

    version_str = gst_version_string ();
    g_print ("%s version %s\n", g_get_prgname (), "1.0");
    g_print ("%s\n", version_str);
    g_free (version_str);

    g_free (playlist_file);

    return 0;
  }

  playlist = g_ptr_array_new ();

  if (playlist_file != NULL) {
    gchar *playlist_contents = NULL;
    gchar **lines = NULL;

    if (g_file_get_contents (playlist_file, &playlist_contents, NULL, &err)) {
      lines = g_strsplit (playlist_contents, "\n", 0);
      num = g_strv_length (lines);

      for (i = 0; i < num; i++) {
        if (lines[i][0] != '\0') {
          GST_LOG ("Playlist[%d]: %s", i + 1, lines[i]);
          add_to_playlist (playlist, lines[i]);
        }
      }
      g_strfreev (lines);
      g_free (playlist_contents);
    } else {
      g_printerr ("Could not read playlist: %s\n", err->message);
      g_clear_error (&err);
    }
    g_free (playlist_file);
    playlist_file = NULL;
  }

  if (playlist->len == 0 && (filenames == NULL || *filenames == NULL)) {
    g_printerr ("Usage: %s FILE1|URI1 [FILE2|URI2] [FILE3|URI3] ...",
        "gst-play");
    g_printerr ("\n\n"),
        g_printerr ("%s\n\n",
        "You must provide at least one filename or URI to play.");
    /* No input provided. Free array */
    g_ptr_array_free (playlist, TRUE);

    return 1;
  }

  /* fill playlist */
  if (filenames != NULL && *filenames != NULL) {
    num = g_strv_length (filenames);
    for (i = 0; i < num; ++i) {
      GST_LOG ("command line argument: %s", filenames[i]);
      add_to_playlist (playlist, filenames[i]);
    }
    g_strfreev (filenames);
  }

  num = playlist->len;
  g_ptr_array_add (playlist, NULL);

  uris = (gchar **) g_ptr_array_free (playlist, FALSE);

  if (shuffle)
    shuffle_uris (uris, num);

  /* prepare */
  play = play_new (uris, volume);

  if (interactive) {
    if (gst_play_kb_set_key_handler (keyboard_cb, play)) {
      atexit (restore_terminal);
    } else {
      g_print ("Interactive keyboard handling in terminal not available.\n");
    }
  }

  /* play */
  do_play (play);

  /* clean up */
  play_free (play);

  g_print ("\n");
  return 0;
}