playlist/lastfm: remove defunct Last.fm support
This plugin has been defunct ever since Last.fm changed their protocol. Since there is no volunteer willing to fix the plugin, I'm removing it now.
This commit is contained in:
parent
ccd7f0825a
commit
a446775d80
|
@ -947,12 +947,6 @@ PLAYLIST_LIBS = \
|
|||
libplaylist_plugins.a \
|
||||
$(FLAC_LIBS)
|
||||
|
||||
if ENABLE_LASTFM
|
||||
libplaylist_plugins_a_SOURCES += \
|
||||
src/playlist/LastFMPlaylistPlugin.cxx \
|
||||
src/playlist/LastFMPlaylistPlugin.hxx
|
||||
endif
|
||||
|
||||
if ENABLE_DESPOTIFY
|
||||
libplaylist_plugins_a_SOURCES += \
|
||||
src/playlist/DespotifyPlaylistPlugin.cxx \
|
||||
|
|
4
NEWS
4
NEWS
|
@ -4,9 +4,11 @@ ver 0.18 (2012/??/??)
|
|||
* protocol:
|
||||
- new command "toggleoutput"
|
||||
- search for album artist falls back to the artist tag
|
||||
* innput:
|
||||
* input:
|
||||
- curl: enable https
|
||||
- soup: plugin removed
|
||||
* playlist:
|
||||
- lastfm: remove defunct Last.fm support
|
||||
* decoder:
|
||||
- adplug: new decoder plugin using libadplug
|
||||
- ffmpeg: drop support for pre-0.8 ffmpeg
|
||||
|
|
16
configure.ac
16
configure.ac
|
@ -265,11 +265,6 @@ AC_ARG_ENABLE(jack,
|
|||
|
||||
AC_SYS_LARGEFILE
|
||||
|
||||
AC_ARG_ENABLE(lastfm,
|
||||
AS_HELP_STRING([--enable-lastfm],
|
||||
[enable support for last.fm radio (default: disable)]),,
|
||||
[enable_lastfm=no])
|
||||
|
||||
AC_ARG_ENABLE(despotify,
|
||||
AS_HELP_STRING([--enable-despotify],
|
||||
[enable support for despotify (default: disable)]),,
|
||||
|
@ -714,16 +709,6 @@ if test x$enable_curl = xyes; then
|
|||
fi
|
||||
AM_CONDITIONAL(ENABLE_CURL, test x$enable_curl = xyes)
|
||||
|
||||
dnl --------------------------------- Last.FM ---------------------------------
|
||||
if test x$enable_lastfm = xyes; then
|
||||
if test x$enable_curl != xyes; then
|
||||
AC_MSG_ERROR([Cannot enable last.fm radio without curl])
|
||||
fi
|
||||
|
||||
AC_DEFINE(ENABLE_LASTFM, 1, [Define when last.fm radio is enabled])
|
||||
fi
|
||||
AM_CONDITIONAL(ENABLE_LASTFM, test x$enable_lastfm = xyes)
|
||||
|
||||
dnl --------------------------------- Despotify ---------------------------------
|
||||
MPD_AUTO_PKG(despotify, DESPOTIFY, [despotify],
|
||||
[Despotify support], [despotify not found])
|
||||
|
@ -1646,7 +1631,6 @@ printf '\nStreaming support:\n\t'
|
|||
results(cdio_paranoia, [CDIO_PARANOIA])
|
||||
results(curl,[CURL])
|
||||
results(despotify,[Despotify])
|
||||
results(lastfm,[Last.FM])
|
||||
results(soundcloud,[Soundcloud])
|
||||
printf '\n\t'
|
||||
results(mms,[MMS])
|
||||
|
|
41
doc/user.xml
41
doc/user.xml
|
@ -220,7 +220,7 @@ systemctl start mpd.socket</programlisting>
|
|||
</para>
|
||||
|
||||
<programlisting>input {
|
||||
plugin "lastfm"
|
||||
plugin "despotify"
|
||||
user "foo"
|
||||
password "bar"
|
||||
}
|
||||
|
@ -1943,45 +1943,6 @@ systemctl start mpd.socket</programlisting>
|
|||
<section>
|
||||
<title>Playlist plugins</title>
|
||||
|
||||
<section>
|
||||
<title><varname>lastfm</varname></title>
|
||||
|
||||
<para>
|
||||
Plays last.fm radio.
|
||||
</para>
|
||||
|
||||
<informaltable>
|
||||
<tgroup cols="2">
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Setting</entry>
|
||||
<entry>Description</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>
|
||||
<varname>user</varname>
|
||||
<parameter>USERNAME</parameter>
|
||||
</entry>
|
||||
<entry>
|
||||
The last.fm user name.
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>
|
||||
<varname>password</varname>
|
||||
<parameter>PWD</parameter>
|
||||
</entry>
|
||||
<entry>
|
||||
The last.fm password.
|
||||
</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title><varname>embcue</varname></title>
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "playlist/ExtM3uPlaylistPlugin.hxx"
|
||||
#include "playlist/M3uPlaylistPlugin.hxx"
|
||||
#include "playlist/XspfPlaylistPlugin.hxx"
|
||||
#include "playlist/LastFMPlaylistPlugin.hxx"
|
||||
#include "playlist/DespotifyPlaylistPlugin.hxx"
|
||||
#include "playlist/SoundCloudPlaylistPlugin.hxx"
|
||||
#include "playlist/PlsPlaylistPlugin.hxx"
|
||||
|
@ -53,9 +52,6 @@ const struct playlist_plugin *const playlist_plugins[] = {
|
|||
#ifdef ENABLE_DESPOTIFY
|
||||
&despotify_playlist_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_LASTFM
|
||||
&lastfm_playlist_plugin,
|
||||
#endif
|
||||
#ifdef ENABLE_SOUNDCLOUD
|
||||
&soundcloud_playlist_plugin,
|
||||
#endif
|
||||
|
|
|
@ -1,281 +0,0 @@
|
|||
/*
|
||||
* 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 "LastFMPlaylistPlugin.hxx"
|
||||
#include "PlaylistPlugin.hxx"
|
||||
#include "PlaylistRegistry.hxx"
|
||||
#include "SongEnumerator.hxx"
|
||||
#include "ConfigData.hxx"
|
||||
#include "Song.hxx"
|
||||
#include "InputStream.hxx"
|
||||
#include "util/Error.hxx"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
class LastfmPlaylist final : public SongEnumerator {
|
||||
struct input_stream *is;
|
||||
|
||||
SongEnumerator *const xspf;
|
||||
|
||||
public:
|
||||
LastfmPlaylist(input_stream *_is, SongEnumerator *_xspf)
|
||||
:is(_is), xspf(_xspf) {
|
||||
}
|
||||
|
||||
virtual ~LastfmPlaylist() {
|
||||
delete xspf;
|
||||
is->Close();
|
||||
}
|
||||
|
||||
virtual Song *NextSong() override {
|
||||
return xspf->NextSong();
|
||||
}
|
||||
};
|
||||
|
||||
static struct {
|
||||
char *user;
|
||||
char *md5;
|
||||
} lastfm_config;
|
||||
|
||||
static bool
|
||||
lastfm_init(const config_param ¶m)
|
||||
{
|
||||
const char *user = param.GetBlockValue("user");
|
||||
const char *passwd = param.GetBlockValue("password");
|
||||
|
||||
if (user == NULL || passwd == NULL) {
|
||||
g_debug("disabling the last.fm playlist plugin "
|
||||
"because account is not configured");
|
||||
return false;
|
||||
}
|
||||
|
||||
lastfm_config.user = g_uri_escape_string(user, NULL, false);
|
||||
|
||||
if (strlen(passwd) != 32)
|
||||
lastfm_config.md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5,
|
||||
passwd, strlen(passwd));
|
||||
else
|
||||
lastfm_config.md5 = g_strdup(passwd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
lastfm_finish(void)
|
||||
{
|
||||
g_free(lastfm_config.user);
|
||||
g_free(lastfm_config.md5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple data fetcher.
|
||||
* @param url path or url of data to fetch.
|
||||
* @return data fetched, or NULL on error. Must be freed with g_free.
|
||||
*/
|
||||
static char *
|
||||
lastfm_get(const char *url, Mutex &mutex, Cond &cond)
|
||||
{
|
||||
struct input_stream *input_stream;
|
||||
Error error;
|
||||
char buffer[4096];
|
||||
size_t length = 0;
|
||||
|
||||
input_stream = input_stream::Open(url, mutex, cond, error);
|
||||
if (input_stream == NULL) {
|
||||
if (error.IsDefined())
|
||||
g_warning("%s", error.GetMessage());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
|
||||
input_stream->WaitReady();
|
||||
|
||||
do {
|
||||
size_t nbytes =
|
||||
input_stream->Read(buffer + length,
|
||||
sizeof(buffer) - length, error);
|
||||
if (nbytes == 0) {
|
||||
if (error.IsDefined())
|
||||
g_warning("%s", error.GetMessage());
|
||||
|
||||
if (input_stream->IsEOF())
|
||||
break;
|
||||
|
||||
/* I/O error */
|
||||
mutex.unlock();
|
||||
input_stream->Close();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length += nbytes;
|
||||
} while (length < sizeof(buffer));
|
||||
|
||||
mutex.unlock();
|
||||
|
||||
input_stream->Close();
|
||||
return g_strndup(buffer, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ini-style value fetcher.
|
||||
* @param response data through which to search.
|
||||
* @param name name of value to search for.
|
||||
* @return value for param name in param response or NULL on error. Free with g_free.
|
||||
*/
|
||||
static char *
|
||||
lastfm_find(const char *response, const char *name)
|
||||
{
|
||||
size_t name_length = strlen(name);
|
||||
|
||||
while (true) {
|
||||
const char *eol = strchr(response, '\n');
|
||||
if (eol == NULL)
|
||||
return NULL;
|
||||
|
||||
if (strncmp(response, name, name_length) == 0 &&
|
||||
response[name_length] == '=') {
|
||||
response += name_length + 1;
|
||||
return g_strndup(response, eol - response);
|
||||
}
|
||||
|
||||
response = eol + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static SongEnumerator *
|
||||
lastfm_open_uri(const char *uri, Mutex &mutex, Cond &cond)
|
||||
{
|
||||
char *p, *q, *response, *session;
|
||||
|
||||
/* handshake */
|
||||
|
||||
p = g_strconcat("http://ws.audioscrobbler.com/radio/handshake.php?"
|
||||
"version=1.1.1&platform=linux&"
|
||||
"username=", lastfm_config.user, "&"
|
||||
"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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
Error error;
|
||||
const auto is = input_stream::Open(p, mutex, cond, error);
|
||||
g_free(p);
|
||||
|
||||
if (is == nullptr) {
|
||||
if (error.IsDefined())
|
||||
g_warning("Failed to load XSPF playlist: %s",
|
||||
error.GetMessage());
|
||||
else
|
||||
g_warning("Failed to load XSPF playlist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mutex.lock();
|
||||
|
||||
is->WaitReady();
|
||||
|
||||
/* last.fm does not send a MIME type, we have to fake it here
|
||||
:-( */
|
||||
is->OverrideMimeType("application/xspf+xml");
|
||||
|
||||
mutex.unlock();
|
||||
|
||||
/* parse the XSPF playlist */
|
||||
|
||||
const auto xspf = playlist_list_open_stream(is, nullptr);
|
||||
if (xspf == nullptr) {
|
||||
is->Close();
|
||||
g_warning("Failed to parse XSPF playlist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* create the playlist object */
|
||||
|
||||
return new LastfmPlaylist(is, xspf);
|
||||
}
|
||||
|
||||
static const char *const lastfm_schemes[] = {
|
||||
"lastfm",
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct playlist_plugin lastfm_playlist_plugin = {
|
||||
"lastfm",
|
||||
|
||||
lastfm_init,
|
||||
lastfm_finish,
|
||||
lastfm_open_uri,
|
||||
nullptr,
|
||||
|
||||
lastfm_schemes,
|
||||
nullptr,
|
||||
nullptr,
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* 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_LASTFM_PLAYLIST_PLUGIN_HXX
|
||||
#define MPD_LASTFM_PLAYLIST_PLUGIN_HXX
|
||||
|
||||
extern const struct playlist_plugin lastfm_playlist_plugin;
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue