Example #1
0
static struct playlist_provider *
pls_open_stream(struct input_stream *is)
{
	GError *error = NULL;
	size_t nbytes;
	char buffer[1024];
	bool success;
	GKeyFile *keyfile;
	struct pls_playlist *playlist;
	GString *kf_data = g_string_new("");

	do {
		nbytes = input_stream_lock_read(is, buffer, sizeof(buffer),
						&error);
		if (nbytes == 0) {
			if (error != NULL) {
				g_string_free(kf_data, TRUE);
				g_warning("%s", error->message);
				g_error_free(error);
				return NULL;
			}

			break;
		}

		kf_data = g_string_append_len(kf_data, buffer,nbytes);
		/* Limit to 64k */
	} while(kf_data->len < 65536);

	if (kf_data->len == 0) {
		g_warning("KeyFile parser failed: No Data");
		g_string_free(kf_data, TRUE);
		return NULL;
	}

	keyfile = g_key_file_new();
	success = g_key_file_load_from_data(keyfile,
					    kf_data->str, kf_data->len,
					    G_KEY_FILE_NONE, &error);

	g_string_free(kf_data, TRUE);

	if (!success) {
		g_warning("KeyFile parser failed: %s", error->message);
		g_error_free(error);
		g_key_file_free(keyfile);
		return NULL;
	}

	playlist = g_new(struct pls_playlist, 1);
	playlist_provider_init(&playlist->base, &pls_playlist_plugin);
	playlist->songs = NULL;

	pls_parser(keyfile, playlist);

	g_key_file_free(keyfile);
	return &playlist->base;
}
static struct playlist_provider *
soundcloud_open_uri(const char *uri, GMutex *mutex, GCond *cond)
{
	struct soundcloud_playlist *playlist = NULL;

	char *s, *p;
	char *scheme, *arg, *rest;
	s = g_strdup(uri);
	scheme = s;
	for (p = s; *p; p++) {
		if (*p == ':' && *(p+1) == '/' && *(p+2) == '/') {
			*p = 0;
			p += 3;
			break;
		}
	}
	arg = p;
	for (; *p; p++) {
		if (*p == '/') {
			*p = 0;
			p++;
			break;
		}
	}
	rest = p;

	if (strcmp(scheme, "soundcloud") != 0) {
		g_warning("incompatible scheme for soundcloud plugin: %s", scheme);
		g_free(s);
		return NULL;
	}

	char *u = NULL;
	if (strcmp(arg, "track") == 0) {
		u = g_strconcat("http://api.soundcloud.com/tracks/",
			rest, ".json?client_id=", soundcloud_config.apikey, NULL);
	} else if (strcmp(arg, "playlist") == 0) {
		u = g_strconcat("http://api.soundcloud.com/playlists/",
			rest, ".json?client_id=", soundcloud_config.apikey, NULL);
	} else if (strcmp(arg, "url") == 0) {
		/* Translate to soundcloud resolver call. libcurl will automatically
		   follow the redirect to the right resource. */
		u = soundcloud_resolve(rest);
	}
	g_free(s);

	if (u == NULL) {
		g_warning("unknown soundcloud URI");
		return NULL;
	}

	yajl_handle hand;
	struct parse_data data;

	data.got_url = 0;
	data.songs = NULL;
	data.title = NULL;
	data.stream_url = NULL;
	hand = yajl_alloc(&parse_callbacks, NULL, NULL, (void *) &data);

	int ret = soundcloud_parse_json(u, hand, mutex, cond);

	g_free(u);
	yajl_free(hand);
	if (data.title != NULL)
		g_free(data.title);
	if (data.stream_url != NULL)
		g_free(data.stream_url);

	if (ret == -1)
		return NULL;

	playlist = g_new(struct soundcloud_playlist, 1);
	playlist_provider_init(&playlist->base, &soundcloud_playlist_plugin);
	playlist->songs = g_slist_reverse(data.songs);

	return &playlist->base;
}
static struct playlist_provider *
lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond)
{
	struct lastfm_playlist *playlist;
	GError *error = NULL;
	char *p, *q, *response, *session;

	/* handshake */

	p = g_strconcat("http://ws.audioscrobbler.com/radio/handshake.php?"
			"version=1.1.1&platform=linux&"
			"username="******"&"
			"passwordmd5=", lastfm_config.md5, "&"
			"debug=0&partner=", NULL);
	response = lastfm_get(p, mutex, cond);
	g_free(p);
	if (response == NULL)
		return NULL;

	/* extract session id from response */

	session = lastfm_find(response, "session");
	g_free(response);
	if (session == NULL) {
		g_warning("last.fm handshake failed");
		return NULL;
	}

	q = g_uri_escape_string(session, NULL, false);
	g_free(session);
	session = q;

	g_debug("session='%s'", session);

	/* "adjust" last.fm radio */

	if (strlen(uri) > 9) {
		char *escaped_uri;

		escaped_uri = g_uri_escape_string(uri, NULL, false);

		p = g_strconcat("http://ws.audioscrobbler.com/radio/adjust.php?"
				"session=", session, "&url=", escaped_uri, "&debug=0",
				NULL);
		g_free(escaped_uri);

		response = lastfm_get(p, mutex, cond);
		g_free(response);
		g_free(p);

		if (response == NULL) {
			g_free(session);
			return NULL;
		}
	}

	/* create the playlist object */

	playlist = g_new(struct lastfm_playlist, 1);
	playlist_provider_init(&playlist->base, &lastfm_playlist_plugin);

	/* open the last.fm playlist */

	p = g_strconcat("http://ws.audioscrobbler.com/radio/xspf.php?"
			"sk=", session, "&discovery=0&desktop=1.5.1.31879",
			NULL);
	g_free(session);

	playlist->is = input_stream_open(p, mutex, cond, &error);
	g_free(p);

	if (playlist->is == NULL) {
		if (error != NULL) {
			g_warning("Failed to load XSPF playlist: %s",
				  error->message);
			g_error_free(error);
		} else
			g_warning("Failed to load XSPF playlist");
		g_free(playlist);
		return NULL;
	}

	g_mutex_lock(mutex);

	input_stream_wait_ready(playlist->is);

	/* last.fm does not send a MIME type, we have to fake it here
	   :-( */
	g_free(playlist->is->mime);
	playlist->is->mime = g_strdup("application/xspf+xml");

	g_mutex_unlock(mutex);

	/* parse the XSPF playlist */

	playlist->xspf = playlist_list_open_stream(playlist->is, NULL);
	if (playlist->xspf == NULL) {
		input_stream_close(playlist->is);
		g_free(playlist);
		g_warning("Failed to parse XSPF playlist");
		return NULL;
	}

	return &playlist->base;
}