Beispiel #1
0
// ----------------------------------------------------------------------------
//
void TextUI::run()
{
	m_running = true;

	m_text_io.printf( "\n\nSpotify API Test Bench - type ? for command list\n\n" );

    m_player->connect();                   // Try to connect using stored credentials

	while ( m_running ) {
        // See if we need to login
        if ( !m_player->isLoggedIn() && !spotify_login( ) )
           break;

        CString label;
        PlayingInfo playing_info;

        if ( m_player->getPlayingTrack( &playing_info ) ) {
            label.Format( "Now %s: %s", "Playing", m_player->getTrackFullName( playing_info.track_link ) );
            label.AppendFormat( " | length %s remaining %s", track_time(playing_info.track_length), track_time(playing_info.time_remaining) );

            if ( m_player->isTrackPaused() )
                label.Append( " | PAUSED" );

		    m_text_io.printf( "\n%s\n", (LPCSTR)label );
        }

		m_text_io.clear();

		m_text_io.printf( "> ", (LPCSTR)label );

		CString cmd;
		int retcode = m_text_io.getString( cmd );
		m_text_io.printf( "\n" );

        if ( !m_player->isLoggedIn() )
            continue;
		if ( retcode != INPUT_SUCCESS )
			continue;
		m_text_io.tokenize( cmd );
		if ( !m_text_io.nextToken( cmd ) )
			continue;

		cmd.MakeLower();

		HandlerMap::iterator it = function_map.find( cmd );
		if ( it == function_map.end() ) {
			m_text_io.printf( "Unrecognized command '%s' - Type ? for list of commands\n", (LPCTSTR)cmd );
		}
		else if ( !m_running && (*it).second.m_running ) {
			m_text_io.printf( "UI must be running to use '%s'\n", (LPCTSTR)cmd );
		}
		else {
		    (this->*(*it).second.m_funcptr)();
		}
	}
}
Beispiel #2
0
static void
gst_spot_src_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstSpotSrc *spot;

  g_return_if_fail (GST_IS_SPOT_SRC (object));

  spot = GST_SPOT_SRC (object);

  switch (prop_id) {
    case ARG_USER:
      g_free (GST_SPOT_SRC_USER (spot));
      GST_SPOT_SRC_USER (spot) = g_value_dup_string (value);
      /* will work for everyone excepct Sverker Olofsson */
      if (g_strcmp0 (GST_SPOT_SRC_PASS (spot), DEFAULT_PASS)) {
	/* FIXME: Handle error */
	spotify_login (spot);
      }
      break;
    case ARG_PASS:
      g_free (GST_SPOT_SRC_PASS (spot));
      GST_SPOT_SRC_PASS (spot) = g_value_dup_string (value);
      /* will work for everyone excepct Sverker Olofsson */
      if (g_strcmp0 (GST_SPOT_SRC_USER (spot), DEFAULT_USER)) {
	/* FIXME: Handle error */
	spotify_login (spot);
      }
      break;
    case ARG_URI:
      //FIXME: how do handle error from this func?
      gst_spot_src_set_spotifyuri (spot, g_value_get_string (value));
      break;
    case ARG_BUFFER_TIME:
      GST_SPOT_SRC_BUFFER_TIME (spot) = (g_value_get_uint64 (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
Beispiel #3
0
int
main(int argc, char *argv[])
{
    spotify_t *spotify;
    int error;
    int ret;

    if (argc <= 2) {
        fprintf(stderr, "Usage: %s <username> <password>\n", argv[0]);
        return -1;
    }

#if defined(EVTHREAD_USE_PTHREADS_IMPLEMENTED)
    if (evthread_use_pthreads()) {
        return -2;
    }
#elif defined(EVTHREAD_USE_WINDOWS_THREADS_IMPLEMENTED)
    if (evthread_use_windows_threads()) {
        return -3;
    }
#else
# error "The libevent threading support not available"
#endif

    spotify = spotify_init(&error);
    if (!spotify) {
        fprintf(stderr, "Spotify failed to initialize\n");
        return -4;
    }
    spotify_login(spotify, argv[1], argv[2]);
    ret = spotify_run(spotify);
    if (ret) {
        fprintf(stderr, "Event loop returned %d\n", ret);
    }
    spotify_logout(spotify);
    spotify_destroy(spotify);

    return 0;
}
/* Thread: scan */
static void
process_file(char *file, time_t mtime, off_t size, int type, int flags)
{
  switch (file_type_get(file))
    {
      case FILE_REGULAR:
	filescanner_process_media(file, mtime, size, type, NULL);

	counter++;

	/* When in bulk mode, split transaction in pieces of 200 */
	if ((flags & F_SCAN_BULK) && (counter % 200 == 0))
	  {
	    DPRINTF(E_LOG, L_SCAN, "Scanned %d files...\n", counter);
	    db_transaction_end();
	    db_transaction_begin();
	  }
	break;

      case FILE_PLAYLIST:
      case FILE_ITUNES:
	if (flags & F_SCAN_BULK)
	  defer_playlist(file, mtime);
	else
	  process_playlist(file, mtime);
	break;

      case FILE_CTRL_REMOTE:
	remote_pairing_read_pin(file);
	break;

#ifdef LASTFM
      case FILE_CTRL_LASTFM:
	lastfm_login(file);
	break;
#endif

#ifdef HAVE_SPOTIFY_H
      case FILE_CTRL_SPOTIFY:
	spotify_login(file);
	break;
#endif

      case FILE_CTRL_INITSCAN:
	if (flags & F_SCAN_BULK)
	  break;

	DPRINTF(E_LOG, L_SCAN, "Startup rescan triggered, found init-rescan file: %s\n", file);

	inofd_event_unset(); // Clears all inotify watches
	db_watch_clear();

	inofd_event_set();
	bulk_scan(F_SCAN_BULK | F_SCAN_RESCAN);
	break;

      case FILE_CTRL_FULLSCAN:
	if (flags & F_SCAN_BULK)
	  break;

	DPRINTF(E_LOG, L_SCAN, "Full rescan triggered, found full-rescan file: %s\n", file);

	player_playback_stop();
	player_queue_clear();
	inofd_event_unset(); // Clears all inotify watches
	db_purge_all(); // Clears files, playlists, playlistitems, inotify and groups

	inofd_event_set();
	bulk_scan(F_SCAN_BULK);
	break;

      default:
	DPRINTF(E_WARN, L_SCAN, "Ignoring file: %s\n", file);
    }
}
/* Thread: scan */
static void *
filescanner(void *arg)
{
  int ret;
#if defined(__linux__)
  struct sched_param param;

  /* Lower the priority of the thread so forked-daapd may still respond
   * during file scan on low power devices. Param must be 0 for the SCHED_BATCH
   * policy.
   */
  memset(&param, 0, sizeof(struct sched_param));
  ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Warning: Could not set thread priority to SCHED_BATCH\n");
    }
#endif

  ret = db_perthread_init();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Error: DB init failed\n");

      pthread_exit(NULL);
    }

  ret = db_watch_clear();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Error: could not clear old watches from DB\n");

      pthread_exit(NULL);
    }

  ret = db_groups_clear();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Error: could not clear old groups from DB\n");

      pthread_exit(NULL);
    }

  /* Recompute all songartistids and songalbumids, in case the SQLite DB got transferred
   * to a different host; the hash is not portable.
   * It will also rebuild the groups we just cleared.
   */
  db_files_update_songartistid();
  db_files_update_songalbumid();

  if (cfg_getbool(cfg_getsec(cfg, "library"), "filescan_disable"))
    bulk_scan(F_SCAN_BULK | F_SCAN_FAST);
  else
    bulk_scan(F_SCAN_BULK);

  if (!scan_exit)
    {
#ifdef HAVE_SPOTIFY_H
      spotify_login(NULL);
#endif

      /* Enable inotify */
      event_add(&inoev, NULL);

      event_base_dispatch(evbase_scan);
    }

  if (!scan_exit)
    DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n");

  db_perthread_deinit();

  pthread_exit(NULL);
}
Beispiel #6
0
/* Thread: scan */
static void
process_file(char *file, time_t mtime, off_t size, int type, int flags, int dir_id)
{
  int is_bulkscan;
  int ret;

  is_bulkscan = (flags & F_SCAN_BULK);

  switch (file_type_get(file))
    {
      case FILE_REGULAR:
	filescanner_process_media(file, mtime, size, type, NULL, dir_id);

	cache_artwork_ping(file, mtime, !is_bulkscan);
	// TODO [artworkcache] If entry in artwork cache exists for no artwork available, delete the entry if media file has embedded artwork

	counter++;

	/* When in bulk mode, split transaction in pieces of 200 */
	if ((flags & F_SCAN_BULK) && (counter % 200 == 0))
	  {
	    DPRINTF(E_LOG, L_SCAN, "Scanned %d files...\n", counter);
	    db_transaction_end();
	    db_transaction_begin();
	  }
	break;

      case FILE_PLAYLIST:
      case FILE_ITUNES:
	if (flags & F_SCAN_BULK)
	  defer_playlist(file, mtime, dir_id);
	else
	  process_playlist(file, mtime, dir_id);
	break;

      case FILE_SMARTPL:
	DPRINTF(E_DBG, L_SCAN, "Smart playlist file: %s\n", file);
	scan_smartpl(file, mtime, dir_id);
	break;

      case FILE_ARTWORK:
	DPRINTF(E_DBG, L_SCAN, "Artwork file: %s\n", file);
	cache_artwork_ping(file, mtime, !is_bulkscan);

	// TODO [artworkcache] If entry in artwork cache exists for no artwork available for a album with files in the same directory, delete the entry

	break;

      case FILE_CTRL_REMOTE:
	remote_pairing_read_pin(file);
	break;

      case FILE_CTRL_LASTFM:
#ifdef LASTFM
	lastfm_login(file);
#else
	DPRINTF(E_LOG, L_SCAN, "Detected LastFM file, but this version was built without LastFM support\n");
#endif
	break;

      case FILE_CTRL_SPOTIFY:
#ifdef HAVE_SPOTIFY_H
	spotify_login(file);
#else
	DPRINTF(E_LOG, L_SCAN, "Detected Spotify file, but this version was built without Spotify support\n");
#endif
	break;

      case FILE_CTRL_INITSCAN:
	if (flags & F_SCAN_BULK)
	  break;

	DPRINTF(E_LOG, L_SCAN, "Startup rescan triggered, found init-rescan file: %s\n", file);

	filescanner_initscan(NULL, &ret);
	break;

      case FILE_CTRL_FULLSCAN:
	if (flags & F_SCAN_BULK)
	  break;

	DPRINTF(E_LOG, L_SCAN, "Full rescan triggered, found full-rescan file: %s\n", file);

	filescanner_fullrescan(NULL, &ret);
	break;

      default:
	DPRINTF(E_WARN, L_SCAN, "Ignoring file: %s\n", file);
    }
}
Beispiel #7
0
/* only used to trigger sp_session_process_events when needed,
 * looks like about once a second */
