[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