[vlc-devel] [PATCH 2/3] Audioscrobbler: Update the scrobbling protocol to the version 2.0.
Samuel Pitoiset
samuel.pitoiset at gmail.com
Sun Mar 11 12:09:49 CET 2012
Patch updated, thanks for your remark !
On Sun, Mar 11, 2012 at 12:05 PM, <samuel.pitoiset at gmail.com> wrote:
> From: Samuel Pitoiset <samuel.pitoiset at gmail.com>
>
> ---
> modules/misc/audioscrobbler.c | 268
> +++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 268 insertions(+)
>
> diff --git a/modules/misc/audioscrobbler.c b/modules/misc/audioscrobbler.c
> index 0da533e..28d5a80 100644
> --- a/modules/misc/audioscrobbler.c
> +++ b/modules/misc/audioscrobbler.c
> @@ -1154,6 +1154,274 @@ static void HandleInterval(mtime_t *next, unsigned
> int *i_interval)
> }
>
>
> /*****************************************************************************
> + * Scrobble : scrobble songs
> +
> *****************************************************************************/
> +static int Scrobble(intf_thread_t *p_this)
> +{
> + intf_sys_t *p_sys = p_this->p_sys;
> + xml_reader_t *p_xml_reader = NULL;
> + vlc_array_t p_params;
> + stream_t *p_stream;
> + uint8_t p_buf[1024];
> + char *psz_request;
> + int i_song;
> +
> + vlc_array_init(&p_params);
> +
> + vlc_mutex_lock(&p_sys->lock);
> + for (i_song = 0 ; i_song < p_sys->i_songs ; i_song++)
> + {
> + audioscrobbler_song_t *p_song = &p_sys->p_queue[i_song];
> + char psz_key[1024], psz_val[1024];
> +
> + /* album */
> + sprintf(psz_key, "album[%d]", i_song);
> + snprintf(psz_val, 1024, "%s", p_song->psz_b);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* artist */
> + sprintf(psz_key, "artist[%d]", i_song);
> + snprintf(psz_val, 1024, "%s", p_song->psz_a);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* track */
> + sprintf(psz_key, "track[%d]", i_song);
> + snprintf(psz_val, 1024, "%s", p_song->psz_t);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* timestamp */
> + sprintf(psz_key, "timestamp[%d]", i_song);
> + sprintf(psz_val, "%u", (unsigned)p_song->date);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* duration */
> + sprintf(psz_key, "duration[%d]", i_song);
> + sprintf(psz_val, "%d", p_song->i_l);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* track number */
> + sprintf(psz_key, "trackNumber[%d]", i_song);
> + snprintf(psz_val, 1024, "%s", p_song->psz_n);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> +
> + /* MusicBrainz track ID */
> + sprintf(psz_key, "mbid[%d]", i_song);
> + snprintf(psz_val, 1024, "%s", p_song->psz_m);
> + AddParam(&p_params, strdup(psz_key), strdup(psz_val));
> + }
> + vlc_mutex_unlock(&p_sys->lock);
> +
> + /* add the method name to the parameters list */
> + AddParam(&p_params, "method", "track.scrobble");
> +
> + /* build the HTTP request */
> + psz_request = BuildSignedRequest(p_this, &p_params, POST);
> + vlc_array_clear(&p_params);
> +
> + if (!psz_request)
> + return VLC_ENOMEM;
> +
> + /* initialize the connection */
> + int i_sock = net_ConnectTCP(p_this, p_sys->p_submit_url.psz_host, 80);
> + if (i_sock == -1)
> + {
> + free(psz_request);
> + return VLC_EGENERIC;
> + }
> +
> + /* transmit the request */
> + int i_net_ret = net_Printf(p_this, i_sock, NULL, "%s", psz_request);
> + free(psz_request);
> +
> + if (i_net_ret == -1)
> + goto proto;
> +
> + /* read the answer */
> + int i_read = net_Read(p_this, i_sock, NULL, p_buf, sizeof(p_buf) - 1,
> false);
> + if (i_read <= 0)
> + goto proto;
> +
> + /* close the connection */
> + net_Close(i_sock);
> + p_buf[i_read] = '\0';
> +
> + /* remove answer headers */
> + char *psz_xml = strstr((const char*) p_buf, "<?xml");
> + if (!psz_xml)
> + goto proto;
> +
> + /* create a stream reading answer */
> + p_stream = stream_MemoryNew(p_this, (uint8_t*) psz_xml,
> strlen(psz_xml), true);
> + if (!p_stream)
> + goto proto;
> +
> + /* create an XML reader */
> + p_xml_reader = xml_ReaderCreate(p_this, p_stream);
> + if (!p_xml_reader)
> + goto proto;
> +
> + /* check root node */
> + const char *node;
> + if (xml_ReaderNextNode(p_xml_reader, &node) != XML_READER_STARTELEM)
> + {
> + msg_Err(p_this, "invalid file (no root node)");
> + goto proto;
> + }
> +
> + if (strcasecmp(node, "lfm"))
> + {
> + msg_Err(p_this, "invalid root node <%s>", node);
> + goto proto;
> + }
> +
> + /* check response status */
> + const char *attr, *value;
> + if ((attr = xml_ReaderNextAttr(p_xml_reader, &value)))
> + {
> + if (strcasecmp(attr, "status"))
> + {
> + msg_Err(p_this, "invalid attribute \"%s\"", attr);
> + goto proto;
> + }
> +
> + if (strcasecmp(value, "ok"))
> + {
> + /* an error occured */
> + if (!strcasecmp(value, "4"))
> + {
> + /* authentication failed, bad username/password
> combination */
> + msg_Err(p_this, "last.fm username or password is
> incorrect.");
> + }
> +
> + if (!strcasecmp(value, "10"))
> + {
> + /* invalid API key */
> + msg_Err(p_this, "You must be granted a valid key by
> last.fm");
> + }
> +
> + if (!strcasecmp(value, "26"))
> + {
> + /* suspend API key */
> + msg_Err(p_this, "Access for your account has been
> suspended.");
> + }
> +
> + goto proto;
> + }
> + }
> +
> + stream_Delete(p_stream);
> + xml_ReaderDelete(p_xml_reader);
> +
> + return VLC_SUCCESS;
> +
> +proto:
> + net_Close(i_sock);
> + if (p_stream)
> + stream_Delete(p_stream);
> + if (p_xml_reader)
> + xml_ReaderDelete(p_xml_reader);
> +
> + return VLC_EGENERIC;
> +}
> +
>
> +/*****************************************************************************
> + * Run : call Handshake() then submit songs
> +
> *****************************************************************************/
> +static void NewRun(intf_thread_t *p_this)
> +{
> + int canc = vlc_savecancel();
> + bool b_handshaked = false;
> +
> + /* data about audioscrobbler session */
> + mtime_t next_exchange; /**< when can we send
> data */
> + unsigned int i_interval; /**< waiting interval
> (secs)*/
> +
> + intf_sys_t *p_sys = p_this->p_sys;
> +
> + /* main loop */
> + for (;;)
> + {
> + vlc_restorecancel(canc);
> + vlc_mutex_lock(&p_sys->lock);
> + mutex_cleanup_push(&p_sys->lock);
> +
> + do
> + vlc_cond_wait(&p_sys->wait, &p_sys->lock);
> + while (mdate() < next_exchange);
> +
> + vlc_cleanup_run();
> + canc = vlc_savecancel();
> +
> + /* handshake if needed */
> + if (!b_handshaked)
> + {
> + msg_Dbg(p_this, "Handshaking with last.fm ...");
> +
> + switch(Handshake(p_this))
> + {
> + case VLC_ENOMEM:
> + return;
> +
> + case VLC_ENOVAR:
> + /* username not set */
> + dialog_Fatal(p_this,
> + _("Last.fm username not set"),
> + "%s", _("Please set a username or disable the "
> + "audioscrobbler plugin, and restart VLC.\n"
> + "Visit http://www.last.fm/join/ to get an
> account.")
> + );
> + return;
> +
> + case VLC_SUCCESS:
> + msg_Dbg(p_this, "Handshake successfull :)");
> + b_handshaked = true;
> + i_interval = 0;
> + next_exchange = mdate();
> + break;
> +
> + case VLC_AUDIOSCROBBLER_EFATAL:
> + msg_Warn(p_this, "Exiting...");
> + return;
> +
> + case VLC_EGENERIC:
> + default:
> + /* protocol error : we'll try later */
> + HandleInterval(&next_exchange, &i_interval);
> + break;
> + }
> + /* if handshake failed let's restart the loop */
> + if (!b_handshaked)
> + continue;
> + }
> +
> + msg_Dbg(p_this, "Going to submit some data...");
> +
> + switch (Scrobble(p_this))
> + {
> + case VLC_SUCCESS:
> + /* submission successful */
> + for (int i = 0; i < p_sys->i_songs; i++)
> + DeleteSong(&p_sys->p_queue[i]);
> + p_sys->i_songs = 0;
> + i_interval = 0;
> + next_exchange = mdate();
> + msg_Dbg(p_this, "Submission successful!");
> + break;
> + case VLC_EGENERIC:
> + /* protocol error : we'll try later */
> + HandleInterval(&next_exchange, &i_interval);
> + b_handshaked = false;
> + break;
> + case VLC_ENOMEM:
> + default:
> + return;
> + break;
> + }
> + }
> + vlc_restorecancel(canc);
> +}
> +
>
> +/*****************************************************************************
> * Run : call Handshake() then submit songs
>
> *****************************************************************************/
> static void Run(intf_thread_t *p_intf)
> --
> 1.7.9.3
>
>
--
Best regards,
Samuel Pitoiset.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20120311/caabc1bb/attachment.html>
More information about the vlc-devel
mailing list