예제 #1
0
static void
spotify_cb_play_token_lost (sp_session *session)
{
  GST_CAT_ERROR_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Play_token_lost callback");
  ugly_spot->play_token_lost = TRUE;
  g_signal_emit (ugly_spot, gst_spot_signals[SIGNAL_PLAY_TOKEN_LOST], 0);
}
예제 #2
0
static gboolean
gst_spot_src_get_size (GstBaseSrc * basesrc, guint64 * size)
{
  GstSpotSrc *spot;
  guint64 duration = 0;

  spot = GST_SPOT_SRC (basesrc);
  /* duration in ms */
  duration = run_spot_cmd (spot, SPOT_CMD_DURATION, 0);
  /* duration in ns */
  duration = 1000000 * duration;

  if (!duration) {
    GST_CAT_ERROR_OBJECT (gst_spot_src_debug_audio, spot, "No duration error");
    goto no_duration;
  }

  *size = (duration/1000000000) * 44100 * 4;
  GST_CAT_LOG_OBJECT (gst_spot_src_debug_audio, spot, "Duration=%" G_GUINT64_FORMAT " => size=%" G_GUINT64_FORMAT, duration, *size);

  return TRUE;

no_duration:
  return FALSE;
}
예제 #3
0
static void
gst_spot_src_init (GstSpotSrc * spot, GstSpotSrcClass * g_class)
{
  GError *err;
  spot->read_position = 0;

  /* its childish to use static global variables */
  ugly_spot = GST_SPOT_SRC (spot);

  GST_SPOT_SRC_URI (spot) = g_strdup (DEFAULT_URI);

  GST_SPOT_SRC_BUFFER_TIME (spot) = BUFFER_TIME_DEFAULT;

  GST_SPOT_SRC_ADAPTER_MUTEX (spot) = g_mutex_new ();
  GST_SPOT_SRC_ADAPTER_COND (spot) = g_cond_new ();
  GST_SPOT_SRC_ADAPTER (spot) = gst_adapter_new ();

  /* initiate format to default format */
  GST_SPOT_SRC_FORMAT (spot) = g_malloc0 (sizeof (sp_audioformat));
  GST_SPOT_SRC_FORMAT (spot)->sample_rate = SPOTIFY_DEFAULT_SAMPLE_RATE;
  GST_SPOT_SRC_FORMAT (spot)->channels = SPOTIFY_DEFAULT_NUMBER_CHANNELS;
  GST_SPOT_SRC_FORMAT (spot)->sample_type = SP_SAMPLETYPE_INT16_NATIVE_ENDIAN;

  /* initiate state varables */
  spot->spot_works = NULL;
  spot->play_token_lost = FALSE;
  spot->end_of_track = FALSE;
  spot->unlock_state = FALSE;

  /* initiate user settings */
  spot->user = g_strdup (DEFAULT_USER);
  spot->pass = g_strdup (DEFAULT_PASS);
  spot->uri = g_strdup (DEFAULT_URI);
  spot->logged_in = FALSE;

  /* intiate worker thread and its state variables */
  spot->keep_spotify_thread = TRUE;
  spot->spotify_thread_initiated = FALSE;
  spot->process_events_mutex = g_mutex_new ();
  spot->process_events_cond = g_cond_new ();
  spot->process_events_thread = g_thread_create ((GThreadFunc)spotify_thread_func, spot, TRUE, &err);

  if (spot->process_events_thread == NULL) {
     GST_CAT_ERROR_OBJECT (gst_spot_src_debug_threads, spot,"G_thread_create failed: %s!", err->message );
     g_error_free (err) ;
  }

  /* make sure spotify thread is up and running, before continuing. */
  GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, spot, "Broadcast process_events_cond");
  g_cond_broadcast (spot->process_events_cond);
  while (!spot->spotify_thread_initiated) {
    /* ugly but hey it yields right. */
    usleep (40);
    GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_threads, spot, "Broadcast process_events_cond, in loop");
    g_cond_broadcast (spot->process_events_cond);
  }
}
예제 #4
0
static void
spotify_cb_logged_in (sp_session *spotify_session, sp_error error)
{
  if (SP_ERROR_OK != error) {
    GST_CAT_ERROR_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Failed to log in to Spotify: %s", sp_error_message (error));
    return;
  }

  sp_user *me = sp_session_user (spotify_session);
  const char *my_name = (sp_user_is_loaded (me) ?
                         sp_user_display_name (me) :
                         sp_user_canonical_name (me));
  GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Logged_in callback, user=%s", my_name);
  /* set default bitrate to audiofility */
  sp_session_preferred_bitrate(spotify_session, SP_BITRATE_320k);
  GST_SPOT_SRC_LOGGED_IN (ugly_spot) = TRUE;
}
예제 #5
0
gint
main (gint argc, gchar * argv[])
{

  gst_init (&argc, &argv);

  GST_DEBUG_CATEGORY_INIT (cat_default, "GST_Check_default", 0,
      "default category for this test");
  GST_DEBUG_CATEGORY_INIT (cat2, "GST_Check_2", 0,
      "second category for this test");
#ifndef GST_DISABLE_GST_DEBUG
  g_assert (gst_debug_remove_log_function (gst_debug_log_default) == 1);
#endif
  gst_debug_add_log_function (check_message, NULL);

  count = 0;
  GST_ERROR ("This is an error.");
  ++count;
  GST_WARNING ("This is a warning.");
  ++count;
  GST_INFO ("This is an info message.");
  ++count;
  GST_DEBUG ("This is a debug message.");
  ++count;
  GST_LOG ("This is a log message.");
  ++count;
  GST_CAT_ERROR (cat2, "This is an error with category.");
  ++count;
  GST_CAT_WARNING (cat2, "This is a warning with category.");
  ++count;
  GST_CAT_INFO (cat2, "This is an info message with category.");
  ++count;
  GST_CAT_DEBUG (cat2, "This is a debug message with category.");
  ++count;
  GST_CAT_LOG (cat2, "This is a log message with category.");
  count = -1;
  pipeline = gst_element_factory_make ("pipeline", "testelement");
  count = 10;
  GST_ERROR_OBJECT (pipeline, "This is an error with object.");
  ++count;
  GST_WARNING_OBJECT (pipeline, "This is a warning with object.");
  ++count;
  GST_INFO_OBJECT (pipeline, "This is an info message with object.");
  ++count;
  GST_DEBUG_OBJECT (pipeline, "This is a debug message with object.");
  ++count;
  GST_LOG_OBJECT (pipeline, "This is a log message with object.");
  ++count;
  GST_CAT_ERROR_OBJECT (cat2, pipeline,
      "This is an error with category and object.");
  ++count;
  GST_CAT_WARNING_OBJECT (cat2, pipeline,
      "This is a warning with category and object.");
  ++count;
  GST_CAT_INFO_OBJECT (cat2, pipeline,
      "This is an info message with category and object.");
  ++count;
  GST_CAT_DEBUG_OBJECT (cat2, pipeline,
      "This is a debug message with category and object.");
  ++count;
  GST_CAT_LOG_OBJECT (cat2, pipeline,
      "This is a log message with category and object.");
  count = -1;

#ifndef GST_DISABLE_GST_DEBUG
  g_assert (gst_debug_remove_log_function (check_message) == 1);
#endif

  return 0;
}
예제 #6
0
static GstFlowReturn
gst_spot_src_create_read (GstSpotSrc * spot, guint64 offset, guint length, GstBuffer ** buffer)
{
  if (spot->unlock_state) {
    return GST_FLOW_WRONG_STATE;
  }

  if (G_UNLIKELY (spot->read_position != offset)) {
    sp_error error;
    /* implement spotify seek here */
    gint sample_rate = GST_SPOT_SRC_FORMAT (spot)->sample_rate;
    gint channels = GST_SPOT_SRC_FORMAT (spot)->channels;
    gint64 frames = offset / (channels * sizeof (int16_t));
    gint64 seek_usec = frames / ((float)sample_rate / 1000);

    GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_audio, spot,
        "Seek_usec = (%" G_GINT64_FORMAT ") = frames (%" G_GINT64_FORMAT ") /  sample_rate (%d/1000)",
        seek_usec, frames, sample_rate);
    GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_audio, spot,
        "Perform seek to %" G_GINT64_FORMAT " bytes and %" G_GINT64_FORMAT " usec",
        offset, seek_usec);

    error = run_spot_cmd (spot, SPOT_CMD_SEEK, seek_usec);
    g_mutex_lock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
    gst_adapter_clear (GST_SPOT_SRC_ADAPTER (spot));
    g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
    run_spot_cmd (spot, SPOT_CMD_PLAY, 0);

    if (error != SP_ERROR_OK) {
      GST_CAT_ERROR_OBJECT (gst_spot_src_debug_audio, spot, "Seek failed");
      goto create_seek_failed;
    }
    spot->read_position = offset;
  }

  /* see if we have bytes to write */
  GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_audio, spot, "Length=%u offset=%" G_GINT64_FORMAT " end=%" G_GINT64_FORMAT " read_position=%" G_GINT64_FORMAT,
                    length, offset, offset+length, spot->read_position);

  g_mutex_lock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
  while (1) {
    *buffer = gst_adapter_take_buffer (GST_SPOT_SRC_ADAPTER (spot), length);
    if (*buffer) {
      spot->read_position += length;
      GST_BUFFER_SIZE (*buffer) = length;
      GST_BUFFER_OFFSET (*buffer) = offset;
      GST_BUFFER_OFFSET_END (*buffer) = offset + length;
      g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
      return GST_FLOW_OK;
    }
    if (spot->end_of_track) {
      g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
      do_end_of_track (spot);
      GST_CAT_DEBUG_OBJECT (gst_spot_src_debug_audio, spot, "End of track");
      return GST_FLOW_WRONG_STATE;
    }
    //should be used in a tight conditional while
    g_cond_wait (GST_SPOT_SRC_ADAPTER_COND (spot), GST_SPOT_SRC_ADAPTER_MUTEX (spot));
    if (spot->unlock_state) {
      g_mutex_unlock (GST_SPOT_SRC_ADAPTER_MUTEX (spot));
      return GST_FLOW_WRONG_STATE;
    }
  }

  GST_CAT_ERROR_OBJECT (gst_spot_src_debug_audio, spot, "Create_read failed");

  create_seek_failed:
  return GST_FLOW_ERROR;
}
예제 #7
0
static void
spotify_cb_connection_error (sp_session *spotify_session, sp_error error)
{
  GST_CAT_ERROR_OBJECT (gst_spot_src_debug_cb, ugly_spot, "Connection_error callback %s",
      sp_error_message (error));
}