static void*
spotify_thread_func (void *data)
{
  int timeout = -1;
  GTimeVal t;
  GstSpotSrc *spot = (GstSpotSrc *) data;

  if (!spotify_create_session (spot)) {
    GST_ERROR_OBJECT (spot, "Create_session error");
    return FALSE;
  }

  while (spot->keep_spotify_thread) {
    sp_session_process_events (GST_SPOT_SRC_SPOTIFY_SESSION (spot), &timeout);
    g_get_current_time (&t);
    g_time_val_add (&t, timeout * 1000);
    g_cond_timed_wait (spot->process_events_cond, spot->process_events_mutex, &t);
    spot->spotify_thread_initiated = TRUE;
    while (spot->spot_works) {
      struct spot_work *spot_work;
      sp_error ret = SP_ERROR_INVALID_INDATA;
      spot_work = (struct spot_work *)spot->spot_works->data;
      g_mutex_lock (spot_work->spot_mutex);
      switch (spot_work->cmd) {
        case SPOT_CMD_START:
          GST_DEBUG_OBJECT (spot, "Uri = %s", GST_SPOT_SRC_URI_LOCATION (spot));
          if (!spotify_login (spot)) {
            /* error message from within function */
            break;
          }

          sp_link *link = sp_link_create_from_string (GST_SPOT_SRC_URI_LOCATION (spot));

          if (!link) {
            GST_ERROR_OBJECT (spot, "Incorrect track ID:%s", GST_SPOT_SRC_URI_LOCATION (spot));
            break;
          }

          GST_SPOT_SRC_CURRENT_TRACK (spot) = sp_link_as_track (link);

          if (!GST_SPOT_SRC_CURRENT_TRACK (spot)) {
            GST_ERROR_OBJECT (spot, "Could get track from uri=%s", GST_SPOT_SRC_URI_LOCATION (spot));
            break;
          }

#if 0
          /* FIXME: why does not this work? */
          if (!sp_track_is_available (GST_SPOT_SRC_CURRENT_TRACK (spot))) {
            /* this probably happens for tracks avaiable in other countries or
               something */
            GST_ERROR_OBJECT (spot, "Track is not available, uri=%s", GST_SPOT_SRC_URI_LOCATION (spot));
            break;
          }
#endif

          sp_track_add_ref (GST_SPOT_SRC_CURRENT_TRACK (spot));
          sp_link_add_ref (link);

          sp_session_process_events (GST_SPOT_SRC_SPOTIFY_SESSION (spot), &timeout);
          while (sp_track_is_loaded (GST_SPOT_SRC_CURRENT_TRACK (spot)) == 0) {
            sp_session_process_events (GST_SPOT_SRC_SPOTIFY_SESSION (spot), &timeout);
            usleep (10000);
          }

          GST_DEBUG_OBJECT (spot, "Now playing \"%s\"", sp_track_name (GST_SPOT_SRC_CURRENT_TRACK (spot)));

          ret = sp_session_player_load (GST_SPOT_SRC_SPOTIFY_SESSION (spot), GST_SPOT_SRC_CURRENT_TRACK (spot));
          if (ret != SP_ERROR_OK) {
            GST_ERROR_OBJECT (spot, "Failed to load track '%s' uri=%s", sp_track_name (GST_SPOT_SRC_CURRENT_TRACK (spot)),
                (GST_SPOT_SRC_URI_LOCATION (spot)));
            break;
          }

          sp_session_process_events (GST_SPOT_SRC_SPOTIFY_SESSION (spot), &timeout);
          ret = sp_session_player_play (GST_SPOT_SRC_SPOTIFY_SESSION (spot), TRUE);
          if (ret != SP_ERROR_OK) {
            GST_ERROR_OBJECT (spot, "Failed to play track '%s' uri=%s", sp_track_name (GST_SPOT_SRC_CURRENT_TRACK (spot)),
                (GST_SPOT_SRC_URI_LOCATION (spot)));
            break;
          }
          break;
        case SPOT_CMD_PROCESS:
          sp_session_process_events (GST_SPOT_SRC_SPOTIFY_SESSION (spot), &timeout);
          break;

        case SPOT_CMD_PLAY:
          ret = sp_session_player_play (GST_SPOT_SRC_SPOTIFY_SESSION (spot), TRUE);
          break;

        case SPOT_CMD_DURATION:
          if (GST_SPOT_SRC_CURRENT_TRACK (spot)) {
            ret = sp_track_duration (GST_SPOT_SRC_CURRENT_TRACK (spot));
          }
          break;

        case SPOT_CMD_STOP:
          if (GST_SPOT_SRC_CURRENT_TRACK (spot)) {
            ret = sp_session_player_play (GST_SPOT_SRC_SPOTIFY_SESSION (spot), FALSE);
            if (ret != SP_ERROR_OK)  {
              break;
            }
            ret = SP_ERROR_OK;
            sp_session_player_unload (GST_SPOT_SRC_SPOTIFY_SESSION (spot));
          }
          break;

        case SPOT_CMD_SEEK:
          if (GST_SPOT_SRC_CURRENT_TRACK (spot)) {
            ret = sp_session_player_seek (GST_SPOT_SRC_SPOTIFY_SESSION (spot), spot_work->opt);
          }
          break;
        default:
          g_assert_not_reached ();
          break;

      }

      /* print all errors caught and propagate to calling thread */
      if (ret != SP_ERROR_OK) {
            GST_ERROR_OBJECT (spot, "Failed with SPOT_CMD=%d, ret=%d, error=%s", spot_work->cmd, ret, sp_error_message (ret));
      }
      spot_work->ret = ret;

      spot->spot_works = g_list_remove (spot->spot_works, spot->spot_works->data);
      g_mutex_unlock (spot_work->spot_mutex);
      g_cond_broadcast (spot_work->spot_cond);
    }
  }

  return NULL;
}
Beispiel #8
0
/* Thread: scan */
static void *
filescanner(void *arg)
{
  int clear_queue_on_stop_disabled;
  int ret;
#ifdef __linux__
  struct sched_param param;

  /* Lower the priority of the thread so forked-daapd may still respond
   * during file scan on low power devices. Param must be 0 for the SCHED_BATCH
   * policy.
   */
  memset(&param, 0, sizeof(struct sched_param));
  ret = pthread_setschedparam(pthread_self(), SCHED_BATCH, &param);
  if (ret != 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Warning: Could not set thread priority to SCHED_BATCH\n");
    }
#endif

  ret = db_perthread_init();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Error: DB init failed\n");

      pthread_exit(NULL);
    }

  ret = db_watch_clear();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_SCAN, "Error: could not clear old watches from DB\n");

      pthread_exit(NULL);
    }

  // Only clear the queue if enabled (default) in config
  clear_queue_on_stop_disabled = cfg_getbool(cfg_getsec(cfg, "mpd"), "clear_queue_on_stop_disable");
  if (!clear_queue_on_stop_disabled)
    {
      ret = db_queue_clear();
      if (ret < 0)
        {
          DPRINTF(E_LOG, L_SCAN, "Error: could not clear queue from DB\n");

          pthread_exit(NULL);
        }
    }

  if (cfg_getbool(cfg_getsec(cfg, "library"), "filescan_disable"))
    bulk_scan(F_SCAN_BULK | F_SCAN_FAST);
  else
    bulk_scan(F_SCAN_BULK);

  if (!scan_exit)
    {
#ifdef HAVE_SPOTIFY_H
      spotify_login(NULL);
#endif

      /* Enable inotify */
      event_add(inoev, NULL);

      event_base_dispatch(evbase_scan);
    }

  if (!scan_exit)
    DPRINTF(E_FATAL, L_SCAN, "Scan event loop terminated ahead of time!\n");

  db_perthread_deinit();

  pthread_exit(NULL);
}