diff options
Diffstat (limited to 'src/playlist')
-rw-r--r-- | src/playlist/AsxPlaylistPlugin.cxx (renamed from src/playlist/asx_playlist_plugin.c) | 126 | ||||
-rw-r--r-- | src/playlist/AsxPlaylistPlugin.hxx (renamed from src/playlist/asx_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/CuePlaylistPlugin.cxx (renamed from src/playlist/cue_playlist_plugin.c) | 36 | ||||
-rw-r--r-- | src/playlist/CuePlaylistPlugin.hxx (renamed from src/playlist/cue_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/DespotifyPlaylistPlugin.cxx | 146 | ||||
-rw-r--r-- | src/playlist/DespotifyPlaylistPlugin.hxx (renamed from src/playlist/despotify_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/EmbeddedCuePlaylistPlugin.cxx (renamed from src/playlist/embcue_playlist_plugin.c) | 43 | ||||
-rw-r--r-- | src/playlist/EmbeddedCuePlaylistPlugin.hxx (renamed from src/playlist/embcue_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/ExtM3uPlaylistPlugin.cxx (renamed from src/playlist/extm3u_playlist_plugin.c) | 45 | ||||
-rw-r--r-- | src/playlist/ExtM3uPlaylistPlugin.hxx (renamed from src/playlist/extm3u_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/LastFMPlaylistPlugin.cxx (renamed from src/playlist/lastfm_playlist_plugin.c) | 43 | ||||
-rw-r--r-- | src/playlist/LastFMPlaylistPlugin.hxx (renamed from src/playlist/lastfm_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/M3uPlaylistPlugin.cxx (renamed from src/playlist/m3u_playlist_plugin.c) | 36 | ||||
-rw-r--r-- | src/playlist/M3uPlaylistPlugin.hxx (renamed from src/playlist/m3u_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/MemoryPlaylistProvider.cxx | 69 | ||||
-rw-r--r-- | src/playlist/MemoryPlaylistProvider.hxx | 39 | ||||
-rw-r--r-- | src/playlist/PlsPlaylistPlugin.cxx (renamed from src/playlist/pls_playlist_plugin.c) | 81 | ||||
-rw-r--r-- | src/playlist/PlsPlaylistPlugin.hxx (renamed from src/playlist/pls_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/RssPlaylistPlugin.cxx (renamed from src/playlist/rss_playlist_plugin.c) | 125 | ||||
-rw-r--r-- | src/playlist/RssPlaylistPlugin.hxx (renamed from src/playlist/rss_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/SoundCloudPlaylistPlugin.cxx (renamed from src/playlist/soundcloud_playlist_plugin.c) | 78 | ||||
-rw-r--r-- | src/playlist/SoundCloudPlaylistPlugin.hxx (renamed from src/playlist/soundcloud_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/XspfPlaylistPlugin.cxx (renamed from src/playlist/xspf_playlist_plugin.c) | 156 | ||||
-rw-r--r-- | src/playlist/XspfPlaylistPlugin.hxx (renamed from src/playlist/xspf_playlist_plugin.h) | 6 | ||||
-rw-r--r-- | src/playlist/despotify_playlist_plugin.c | 217 |
25 files changed, 588 insertions, 718 deletions
diff --git a/src/playlist/asx_playlist_plugin.c b/src/playlist/AsxPlaylistPlugin.cxx index 298687859..25319ca6b 100644 --- a/src/playlist/asx_playlist_plugin.c +++ b/src/playlist/AsxPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,8 @@ */ #include "config.h" -#include "playlist/asx_playlist_plugin.h" -#include "playlist_plugin.h" +#include "AsxPlaylistPlugin.hxx" +#include "MemoryPlaylistProvider.hxx" #include "input_stream.h" #include "song.h" #include "tag.h" @@ -35,12 +35,12 @@ /** * This is the state object for the GLib XML parser. */ -struct asx_parser { +struct AsxParser { /** * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list<SongPointer> songs; /** * The current position in the XML file. @@ -61,6 +61,10 @@ struct asx_parser { * element. */ struct song *song; + + AsxParser() + :state(ROOT) {} + }; static const gchar * @@ -81,19 +85,19 @@ asx_start_element(G_GNUC_UNUSED GMarkupParseContext *context, const gchar **attribute_values, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct asx_parser *parser = user_data; + AsxParser *parser = (AsxParser *)user_data; switch (parser->state) { - case ROOT: + case AsxParser::ROOT: if (g_ascii_strcasecmp(element_name, "entry") == 0) { - parser->state = ENTRY; + parser->state = AsxParser::ENTRY; parser->song = song_remote_new("asx:"); parser->tag = TAG_NUM_OF_ITEM_TYPES; } break; - case ENTRY: + case AsxParser::ENTRY: if (g_ascii_strcasecmp(element_name, "ref") == 0) { const gchar *href = get_attribute(attribute_names, attribute_values, @@ -130,21 +134,20 @@ asx_end_element(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *element_name, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct asx_parser *parser = user_data; + AsxParser *parser = (AsxParser *)user_data; switch (parser->state) { - case ROOT: + case AsxParser::ROOT: break; - case ENTRY: + case AsxParser::ENTRY: if (g_ascii_strcasecmp(element_name, "entry") == 0) { if (strcmp(parser->song->uri, "asx:") != 0) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); else song_free(parser->song); - parser->state = ROOT; + parser->state = AsxParser::ROOT; } else parser->tag = TAG_NUM_OF_ITEM_TYPES; @@ -157,13 +160,13 @@ asx_text(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct asx_parser *parser = user_data; + AsxParser *parser = (AsxParser *)user_data; switch (parser->state) { - case ROOT: + case AsxParser::ROOT: break; - case ENTRY: + case AsxParser::ENTRY: if (parser->tag != TAG_NUM_OF_ITEM_TYPES) { if (parser->song->tag == NULL) parser->song->tag = tag_new(); @@ -176,29 +179,20 @@ asx_text(G_GNUC_UNUSED GMarkupParseContext *context, } static const GMarkupParser asx_parser = { - .start_element = asx_start_element, - .end_element = asx_end_element, - .text = asx_text, + asx_start_element, + asx_end_element, + asx_text, + nullptr, + nullptr, }; static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = data; - - song_free(song); -} - -static void asx_parser_destroy(gpointer data) { - struct asx_parser *parser = data; + AsxParser *parser = (AsxParser *)data; - if (parser->state >= ENTRY) + if (parser->state >= AsxParser::ENTRY) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -206,20 +200,10 @@ asx_parser_destroy(gpointer data) * */ -struct asx_playlist { - struct playlist_provider base; - - GSList *songs; -}; - static struct playlist_provider * asx_open_stream(struct input_stream *is) { - struct asx_parser parser = { - .songs = NULL, - .state = ROOT, - }; - struct asx_playlist *playlist; + AsxParser parser; GMarkupParseContext *context; char buffer[1024]; size_t nbytes; @@ -264,41 +248,13 @@ asx_open_stream(struct input_stream *is) return NULL; } - /* create a #asx_playlist object from the parsed song list */ - - playlist = g_new(struct asx_playlist, 1); - playlist_provider_init(&playlist->base, &asx_playlist_plugin); - playlist->songs = g_slist_reverse(parser.songs); - parser.songs = NULL; + parser.songs.reverse(); + MemoryPlaylistProvider *playlist = + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); - return &playlist->base; -} - -static void -asx_close(struct playlist_provider *_playlist) -{ - struct asx_playlist *playlist = (struct asx_playlist *)_playlist; - - g_slist_foreach(playlist->songs, song_free_callback, NULL); - g_slist_free(playlist->songs); - g_free(playlist); -} - -static struct song * -asx_read(struct playlist_provider *_playlist) -{ - struct asx_playlist *playlist = (struct asx_playlist *)_playlist; - struct song *song; - - if (playlist->songs == NULL) - return NULL; - - song = playlist->songs->data; - playlist->songs = g_slist_remove(playlist->songs, song); - - return song; + return playlist; } static const char *const asx_suffixes[] = { @@ -312,12 +268,16 @@ static const char *const asx_mime_types[] = { }; const struct playlist_plugin asx_playlist_plugin = { - .name = "asx", + "asx", - .open_stream = asx_open_stream, - .close = asx_close, - .read = asx_read, + nullptr, + nullptr, + nullptr, + asx_open_stream, + nullptr, + nullptr, - .suffixes = asx_suffixes, - .mime_types = asx_mime_types, + nullptr, + asx_suffixes, + asx_mime_types, }; diff --git a/src/playlist/asx_playlist_plugin.h b/src/playlist/AsxPlaylistPlugin.hxx index 6c01c1209..240c1824a 100644 --- a/src/playlist/asx_playlist_plugin.h +++ b/src/playlist/AsxPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_ASX_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_ASX_PLAYLIST_PLUGIN_H +#ifndef MPD_ASX_PLAYLIST_PLUGIN_HXX +#define MPD_ASX_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin asx_playlist_plugin; diff --git a/src/playlist/cue_playlist_plugin.c b/src/playlist/CuePlaylistPlugin.cxx index b85de77d3..07eb5e243 100644 --- a/src/playlist/cue_playlist_plugin.c +++ b/src/playlist/CuePlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,13 +18,16 @@ */ #include "config.h" -#include "playlist/cue_playlist_plugin.h" -#include "playlist_plugin.h" +#include "CuePlaylistPlugin.hxx" +#include "PlaylistPlugin.hxx" #include "tag.h" #include "song.h" -#include "cue/cue_parser.h" #include "input_stream.h" + +extern "C" { #include "text_input_stream.h" +#include "cue/cue_parser.h" +} #include <glib.h> #include <assert.h> @@ -33,7 +36,7 @@ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "cue" -struct cue_playlist { +struct CuePlaylist { struct playlist_provider base; struct input_stream *is; @@ -44,21 +47,20 @@ struct cue_playlist { static struct playlist_provider * cue_playlist_open_stream(struct input_stream *is) { - struct cue_playlist *playlist = g_new(struct cue_playlist, 1); + CuePlaylist *playlist = g_new(CuePlaylist, 1); playlist_provider_init(&playlist->base, &cue_playlist_plugin); playlist->is = is; playlist->tis = text_input_stream_new(is); playlist->parser = cue_parser_new(); - return &playlist->base; } static void cue_playlist_close(struct playlist_provider *_playlist) { - struct cue_playlist *playlist = (struct cue_playlist *)_playlist; + CuePlaylist *playlist = (CuePlaylist *)_playlist; cue_parser_free(playlist->parser); text_input_stream_free(playlist->tis); @@ -68,7 +70,7 @@ cue_playlist_close(struct playlist_provider *_playlist) static struct song * cue_playlist_read(struct playlist_provider *_playlist) { - struct cue_playlist *playlist = (struct cue_playlist *)_playlist; + CuePlaylist *playlist = (CuePlaylist *)_playlist; struct song *song = cue_parser_get(playlist->parser); if (song != NULL) @@ -97,12 +99,16 @@ static const char *const cue_playlist_mime_types[] = { }; const struct playlist_plugin cue_playlist_plugin = { - .name = "cue", + "cue", - .open_stream = cue_playlist_open_stream, - .close = cue_playlist_close, - .read = cue_playlist_read, + nullptr, + nullptr, + nullptr, + cue_playlist_open_stream, + cue_playlist_close, + cue_playlist_read, - .suffixes = cue_playlist_suffixes, - .mime_types = cue_playlist_mime_types, + nullptr, + cue_playlist_suffixes, + cue_playlist_mime_types, }; diff --git a/src/playlist/cue_playlist_plugin.h b/src/playlist/CuePlaylistPlugin.hxx index c02e2235a..cf5e3a8f0 100644 --- a/src/playlist/cue_playlist_plugin.h +++ b/src/playlist/CuePlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_CUE_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_CUE_PLAYLIST_PLUGIN_H +#ifndef MPD_CUE_PLAYLIST_PLUGIN_HXX +#define MPD_CUE_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin cue_playlist_plugin; diff --git a/src/playlist/DespotifyPlaylistPlugin.cxx b/src/playlist/DespotifyPlaylistPlugin.cxx new file mode 100644 index 000000000..25f12785a --- /dev/null +++ b/src/playlist/DespotifyPlaylistPlugin.cxx @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2011-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "DespotifyPlaylistPlugin.hxx" +#include "DespotifyUtils.hxx" +#include "MemoryPlaylistProvider.hxx" +#include "tag.h" +#include "song.h" + +extern "C" { +#include <despotify.h> +} + +#include <glib.h> + +#include <string.h> +#include <stdlib.h> + +static void +add_song(std::forward_list<SongPointer> &songs, struct ds_track *track) +{ + const char *dsp_scheme = despotify_playlist_plugin.schemes[0]; + struct song *song; + char uri[128]; + char *ds_uri; + + /* Create a spt://... URI for MPD */ + g_snprintf(uri, sizeof(uri), "%s://", dsp_scheme); + ds_uri = uri + strlen(dsp_scheme) + 3; + + if (despotify_track_to_uri(track, ds_uri) != ds_uri) { + /* Should never really fail, but let's be sure */ + g_debug("Can't add track %s\n", track->title); + return; + } + + song = song_remote_new(uri); + song->tag = mpd_despotify_tag_from_track(track); + + songs.emplace_front(song); +} + +static bool +parse_track(struct despotify_session *session, + std::forward_list<SongPointer> &songs, + struct ds_link *link) +{ + struct ds_track *track = despotify_link_get_track(session, link); + if (track == nullptr) + return false; + + add_song(songs, track); + return true; +} + +static bool +parse_playlist(struct despotify_session *session, + std::forward_list<SongPointer> &songs, + struct ds_link *link) +{ + ds_playlist *playlist = despotify_link_get_playlist(session, link); + if (playlist == nullptr) + return false; + + for (ds_track *track = playlist->tracks; track != nullptr; + track = track->next) + add_song(songs, track); + + return true; +} + +static struct playlist_provider * +despotify_playlist_open_uri(const char *url, + gcc_unused Mutex &mutex, gcc_unused Cond &cond) +{ + despotify_session *session = mpd_despotify_get_session(); + if (session == nullptr) + return nullptr; + + /* Get link without spt:// */ + ds_link *link = + despotify_link_from_uri(url + strlen(despotify_playlist_plugin.schemes[0]) + 3); + if (link == nullptr) { + g_debug("Can't find %s\n", url); + return nullptr; + } + + std::forward_list<SongPointer> songs; + + bool parse_result; + switch (link->type) { + case LINK_TYPE_TRACK: + parse_result = parse_track(session, songs, link); + break; + case LINK_TYPE_PLAYLIST: + parse_result = parse_playlist(session, songs, link); + break; + default: + parse_result = false; + break; + } + + despotify_free_link(link); + if (!parse_result) + return nullptr; + + songs.reverse(); + return new MemoryPlaylistProvider(std::move(songs)); +} + +static const char *const despotify_schemes[] = { + "spt", + nullptr +}; + +const struct playlist_plugin despotify_playlist_plugin = { + "despotify", + + nullptr, + nullptr, + despotify_playlist_open_uri, + nullptr, + nullptr, + nullptr, + + despotify_schemes, + nullptr, + nullptr, +}; diff --git a/src/playlist/despotify_playlist_plugin.h b/src/playlist/DespotifyPlaylistPlugin.hxx index f8ee20de0..c1e5b7f39 100644 --- a/src/playlist/despotify_playlist_plugin.h +++ b/src/playlist/DespotifyPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Music Player Daemon Project + * Copyright (C) 2011-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_DESPOTIFY_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_DESPOTIFY_PLAYLIST_PLUGIN_H +#ifndef MPD_PLAYLIST_DESPOTIFY_PLAYLIST_PLUGIN_HXX +#define MPD_PLAYLIST_DESPOTIFY_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin despotify_playlist_plugin; diff --git a/src/playlist/embcue_playlist_plugin.c b/src/playlist/EmbeddedCuePlaylistPlugin.cxx index 6d9a957f9..04cb12eca 100644 --- a/src/playlist/embcue_playlist_plugin.c +++ b/src/playlist/EmbeddedCuePlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2012 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -24,15 +24,18 @@ */ #include "config.h" -#include "playlist/embcue_playlist_plugin.h" -#include "playlist_plugin.h" +#include "EmbeddedCuePlaylistPlugin.hxx" +#include "PlaylistPlugin.hxx" #include "tag.h" #include "tag_handler.h" -#include "tag_file.h" +#include "song.h" +#include "TagFile.hxx" + +extern "C" { #include "tag_ape.h" #include "tag_id3.h" -#include "song.h" #include "cue/cue_parser.h" +} #include <glib.h> #include <assert.h> @@ -67,7 +70,7 @@ struct embcue_playlist { static void embcue_tag_pair(const char *name, const char *value, void *ctx) { - struct embcue_playlist *playlist = ctx; + struct embcue_playlist *playlist = (struct embcue_playlist *)ctx; if (playlist->cuesheet == NULL && g_ascii_strcasecmp(name, "cuesheet") == 0) @@ -75,13 +78,15 @@ embcue_tag_pair(const char *name, const char *value, void *ctx) } static const struct tag_handler embcue_tag_handler = { - .pair = embcue_tag_pair, + nullptr, + nullptr, + embcue_tag_pair, }; static struct playlist_provider * embcue_playlist_open_uri(const char *uri, - G_GNUC_UNUSED GMutex *mutex, - G_GNUC_UNUSED GCond *cond) + gcc_unused Mutex &mutex, + gcc_unused Cond &cond) { if (!g_path_is_absolute(uri)) /* only local files supported */ @@ -170,12 +175,16 @@ static const char *const embcue_playlist_suffixes[] = { }; const struct playlist_plugin embcue_playlist_plugin = { - .name = "cue", - - .open_uri = embcue_playlist_open_uri, - .close = embcue_playlist_close, - .read = embcue_playlist_read, - - .suffixes = embcue_playlist_suffixes, - .mime_types = NULL, + "cue", + + nullptr, + nullptr, + embcue_playlist_open_uri, + nullptr, + embcue_playlist_close, + embcue_playlist_read, + + embcue_playlist_suffixes, + nullptr, + nullptr, }; diff --git a/src/playlist/embcue_playlist_plugin.h b/src/playlist/EmbeddedCuePlaylistPlugin.hxx index c5f21b27e..e306730f4 100644 --- a/src/playlist/embcue_playlist_plugin.h +++ b/src/playlist/EmbeddedCuePlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2012 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_EMBCUE_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_EMBCUE_PLAYLIST_PLUGIN_H +#ifndef MPD_EMBCUE_PLAYLIST_PLUGIN_HXX +#define MPD_EMBCUE_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin embcue_playlist_plugin; diff --git a/src/playlist/extm3u_playlist_plugin.c b/src/playlist/ExtM3uPlaylistPlugin.cxx index 19be8d1c4..ce026dab8 100644 --- a/src/playlist/extm3u_playlist_plugin.c +++ b/src/playlist/ExtM3uPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,20 +18,22 @@ */ #include "config.h" -#include "playlist/extm3u_playlist_plugin.h" -#include "playlist_plugin.h" -#include "text_input_stream.h" -#include "uri.h" +#include "ExtM3uPlaylistPlugin.hxx" +#include "PlaylistPlugin.hxx" #include "song.h" #include "tag.h" #include "string_util.h" +extern "C" { +#include "text_input_stream.h" +} + #include <glib.h> #include <string.h> #include <stdlib.h> -struct extm3u_playlist { +struct ExtM3uPlaylist { struct playlist_provider base; struct text_input_stream *tis; @@ -40,13 +42,10 @@ struct extm3u_playlist { static struct playlist_provider * extm3u_open_stream(struct input_stream *is) { - struct extm3u_playlist *playlist; - const char *line; - - playlist = g_new(struct extm3u_playlist, 1); + ExtM3uPlaylist *playlist = g_new(ExtM3uPlaylist, 1); playlist->tis = text_input_stream_new(is); - line = text_input_stream_read(playlist->tis); + const char *line = text_input_stream_read(playlist->tis); if (line == NULL || strcmp(line, "#EXTM3U") != 0) { /* no EXTM3U header: fall back to the plain m3u plugin */ @@ -62,7 +61,7 @@ extm3u_open_stream(struct input_stream *is) static void extm3u_close(struct playlist_provider *_playlist) { - struct extm3u_playlist *playlist = (struct extm3u_playlist *)_playlist; + ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist; text_input_stream_free(playlist->tis); g_free(playlist); @@ -111,7 +110,7 @@ extm3u_parse_tag(const char *line) static struct song * extm3u_read(struct playlist_provider *_playlist) { - struct extm3u_playlist *playlist = (struct extm3u_playlist *)_playlist; + ExtM3uPlaylist *playlist = (ExtM3uPlaylist *)_playlist; struct tag *tag = NULL; const char *line; struct song *song; @@ -151,12 +150,16 @@ static const char *const extm3u_mime_types[] = { }; const struct playlist_plugin extm3u_playlist_plugin = { - .name = "extm3u", - - .open_stream = extm3u_open_stream, - .close = extm3u_close, - .read = extm3u_read, - - .suffixes = extm3u_suffixes, - .mime_types = extm3u_mime_types, + "extm3u", + + nullptr, + nullptr, + nullptr, + extm3u_open_stream, + extm3u_close, + extm3u_read, + + nullptr, + extm3u_suffixes, + extm3u_mime_types, }; diff --git a/src/playlist/extm3u_playlist_plugin.h b/src/playlist/ExtM3uPlaylistPlugin.hxx index 5f611ac9c..844fba15c 100644 --- a/src/playlist/extm3u_playlist_plugin.h +++ b/src/playlist/ExtM3uPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_EXTM3U_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_EXTM3U_PLAYLIST_PLUGIN_H +#ifndef MPD_EXTM3U_PLAYLIST_PLUGIN_HXX +#define MPD_EXTM3U_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin extm3u_playlist_plugin; diff --git a/src/playlist/lastfm_playlist_plugin.c b/src/playlist/LastFMPlaylistPlugin.cxx index ead14deaa..496388407 100644 --- a/src/playlist/lastfm_playlist_plugin.c +++ b/src/playlist/LastFMPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,11 +18,10 @@ */ #include "config.h" -#include "playlist/lastfm_playlist_plugin.h" -#include "playlist_plugin.h" -#include "playlist_list.h" +#include "LastFMPlaylistPlugin.hxx" +#include "PlaylistPlugin.hxx" +#include "PlaylistRegistry.hxx" #include "conf.h" -#include "uri.h" #include "song.h" #include "input_stream.h" @@ -80,7 +79,7 @@ lastfm_finish(void) * @return data fetched, or NULL on error. Must be freed with g_free. */ static char * -lastfm_get(const char *url, GMutex *mutex, GCond *cond) +lastfm_get(const char *url, Mutex &mutex, Cond &cond) { struct input_stream *input_stream; GError *error = NULL; @@ -97,7 +96,7 @@ lastfm_get(const char *url, GMutex *mutex, GCond *cond) return NULL; } - g_mutex_lock(mutex); + mutex.lock(); input_stream_wait_ready(input_stream); @@ -114,7 +113,7 @@ lastfm_get(const char *url, GMutex *mutex, GCond *cond) break; /* I/O error */ - g_mutex_unlock(mutex); + mutex.unlock(); input_stream_close(input_stream); return NULL; } @@ -122,7 +121,7 @@ lastfm_get(const char *url, GMutex *mutex, GCond *cond) length += nbytes; } while (length < sizeof(buffer)); - g_mutex_unlock(mutex); + mutex.unlock(); input_stream_close(input_stream); return g_strndup(buffer, length); @@ -155,7 +154,7 @@ lastfm_find(const char *response, const char *name) } static struct playlist_provider * -lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond) +lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond) { struct lastfm_playlist *playlist; GError *error = NULL; @@ -236,16 +235,15 @@ lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond) return NULL; } - g_mutex_lock(mutex); + mutex.lock(); 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"); + input_stream_override_mime_type(playlist->is, "application/xspf+xml"); - g_mutex_unlock(mutex); + mutex.unlock(); /* parse the XSPF playlist */ @@ -284,13 +282,16 @@ static const char *const lastfm_schemes[] = { }; const struct playlist_plugin lastfm_playlist_plugin = { - .name = "lastfm", + "lastfm", - .init = lastfm_init, - .finish = lastfm_finish, - .open_uri = lastfm_open_uri, - .close = lastfm_close, - .read = lastfm_read, + lastfm_init, + lastfm_finish, + lastfm_open_uri, + nullptr, + lastfm_close, + lastfm_read, - .schemes = lastfm_schemes, + lastfm_schemes, + nullptr, + nullptr, }; diff --git a/src/playlist/lastfm_playlist_plugin.h b/src/playlist/LastFMPlaylistPlugin.hxx index 46a8b0caf..fe0e206d8 100644 --- a/src/playlist/lastfm_playlist_plugin.h +++ b/src/playlist/LastFMPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_LASTFM_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_LASTFM_PLAYLIST_PLUGIN_H +#ifndef MPD_LASTFM_PLAYLIST_PLUGIN_HXX +#define MPD_LASTFM_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin lastfm_playlist_plugin; diff --git a/src/playlist/m3u_playlist_plugin.c b/src/playlist/M3uPlaylistPlugin.cxx index 45b70d2b1..eeecd2779 100644 --- a/src/playlist/m3u_playlist_plugin.c +++ b/src/playlist/M3uPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,15 +18,17 @@ */ #include "config.h" -#include "playlist/m3u_playlist_plugin.h" -#include "playlist_plugin.h" -#include "text_input_stream.h" -#include "uri.h" +#include "M3uPlaylistPlugin.hxx" +#include "PlaylistPlugin.hxx" #include "song.h" +extern "C" { +#include "text_input_stream.h" +} + #include <glib.h> -struct m3u_playlist { +struct M3uPlaylist { struct playlist_provider base; struct text_input_stream *tis; @@ -35,7 +37,7 @@ struct m3u_playlist { static struct playlist_provider * m3u_open_stream(struct input_stream *is) { - struct m3u_playlist *playlist = g_new(struct m3u_playlist, 1); + M3uPlaylist *playlist = g_new(M3uPlaylist, 1); playlist_provider_init(&playlist->base, &m3u_playlist_plugin); playlist->tis = text_input_stream_new(is); @@ -46,7 +48,7 @@ m3u_open_stream(struct input_stream *is) static void m3u_close(struct playlist_provider *_playlist) { - struct m3u_playlist *playlist = (struct m3u_playlist *)_playlist; + M3uPlaylist *playlist = (M3uPlaylist *)_playlist; text_input_stream_free(playlist->tis); g_free(playlist); @@ -55,7 +57,7 @@ m3u_close(struct playlist_provider *_playlist) static struct song * m3u_read(struct playlist_provider *_playlist) { - struct m3u_playlist *playlist = (struct m3u_playlist *)_playlist; + M3uPlaylist *playlist = (M3uPlaylist *)_playlist; const char *line; do { @@ -81,12 +83,16 @@ static const char *const m3u_mime_types[] = { }; const struct playlist_plugin m3u_playlist_plugin = { - .name = "m3u", + "m3u", - .open_stream = m3u_open_stream, - .close = m3u_close, - .read = m3u_read, + nullptr, + nullptr, + nullptr, + m3u_open_stream, + m3u_close, + m3u_read, - .suffixes = m3u_suffixes, - .mime_types = m3u_mime_types, + nullptr, + m3u_suffixes, + m3u_mime_types, }; diff --git a/src/playlist/m3u_playlist_plugin.h b/src/playlist/M3uPlaylistPlugin.hxx index 3890a5fc2..a2058bb29 100644 --- a/src/playlist/m3u_playlist_plugin.h +++ b/src/playlist/M3uPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_M3U_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_M3U_PLAYLIST_PLUGIN_H +#ifndef MPD_M3U_PLAYLIST_PLUGIN_HXX +#define MPD_M3U_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin m3u_playlist_plugin; diff --git a/src/playlist/MemoryPlaylistProvider.cxx b/src/playlist/MemoryPlaylistProvider.cxx new file mode 100644 index 000000000..4fe3d6cef --- /dev/null +++ b/src/playlist/MemoryPlaylistProvider.cxx @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "MemoryPlaylistProvider.hxx" +#include "song.h" + +static void +memory_playlist_close(struct playlist_provider *_playlist) +{ + MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist; + + delete playlist; +} + +static struct song * +memory_playlist_read(struct playlist_provider *_playlist) +{ + MemoryPlaylistProvider *playlist = (MemoryPlaylistProvider *)_playlist; + + return playlist->Read(); +} + +static constexpr struct playlist_plugin memory_playlist_plugin = { + nullptr, + + nullptr, + nullptr, + nullptr, + nullptr, + memory_playlist_close, + memory_playlist_read, + + nullptr, + nullptr, + nullptr, +}; + +MemoryPlaylistProvider::MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs) + :songs(std::move(_songs)) { + playlist_provider_init(this, &memory_playlist_plugin); +} + +inline song * +MemoryPlaylistProvider::Read() +{ + if (songs.empty()) + return NULL; + + auto result = songs.front().Steal(); + songs.pop_front(); + return result; +} diff --git a/src/playlist/MemoryPlaylistProvider.hxx b/src/playlist/MemoryPlaylistProvider.hxx new file mode 100644 index 000000000..246ffd10a --- /dev/null +++ b/src/playlist/MemoryPlaylistProvider.hxx @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2003-2013 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_MEMORY_PLAYLIST_PROVIDER_HXX +#define MPD_MEMORY_PLAYLIST_PROVIDER_HXX + +#include "PlaylistPlugin.hxx" +#include "SongPointer.hxx" + +#include <forward_list> + +struct song; + +class MemoryPlaylistProvider : public playlist_provider { + std::forward_list<SongPointer> songs; + +public: + MemoryPlaylistProvider(std::forward_list<SongPointer> &&_songs); + + song *Read(); +}; + +#endif diff --git a/src/playlist/pls_playlist_plugin.c b/src/playlist/PlsPlaylistPlugin.cxx index c4e5492af..3cf5f46e5 100644 --- a/src/playlist/pls_playlist_plugin.c +++ b/src/playlist/PlsPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,21 +18,17 @@ */ #include "config.h" -#include "playlist/pls_playlist_plugin.h" -#include "playlist_plugin.h" +#include "PlsPlaylistPlugin.hxx" +#include "MemoryPlaylistProvider.hxx" #include "input_stream.h" #include "uri.h" #include "song.h" #include "tag.h" -#include <glib.h> - -struct pls_playlist { - struct playlist_provider base; - GSList *songs; -}; +#include <glib.h> -static void pls_parser(GKeyFile *keyfile, struct pls_playlist *playlist) +static void +pls_parser(GKeyFile *keyfile, std::forward_list<SongPointer> &songs) { gchar *key; gchar *value; @@ -97,7 +93,7 @@ static void pls_parser(GKeyFile *keyfile, struct pls_playlist *playlist) if(error) g_error_free(error); error = NULL; - playlist->songs = g_slist_prepend(playlist->songs, song); + songs.emplace_front(song); num_entries--; } @@ -111,7 +107,6 @@ pls_open_stream(struct input_stream *is) char buffer[1024]; bool success; GKeyFile *keyfile; - struct pls_playlist *playlist; GString *kf_data = g_string_new(""); do { @@ -152,50 +147,12 @@ pls_open_stream(struct input_stream *is) return NULL; } - playlist = g_new(struct pls_playlist, 1); - playlist_provider_init(&playlist->base, &pls_playlist_plugin); - playlist->songs = NULL; - - pls_parser(keyfile, playlist); - + std::forward_list<SongPointer> songs; + pls_parser(keyfile, songs); g_key_file_free(keyfile); - return &playlist->base; -} - -static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = data; - - song_free(song); -} - -static void -pls_close(struct playlist_provider *_playlist) -{ - struct pls_playlist *playlist = (struct pls_playlist *)_playlist; - - g_slist_foreach(playlist->songs, song_free_callback, NULL); - g_slist_free(playlist->songs); - - g_free(playlist); - -} - -static struct song * -pls_read(struct playlist_provider *_playlist) -{ - struct pls_playlist *playlist = (struct pls_playlist *)_playlist; - struct song *song; - - if (playlist->songs == NULL) - return NULL; - - song = playlist->songs->data; - playlist->songs = g_slist_remove(playlist->songs, song); - - return song; + songs.reverse(); + return new MemoryPlaylistProvider(std::move(songs)); } static const char *const pls_suffixes[] = { @@ -209,12 +166,16 @@ static const char *const pls_mime_types[] = { }; const struct playlist_plugin pls_playlist_plugin = { - .name = "pls", + "pls", - .open_stream = pls_open_stream, - .close = pls_close, - .read = pls_read, + nullptr, + nullptr, + nullptr, + pls_open_stream, + nullptr, + nullptr, - .suffixes = pls_suffixes, - .mime_types = pls_mime_types, + nullptr, + pls_suffixes, + pls_mime_types, }; diff --git a/src/playlist/pls_playlist_plugin.h b/src/playlist/PlsPlaylistPlugin.hxx index d03435f6d..3fafd36d0 100644 --- a/src/playlist/pls_playlist_plugin.h +++ b/src/playlist/PlsPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_PLS_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_PLS_PLAYLIST_PLUGIN_H +#ifndef MPD_PLS_PLAYLIST_PLUGIN_HXX +#define MPD_PLS_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin pls_playlist_plugin; diff --git a/src/playlist/rss_playlist_plugin.c b/src/playlist/RssPlaylistPlugin.cxx index 6740cba7e..3b69202e6 100644 --- a/src/playlist/rss_playlist_plugin.c +++ b/src/playlist/RssPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,8 +18,8 @@ */ #include "config.h" -#include "playlist/rss_playlist_plugin.h" -#include "playlist_plugin.h" +#include "RssPlaylistPlugin.hxx" +#include "MemoryPlaylistProvider.hxx" #include "input_stream.h" #include "song.h" #include "tag.h" @@ -35,12 +35,12 @@ /** * This is the state object for the GLib XML parser. */ -struct rss_parser { +struct RssParser { /** * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list<SongPointer> songs; /** * The current position in the XML file. @@ -61,6 +61,9 @@ struct rss_parser { * element. */ struct song *song; + + RssParser() + :state(ROOT) {} }; static const gchar * @@ -81,19 +84,19 @@ rss_start_element(G_GNUC_UNUSED GMarkupParseContext *context, const gchar **attribute_values, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct rss_parser *parser = user_data; + RssParser *parser = (RssParser *)user_data; switch (parser->state) { - case ROOT: + case RssParser::ROOT: if (g_ascii_strcasecmp(element_name, "item") == 0) { - parser->state = ITEM; + parser->state = RssParser::ITEM; parser->song = song_remote_new("rss:"); parser->tag = TAG_NUM_OF_ITEM_TYPES; } break; - case ITEM: + case RssParser::ITEM: if (g_ascii_strcasecmp(element_name, "enclosure") == 0) { const gchar *href = get_attribute(attribute_names, attribute_values, @@ -128,21 +131,20 @@ rss_end_element(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *element_name, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct rss_parser *parser = user_data; + RssParser *parser = (RssParser *)user_data; switch (parser->state) { - case ROOT: + case RssParser::ROOT: break; - case ITEM: + case RssParser::ITEM: if (g_ascii_strcasecmp(element_name, "item") == 0) { if (strcmp(parser->song->uri, "rss:") != 0) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); else song_free(parser->song); - parser->state = ROOT; + parser->state = RssParser::ROOT; } else parser->tag = TAG_NUM_OF_ITEM_TYPES; @@ -155,13 +157,13 @@ rss_text(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct rss_parser *parser = user_data; + RssParser *parser = (RssParser *)user_data; switch (parser->state) { - case ROOT: + case RssParser::ROOT: break; - case ITEM: + case RssParser::ITEM: if (parser->tag != TAG_NUM_OF_ITEM_TYPES) { if (parser->song->tag == NULL) parser->song->tag = tag_new(); @@ -174,29 +176,20 @@ rss_text(G_GNUC_UNUSED GMarkupParseContext *context, } static const GMarkupParser rss_parser = { - .start_element = rss_start_element, - .end_element = rss_end_element, - .text = rss_text, + rss_start_element, + rss_end_element, + rss_text, + nullptr, + nullptr, }; static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = data; - - song_free(song); -} - -static void rss_parser_destroy(gpointer data) { - struct rss_parser *parser = data; + RssParser *parser = (RssParser *)data; - if (parser->state >= ITEM) + if (parser->state >= RssParser::ITEM) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -204,20 +197,10 @@ rss_parser_destroy(gpointer data) * */ -struct rss_playlist { - struct playlist_provider base; - - GSList *songs; -}; - static struct playlist_provider * rss_open_stream(struct input_stream *is) { - struct rss_parser parser = { - .songs = NULL, - .state = ROOT, - }; - struct rss_playlist *playlist; + RssParser parser; GMarkupParseContext *context; char buffer[1024]; size_t nbytes; @@ -262,41 +245,13 @@ rss_open_stream(struct input_stream *is) return NULL; } - /* create a #rss_playlist object from the parsed song list */ - - playlist = g_new(struct rss_playlist, 1); - playlist_provider_init(&playlist->base, &rss_playlist_plugin); - playlist->songs = g_slist_reverse(parser.songs); - parser.songs = NULL; + parser.songs.reverse(); + MemoryPlaylistProvider *playlist = + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); - return &playlist->base; -} - -static void -rss_close(struct playlist_provider *_playlist) -{ - struct rss_playlist *playlist = (struct rss_playlist *)_playlist; - - g_slist_foreach(playlist->songs, song_free_callback, NULL); - g_slist_free(playlist->songs); - g_free(playlist); -} - -static struct song * -rss_read(struct playlist_provider *_playlist) -{ - struct rss_playlist *playlist = (struct rss_playlist *)_playlist; - struct song *song; - - if (playlist->songs == NULL) - return NULL; - - song = playlist->songs->data; - playlist->songs = g_slist_remove(playlist->songs, song); - - return song; + return playlist; } static const char *const rss_suffixes[] = { @@ -311,12 +266,16 @@ static const char *const rss_mime_types[] = { }; const struct playlist_plugin rss_playlist_plugin = { - .name = "rss", + "rss", - .open_stream = rss_open_stream, - .close = rss_close, - .read = rss_read, + nullptr, + nullptr, + nullptr, + rss_open_stream, + nullptr, + nullptr, - .suffixes = rss_suffixes, - .mime_types = rss_mime_types, + nullptr, + rss_suffixes, + rss_mime_types, }; diff --git a/src/playlist/rss_playlist_plugin.h b/src/playlist/RssPlaylistPlugin.hxx index 3b376de79..f49f7e9cf 100644 --- a/src/playlist/rss_playlist_plugin.h +++ b/src/playlist/RssPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_RSS_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_RSS_PLAYLIST_PLUGIN_H +#ifndef MPD_RSS_PLAYLIST_PLUGIN_HXX +#define MPD_RSS_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin rss_playlist_plugin; diff --git a/src/playlist/soundcloud_playlist_plugin.c b/src/playlist/SoundCloudPlaylistPlugin.cxx index 7c79f880a..5a258865c 100644 --- a/src/playlist/soundcloud_playlist_plugin.c +++ b/src/playlist/SoundCloudPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,10 +18,10 @@ */ #include "config.h" -#include "playlist/soundcloud_playlist_plugin.h" +#include "SoundCloudPlaylistPlugin.hxx" +#include "MemoryPlaylistProvider.hxx" #include "conf.h" #include "input_stream.h" -#include "playlist_plugin.h" #include "song.h" #include "tag.h" @@ -30,12 +30,6 @@ #include <string.h> -struct soundcloud_playlist { - struct playlist_provider base; - - GSList *songs; -}; - static struct { char *apikey; } soundcloud_config; @@ -107,7 +101,8 @@ struct parse_data { long duration; char* title; int got_url; /* nesting level of last stream_url */ - GSList* songs; + + std::forward_list<SongPointer> songs; }; static int handle_integer(void *ctx, @@ -221,7 +216,7 @@ static int handle_end_map(void *ctx) tag_add_item(t, TAG_NAME, data->title); s->tag = t; - data->songs = g_slist_prepend(data->songs, s); + data->songs.emplace_front(s); return 1; } @@ -247,7 +242,8 @@ static yajl_callbacks parse_callbacks = { * @return -1 on error, 0 on success. */ static int -soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* cond) +soundcloud_parse_json(const char *url, yajl_handle hand, + Mutex &mutex, Cond &cond) { struct input_stream *input_stream; GError *error = NULL; @@ -264,7 +260,7 @@ soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* c return -1; } - g_mutex_lock(mutex); + mutex.lock(); input_stream_wait_ready(input_stream); yajl_status stat; @@ -280,7 +276,7 @@ soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* c if (input_stream_eof(input_stream)) { done = true; } else { - g_mutex_unlock(mutex); + mutex.unlock(); input_stream_close(input_stream); return -1; } @@ -308,7 +304,7 @@ soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* c } } - g_mutex_unlock(mutex); + mutex.unlock(); input_stream_close(input_stream); return 0; @@ -323,10 +319,8 @@ soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* c */ static struct playlist_provider * -soundcloud_open_uri(const char *uri, GMutex *mutex, GCond *cond) +soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) { - struct soundcloud_playlist *playlist = NULL; - char *s, *p; char *scheme, *arg, *rest; s = g_strdup(uri); @@ -377,7 +371,6 @@ soundcloud_open_uri(const char *uri, GMutex *mutex, GCond *cond) struct parse_data data; data.got_url = 0; - data.songs = NULL; data.title = NULL; data.stream_url = NULL; #ifdef HAVE_YAJL1 @@ -398,34 +391,8 @@ soundcloud_open_uri(const char *uri, GMutex *mutex, GCond *cond) 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 void -soundcloud_close(struct playlist_provider *_playlist) -{ - struct soundcloud_playlist *playlist = (struct soundcloud_playlist *)_playlist; - - g_free(playlist); -} - - -static struct song * -soundcloud_read(struct playlist_provider *_playlist) -{ - struct soundcloud_playlist *playlist = (struct soundcloud_playlist *)_playlist; - - if (playlist->songs == NULL) - return NULL; - - struct song* s; - s = (struct song *)playlist->songs->data; - playlist->songs = g_slist_remove(playlist->songs, s); - return s; + data.songs.reverse(); + return new MemoryPlaylistProvider(std::move(data.songs)); } static const char *const soundcloud_schemes[] = { @@ -434,15 +401,18 @@ static const char *const soundcloud_schemes[] = { }; const struct playlist_plugin soundcloud_playlist_plugin = { - .name = "soundcloud", + "soundcloud", - .init = soundcloud_init, - .finish = soundcloud_finish, - .open_uri = soundcloud_open_uri, - .close = soundcloud_close, - .read = soundcloud_read, + soundcloud_init, + soundcloud_finish, + soundcloud_open_uri, + nullptr, + nullptr, + nullptr, - .schemes = soundcloud_schemes, + soundcloud_schemes, + nullptr, + nullptr, }; diff --git a/src/playlist/soundcloud_playlist_plugin.h b/src/playlist/SoundCloudPlaylistPlugin.hxx index e09e2dd46..7c121328c 100644 --- a/src/playlist/soundcloud_playlist_plugin.h +++ b/src/playlist/SoundCloudPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_SOUNDCLOUD_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_SOUNDCLOUD_PLAYLIST_PLUGIN_H +#ifndef MPD_SOUNDCLOUD_PLAYLIST_PLUGIN_HXX +#define MPD_SOUNDCLOUD_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin soundcloud_playlist_plugin; diff --git a/src/playlist/xspf_playlist_plugin.c b/src/playlist/XspfPlaylistPlugin.cxx index 17d9040e2..bd84d86b7 100644 --- a/src/playlist/xspf_playlist_plugin.c +++ b/src/playlist/XspfPlaylistPlugin.cxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -18,11 +18,10 @@ */ #include "config.h" -#include "playlist/xspf_playlist_plugin.h" -#include "playlist_plugin.h" +#include "XspfPlaylistPlugin.hxx" +#include "MemoryPlaylistProvider.hxx" #include "input_stream.h" #include "uri.h" -#include "song.h" #include "tag.h" #include <glib.h> @@ -36,12 +35,12 @@ /** * This is the state object for the GLib XML parser. */ -struct xspf_parser { +struct XspfParser { /** * The list of songs (in reverse order because that's faster * while adding). */ - GSList *songs; + std::forward_list<SongPointer> songs; /** * The current position in the XML file. @@ -63,6 +62,9 @@ struct xspf_parser { * element. */ struct song *song; + + XspfParser() + :state(ROOT) {} }; static void @@ -72,33 +74,33 @@ xspf_start_element(G_GNUC_UNUSED GMarkupParseContext *context, G_GNUC_UNUSED const gchar **attribute_values, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct xspf_parser *parser = user_data; + XspfParser *parser = (XspfParser *)user_data; switch (parser->state) { - case ROOT: + case XspfParser::ROOT: if (strcmp(element_name, "playlist") == 0) - parser->state = PLAYLIST; + parser->state = XspfParser::PLAYLIST; break; - case PLAYLIST: + case XspfParser::PLAYLIST: if (strcmp(element_name, "trackList") == 0) - parser->state = TRACKLIST; + parser->state = XspfParser::TRACKLIST; break; - case TRACKLIST: + case XspfParser::TRACKLIST: if (strcmp(element_name, "track") == 0) { - parser->state = TRACK; + parser->state = XspfParser::TRACK; parser->song = NULL; parser->tag = TAG_NUM_OF_ITEM_TYPES; } break; - case TRACK: + case XspfParser::TRACK: if (strcmp(element_name, "location") == 0) - parser->state = LOCATION; + parser->state = XspfParser::LOCATION; else if (strcmp(element_name, "title") == 0) parser->tag = TAG_TITLE; else if (strcmp(element_name, "creator") == 0) @@ -114,7 +116,7 @@ xspf_start_element(G_GNUC_UNUSED GMarkupParseContext *context, break; - case LOCATION: + case XspfParser::LOCATION: break; } } @@ -124,38 +126,37 @@ xspf_end_element(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *element_name, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct xspf_parser *parser = user_data; + XspfParser *parser = (XspfParser *)user_data; switch (parser->state) { - case ROOT: + case XspfParser::ROOT: break; - case PLAYLIST: + case XspfParser::PLAYLIST: if (strcmp(element_name, "playlist") == 0) - parser->state = ROOT; + parser->state = XspfParser::ROOT; break; - case TRACKLIST: + case XspfParser::TRACKLIST: if (strcmp(element_name, "tracklist") == 0) - parser->state = PLAYLIST; + parser->state = XspfParser::PLAYLIST; break; - case TRACK: + case XspfParser::TRACK: if (strcmp(element_name, "track") == 0) { if (parser->song != NULL) - parser->songs = g_slist_prepend(parser->songs, - parser->song); + parser->songs.emplace_front(parser->song); - parser->state = TRACKLIST; + parser->state = XspfParser::TRACKLIST; } else parser->tag = TAG_NUM_OF_ITEM_TYPES; break; - case LOCATION: - parser->state = TRACK; + case XspfParser::LOCATION: + parser->state = XspfParser::TRACK; break; } } @@ -165,15 +166,15 @@ xspf_text(G_GNUC_UNUSED GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, G_GNUC_UNUSED GError **error) { - struct xspf_parser *parser = user_data; + XspfParser *parser = (XspfParser *)user_data; switch (parser->state) { - case ROOT: - case PLAYLIST: - case TRACKLIST: + case XspfParser::ROOT: + case XspfParser::PLAYLIST: + case XspfParser::TRACKLIST: break; - case TRACK: + case XspfParser::TRACK: if (parser->song != NULL && parser->tag != TAG_NUM_OF_ITEM_TYPES) { if (parser->song->tag == NULL) @@ -184,7 +185,7 @@ xspf_text(G_GNUC_UNUSED GMarkupParseContext *context, break; - case LOCATION: + case XspfParser::LOCATION: if (parser->song == NULL) { char *uri = g_strndup(text, text_len); parser->song = song_remote_new(uri); @@ -196,29 +197,20 @@ xspf_text(G_GNUC_UNUSED GMarkupParseContext *context, } static const GMarkupParser xspf_parser = { - .start_element = xspf_start_element, - .end_element = xspf_end_element, - .text = xspf_text, + xspf_start_element, + xspf_end_element, + xspf_text, + nullptr, + nullptr, }; static void -song_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = data; - - song_free(song); -} - -static void xspf_parser_destroy(gpointer data) { - struct xspf_parser *parser = data; + XspfParser *parser = (XspfParser *)data; - if (parser->state >= TRACK && parser->song != NULL) + if (parser->state >= XspfParser::TRACK && parser->song != NULL) song_free(parser->song); - - g_slist_foreach(parser->songs, song_free_callback, NULL); - g_slist_free(parser->songs); } /* @@ -226,20 +218,10 @@ xspf_parser_destroy(gpointer data) * */ -struct xspf_playlist { - struct playlist_provider base; - - GSList *songs; -}; - static struct playlist_provider * xspf_open_stream(struct input_stream *is) { - struct xspf_parser parser = { - .songs = NULL, - .state = ROOT, - }; - struct xspf_playlist *playlist; + XspfParser parser; GMarkupParseContext *context; char buffer[1024]; size_t nbytes; @@ -284,41 +266,13 @@ xspf_open_stream(struct input_stream *is) return NULL; } - /* create a #xspf_playlist object from the parsed song list */ - - playlist = g_new(struct xspf_playlist, 1); - playlist_provider_init(&playlist->base, &xspf_playlist_plugin); - playlist->songs = g_slist_reverse(parser.songs); - parser.songs = NULL; + parser.songs.reverse(); + MemoryPlaylistProvider *playlist = + new MemoryPlaylistProvider(std::move(parser.songs)); g_markup_parse_context_free(context); - return &playlist->base; -} - -static void -xspf_close(struct playlist_provider *_playlist) -{ - struct xspf_playlist *playlist = (struct xspf_playlist *)_playlist; - - g_slist_foreach(playlist->songs, song_free_callback, NULL); - g_slist_free(playlist->songs); - g_free(playlist); -} - -static struct song * -xspf_read(struct playlist_provider *_playlist) -{ - struct xspf_playlist *playlist = (struct xspf_playlist *)_playlist; - struct song *song; - - if (playlist->songs == NULL) - return NULL; - - song = playlist->songs->data; - playlist->songs = g_slist_remove(playlist->songs, song); - - return song; + return playlist; } static const char *const xspf_suffixes[] = { @@ -332,12 +286,16 @@ static const char *const xspf_mime_types[] = { }; const struct playlist_plugin xspf_playlist_plugin = { - .name = "xspf", + "xspf", - .open_stream = xspf_open_stream, - .close = xspf_close, - .read = xspf_read, + nullptr, + nullptr, + nullptr, + xspf_open_stream, + nullptr, + nullptr, - .suffixes = xspf_suffixes, - .mime_types = xspf_mime_types, + nullptr, + xspf_suffixes, + xspf_mime_types, }; diff --git a/src/playlist/xspf_playlist_plugin.h b/src/playlist/XspfPlaylistPlugin.hxx index 4636d7e83..fc9bbd2c6 100644 --- a/src/playlist/xspf_playlist_plugin.h +++ b/src/playlist/XspfPlaylistPlugin.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2011 The Music Player Daemon Project + * Copyright (C) 2003-2013 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -17,8 +17,8 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef MPD_PLAYLIST_XSPF_PLAYLIST_PLUGIN_H -#define MPD_PLAYLIST_XSPF_PLAYLIST_PLUGIN_H +#ifndef MPD_XSPF_PLAYLIST_PLUGIN_HXX +#define MPD_XSPF_PLAYLIST_PLUGIN_HXX extern const struct playlist_plugin xspf_playlist_plugin; diff --git a/src/playlist/despotify_playlist_plugin.c b/src/playlist/despotify_playlist_plugin.c deleted file mode 100644 index 30b852c73..000000000 --- a/src/playlist/despotify_playlist_plugin.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2011 The Music Player Daemon Project - * http://www.musicpd.org - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "config.h" -#include "playlist/despotify_playlist_plugin.h" -#include "playlist_plugin.h" -#include "playlist_list.h" -#include "conf.h" -#include "uri.h" -#include "tag.h" -#include "song.h" -#include "input_stream.h" -#include "despotify_utils.h" - -#include <glib.h> - -#include <assert.h> -#include <string.h> -#include <stdlib.h> -#include <despotify.h> - -struct despotify_playlist { - struct playlist_provider base; - - struct despotify_session *session; - GSList *list; -}; - -static void -add_song(struct despotify_playlist *ctx, struct ds_track *track) -{ - const char *dsp_scheme = despotify_playlist_plugin.schemes[0]; - struct song *song; - char uri[128]; - char *ds_uri; - - /* Create a spt://... URI for MPD */ - g_snprintf(uri, sizeof(uri), "%s://", dsp_scheme); - ds_uri = uri + strlen(dsp_scheme) + 3; - - if (despotify_track_to_uri(track, ds_uri) != ds_uri) { - /* Should never really fail, but let's be sure */ - g_debug("Can't add track %s\n", track->title); - return; - } - - song = song_remote_new(uri); - song->tag = mpd_despotify_tag_from_track(track); - - ctx->list = g_slist_prepend(ctx->list, song); -} - -static bool -parse_track(struct despotify_playlist *ctx, - struct ds_link *link) -{ - struct ds_track *track; - - track = despotify_link_get_track(ctx->session, link); - if (!track) - return false; - add_song(ctx, track); - - return true; -} - -static bool -parse_playlist(struct despotify_playlist *ctx, - struct ds_link *link) -{ - struct ds_playlist *playlist; - struct ds_track *track; - - playlist = despotify_link_get_playlist(ctx->session, link); - if (!playlist) - return false; - - for (track = playlist->tracks; track; track = track->next) - add_song(ctx, track); - - return true; -} - -static bool -despotify_playlist_init(G_GNUC_UNUSED const struct config_param *param) -{ - return true; -} - -static void -despotify_playlist_finish(void) -{ -} - - -static struct playlist_provider * -despotify_playlist_open_uri(const char *url, G_GNUC_UNUSED GMutex *mutex, - G_GNUC_UNUSED GCond *cond) -{ - struct despotify_playlist *ctx; - struct despotify_session *session; - struct ds_link *link; - bool parse_result; - - session = mpd_despotify_get_session(); - if (!session) - goto clean_none; - - /* Get link without spt:// */ - link = despotify_link_from_uri(url + strlen(despotify_playlist_plugin.schemes[0]) + 3); - if (!link) { - g_debug("Can't find %s\n", url); - goto clean_none; - } - - ctx = g_new(struct despotify_playlist, 1); - - ctx->list = NULL; - ctx->session = session; - playlist_provider_init(&ctx->base, &despotify_playlist_plugin); - - switch (link->type) - { - case LINK_TYPE_TRACK: - parse_result = parse_track(ctx, link); - break; - case LINK_TYPE_PLAYLIST: - parse_result = parse_playlist(ctx, link); - break; - default: - parse_result = false; - break; - } - despotify_free_link(link); - if (!parse_result) - goto clean_playlist; - - ctx->list = g_slist_reverse(ctx->list); - - return &ctx->base; - -clean_playlist: - g_slist_free(ctx->list); -clean_none: - - return NULL; -} - -static void -track_free_callback(gpointer data, G_GNUC_UNUSED gpointer user_data) -{ - struct song *song = (struct song *)data; - - song_free(song); -} - -static void -despotify_playlist_close(struct playlist_provider *_playlist) -{ - struct despotify_playlist *ctx = (struct despotify_playlist *)_playlist; - - g_slist_foreach(ctx->list, track_free_callback, NULL); - g_slist_free(ctx->list); - - g_free(ctx); -} - - -static struct song * -despotify_playlist_read(struct playlist_provider *_playlist) -{ - struct despotify_playlist *ctx = (struct despotify_playlist *)_playlist; - struct song *out; - - if (!ctx->list) - return NULL; - - /* Remove the current track */ - out = ctx->list->data; - ctx->list = g_slist_remove(ctx->list, out); - - return out; -} - - -static const char *const despotify_schemes[] = { - "spt", - NULL -}; - -const struct playlist_plugin despotify_playlist_plugin = { - .name = "despotify", - - .init = despotify_playlist_init, - .finish = despotify_playlist_finish, - .open_uri = despotify_playlist_open_uri, - .read = despotify_playlist_read, - .close = despotify_playlist_close, - - .schemes = despotify_schemes, -}; |