Patch updated, thanks for your remark !<br><br><div class="gmail_quote">On Sun, Mar 11, 2012 at 12:05 PM,  <span dir="ltr"><<a href="mailto:samuel.pitoiset@gmail.com">samuel.pitoiset@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

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