aboutsummaryrefslogtreecommitdiffstats
path: root/src/playlist/SoundCloudPlaylistPlugin.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/playlist/SoundCloudPlaylistPlugin.cxx157
1 files changed, 69 insertions, 88 deletions
diff --git a/src/playlist/SoundCloudPlaylistPlugin.cxx b/src/playlist/SoundCloudPlaylistPlugin.cxx
index f6797b14d..50a9cb214 100644
--- a/src/playlist/SoundCloudPlaylistPlugin.cxx
+++ b/src/playlist/SoundCloudPlaylistPlugin.cxx
@@ -24,7 +24,8 @@
#include "ConfigData.hxx"
#include "InputStream.hxx"
#include "Song.hxx"
-#include "tag/Tag.hxx"
+#include "tag/TagBuilder.hxx"
+#include "util/StringUtil.hxx"
#include "util/Error.hxx"
#include "util/Domain.hxx"
#include "Log.hxx"
@@ -45,7 +46,8 @@ static constexpr Domain soundcloud_domain("soundcloud");
static bool
soundcloud_init(const config_param &param)
{
- soundcloud_config.apikey = param.GetBlockValue("apikey", "");
+ // APIKEY for MPD application, registered under DarkFox' account.
+ soundcloud_config.apikey = param.GetBlockValue("apikey", "a25e51780f7f86af0afa91f241d091f8");
if (soundcloud_config.apikey.empty()) {
LogDebug(soundcloud_domain,
"disabling the soundcloud playlist plugin "
@@ -62,19 +64,20 @@ soundcloud_init(const config_param &param)
* @return Constructed URL. Must be freed with g_free.
*/
static char *
-soundcloud_resolve(const char* uri) {
+soundcloud_resolve(const char* uri)
+{
char *u, *ru;
- if (g_str_has_prefix(uri, "http://")) {
+ if (StringStartsWith(uri, "https://")) {
u = g_strdup(uri);
- } else if (g_str_has_prefix(uri, "soundcloud.com")) {
- u = g_strconcat("http://", uri, nullptr);
+ } else if (StringStartsWith(uri, "soundcloud.com")) {
+ u = g_strconcat("https://", uri, nullptr);
} else {
/* assume it's just a path on soundcloud.com */
- u = g_strconcat("http://soundcloud.com/", uri, nullptr);
+ u = g_strconcat("https://soundcloud.com/", uri, nullptr);
}
- ru = g_strconcat("http://api.soundcloud.com/resolve.json?url=",
+ ru = g_strconcat("https://api.soundcloud.com/resolve.json?url=",
u, "&client_id=",
soundcloud_config.apikey.c_str(), nullptr);
g_free(u);
@@ -105,15 +108,16 @@ struct parse_data {
char* title;
int got_url; /* nesting level of last stream_url */
- std::forward_list<SongPointer> songs;
+ std::forward_list<DetachedSong> songs;
};
-static int handle_integer(void *ctx,
- long
+static int
+handle_integer(void *ctx,
+ long
#ifndef HAVE_YAJL1
- long
+ long
#endif
- intval)
+ intval)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -128,26 +132,25 @@ static int handle_integer(void *ctx,
return 1;
}
-static int handle_string(void *ctx, const unsigned char* stringval,
+static int
+handle_string(void *ctx, const unsigned char* stringval,
#ifdef HAVE_YAJL1
- unsigned int
+ unsigned int
#else
- size_t
+ size_t
#endif
- stringlen)
+ stringlen)
{
struct parse_data *data = (struct parse_data *) ctx;
const char *s = (const char *) stringval;
switch (data->key) {
case Title:
- if (data->title != nullptr)
- g_free(data->title);
+ g_free(data->title);
data->title = g_strndup(s, stringlen);
break;
case Stream_URL:
- if (data->stream_url != nullptr)
- g_free(data->stream_url);
+ g_free(data->stream_url);
data->stream_url = g_strndup(s, stringlen);
data->got_url = 1;
break;
@@ -158,13 +161,14 @@ static int handle_string(void *ctx, const unsigned char* stringval,
return 1;
}
-static int handle_mapkey(void *ctx, const unsigned char* stringval,
+static int
+handle_mapkey(void *ctx, const unsigned char* stringval,
#ifdef HAVE_YAJL1
- unsigned int
+ unsigned int
#else
- size_t
+ size_t
#endif
- stringlen)
+ stringlen)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -181,7 +185,8 @@ static int handle_mapkey(void *ctx, const unsigned char* stringval,
return 1;
}
-static int handle_start_map(void *ctx)
+static int
+handle_start_map(void *ctx)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -191,7 +196,8 @@ static int handle_start_map(void *ctx)
return 1;
}
-static int handle_end_map(void *ctx)
+static int
+handle_end_map(void *ctx)
{
struct parse_data *data = (struct parse_data *) ctx;
@@ -206,21 +212,16 @@ static int handle_end_map(void *ctx)
/* got_url == 1, track finished, make it into a song */
data->got_url = 0;
- Song *s;
- char *u;
+ char *u = g_strconcat(data->stream_url, "?client_id=",
+ soundcloud_config.apikey.c_str(), nullptr);
- u = g_strconcat(data->stream_url, "?client_id=",
- soundcloud_config.apikey.c_str(), nullptr);
- s = Song::NewRemote(u);
- g_free(u);
-
- Tag *t = new Tag();
- t->time = data->duration / 1000;
+ TagBuilder tag;
+ tag.SetTime(data->duration / 1000);
if (data->title != nullptr)
- t->AddItem(TAG_NAME, data->title);
- s->tag = t;
+ tag.AddItem(TAG_NAME, data->title);
- data->songs.emplace_front(s);
+ data->songs.emplace_front(u, tag.Commit());
+ g_free(u);
return 1;
}
@@ -249,12 +250,9 @@ static int
soundcloud_parse_json(const char *url, yajl_handle hand,
Mutex &mutex, Cond &cond)
{
- char buffer[4096];
- unsigned char *ubuffer = (unsigned char *)buffer;
-
Error error;
- InputStream *input_stream = InputStream::Open(url, mutex, cond,
- error);
+ InputStream *input_stream = InputStream::OpenReady(url, mutex, cond,
+ error);
if (input_stream == nullptr) {
if (error.IsDefined())
LogError(error);
@@ -262,12 +260,13 @@ soundcloud_parse_json(const char *url, yajl_handle hand,
}
mutex.lock();
- input_stream->WaitReady();
yajl_status stat;
int done = 0;
while (!done) {
+ char buffer[4096];
+ unsigned char *ubuffer = (unsigned char *)buffer;
const size_t nbytes =
input_stream->Read(buffer, sizeof(buffer), error);
if (nbytes == 0) {
@@ -318,80 +317,62 @@ soundcloud_parse_json(const char *url, yajl_handle hand,
* soundcloud://playlist/<playlist-id>
* soundcloud://url/<url or path of soundcloud page>
*/
-
static SongEnumerator *
soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond)
{
- 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) {
- FormatWarning(soundcloud_domain,
- "incompatible scheme for soundcloud plugin: %s",
- scheme);
- g_free(s);
- return nullptr;
- }
+ assert(memcmp(uri, "soundcloud://", 13) == 0);
+ uri += 13;
char *u = nullptr;
- if (strcmp(arg, "track") == 0) {
- u = g_strconcat("http://api.soundcloud.com/tracks/",
+ if (memcmp(uri, "track/", 6) == 0) {
+ const char *rest = uri + 6;
+ u = g_strconcat("https://api.soundcloud.com/tracks/",
rest, ".json?client_id=",
soundcloud_config.apikey.c_str(), nullptr);
- } else if (strcmp(arg, "playlist") == 0) {
- u = g_strconcat("http://api.soundcloud.com/playlists/",
+ } else if (memcmp(uri, "playlist/", 9) == 0) {
+ const char *rest = uri + 9;
+ u = g_strconcat("https://api.soundcloud.com/playlists/",
rest, ".json?client_id=",
soundcloud_config.apikey.c_str(), nullptr);
- } else if (strcmp(arg, "url") == 0) {
+ } else if (memcmp(uri, "user/", 5) == 0) {
+ const char *rest = uri + 5;
+ u = g_strconcat("https://api.soundcloud.com/users/",
+ rest, "/tracks.json?client_id=",
+ soundcloud_config.apikey.c_str(), nullptr);
+ } else if (memcmp(uri, "search/", 7) == 0) {
+ const char *rest = uri + 7;
+ u = g_strconcat("https://api.soundcloud.com/tracks.json?q=",
+ rest, "&client_id=",
+ soundcloud_config.apikey.c_str(), nullptr);
+ } else if (memcmp(uri, "url/", 4) == 0) {
+ const char *rest = uri + 4;
/* Translate to soundcloud resolver call. libcurl will automatically
follow the redirect to the right resource. */
u = soundcloud_resolve(rest);
}
- g_free(s);
if (u == nullptr) {
LogWarning(soundcloud_domain, "unknown soundcloud URI");
return nullptr;
}
- yajl_handle hand;
struct parse_data data;
-
data.got_url = 0;
data.title = nullptr;
data.stream_url = nullptr;
#ifdef HAVE_YAJL1
- hand = yajl_alloc(&parse_callbacks, nullptr, nullptr, (void *) &data);
+ yajl_handle hand = yajl_alloc(&parse_callbacks, nullptr, nullptr,
+ &data);
#else
- hand = yajl_alloc(&parse_callbacks, nullptr, (void *) &data);
+ yajl_handle hand = yajl_alloc(&parse_callbacks, nullptr, &data);
#endif
int ret = soundcloud_parse_json(u, hand, mutex, cond);
g_free(u);
yajl_free(hand);
- if (data.title != nullptr)
- g_free(data.title);
- if (data.stream_url != nullptr)
- g_free(data.stream_url);
+ g_free(data.title);
+ g_free(data.stream_url);
if (ret == -1)
return nullptr;