]> git.sesse.net Git - vlc/blobdiff - modules/misc/audioscrobbler.c
vlc_plugin: fix non-LGPL plugins meta infos
[vlc] / modules / misc / audioscrobbler.c
index ef1a8e4d508ce95ccac0d9db5bceae98eeaecb90..81e2a8b66d501818a5bdeb62073ed8defe939f33 100644 (file)
 # include "config.h"
 #endif
 
+#include <assert.h>
 #include <time.h>
 
+#define VLC_MODULE_LICENSE VLC_LICENSE_GPL_2_PLUS
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_interface.h>
+#include <vlc_input.h>
 #include <vlc_dialog.h>
 #include <vlc_meta.h>
 #include <vlc_md5.h>
@@ -73,8 +76,10 @@ struct intf_sys_t
     audioscrobbler_song_t   p_queue[QUEUE_MAX]; /**< songs not submitted yet*/
     int                     i_songs;            /**< number of songs        */
 
+    input_thread_t         *p_input;            /**< current input thread   */
     vlc_mutex_t             lock;               /**< p_sys mutex            */
     vlc_cond_t              wait;               /**< song to submit event   */
+    vlc_thread_t            thread;             /**< thread to submit song  */
 
     /* submission of played songs */
     vlc_url_t               p_submit_url;       /**< where to submit data   */
@@ -95,16 +100,13 @@ struct intf_sys_t
 
     bool                    b_submit;           /**< do we have to submit ? */
 
-    bool                    b_state_cb;         /**< if we registered the
-                                                 * "state" callback         */
-
     bool                    b_meta_read;        /**< if we read the song's
                                                  * metadata already         */
 };
 
 static int  Open            (vlc_object_t *);
 static void Close           (vlc_object_t *);
-static void Run             (intf_thread_t *);
+static void *Run            (void *);
 
 /*****************************************************************************
  * Module descriptor
@@ -154,23 +156,15 @@ static void DeleteSong(audioscrobbler_song_t* p_song)
 /*****************************************************************************
  * ReadMetaData : Read meta data when parsed by vlc
  *****************************************************************************/
-static void ReadMetaData(intf_thread_t *p_this)
+static void ReadMetaData(intf_thread_t *p_this, input_thread_t *p_input)
 {
-    input_thread_t      *p_input;
-    input_item_t        *p_item;
-
-    intf_sys_t          *p_sys = p_this->p_sys;
+    intf_sys_t *p_sys = p_this->p_sys;
 
-    p_input = playlist_CurrentInput(pl_Get(p_this));
-    if (!p_input)
-        return;
+    assert(p_input != NULL);
 
-    p_item = input_GetItem(p_input);
-    if (!p_item)
-    {
-        vlc_object_release(p_input);
+    input_item_t *p_item = input_GetItem(p_input);
+    if (p_item == NULL)
         return;
-    }
 
 #define ALLOC_ITEM_META(a, b) do { \
         char *psz_meta = input_item_Get##b(p_item); \
@@ -221,7 +215,6 @@ static void ReadMetaData(intf_thread_t *p_this)
 
 end:
     vlc_mutex_unlock(&p_sys->lock);
-    vlc_object_release(p_input);
 }
 
 /*****************************************************************************
@@ -332,7 +325,7 @@ static int PlayingChange(vlc_object_t *p_this, const char *psz_var,
 
     if (!p_sys->b_meta_read && state >= PLAYING_S)
     {
-        ReadMetaData(p_intf);
+        ReadMetaData(p_intf, p_input);
         return VLC_SUCCESS;
     }
 
@@ -356,34 +349,33 @@ static int PlayingChange(vlc_object_t *p_this, const char *psz_var,
 static int ItemChange(vlc_object_t *p_this, const char *psz_var,
                        vlc_value_t oldval, vlc_value_t newval, void *p_data)
 {
-    input_thread_t      *p_input;
-    intf_thread_t       *p_intf     = (intf_thread_t*) p_data;
-    intf_sys_t          *p_sys      = p_intf->p_sys;
-    input_item_t        *p_item;
+    intf_thread_t  *p_intf  = p_data;
+    intf_sys_t     *p_sys   = p_intf->p_sys;
+    input_thread_t *p_input = newval.p_address;
 
     VLC_UNUSED(p_this); VLC_UNUSED(psz_var);
-    VLC_UNUSED(oldval); VLC_UNUSED(newval);
+    VLC_UNUSED(oldval);
 
-    p_sys->b_state_cb       = false;
     p_sys->b_meta_read      = false;
     p_sys->b_submit         = false;
 
-    p_input = playlist_CurrentInput(pl_Get(p_intf));
+    if (p_sys->p_input != NULL)
+    {
+        var_DelCallback(p_sys->p_input, "intf-event", PlayingChange, p_intf);
+        vlc_object_release(p_sys->p_input);
+        p_sys->p_input = NULL;
+    }
 
-    if (!p_input || p_input->b_dead)
+    if (p_input == NULL)
         return VLC_SUCCESS;
 
-    p_item = input_GetItem(p_input);
-    if (!p_item)
-    {
-        vlc_object_release(p_input);
+    input_item_t *p_item = input_GetItem(p_input);
+    if (p_item == NULL)
         return VLC_SUCCESS;
-    }
 
     if (var_CountChoices(p_input, "video-es"))
     {
         msg_Dbg(p_this, "Not an audio-only input, not submitting");
-        vlc_object_release(p_input);
         return VLC_SUCCESS;
     }
 
@@ -391,15 +383,14 @@ static int ItemChange(vlc_object_t *p_this, const char *psz_var,
     time(&p_sys->p_current_song.date);        /* to be sent to last.fm */
     p_sys->p_current_song.i_start = mdate();    /* only used locally */
 
+    p_sys->p_input = vlc_object_hold(p_input);
     var_AddCallback(p_input, "intf-event", PlayingChange, p_intf);
-    p_sys->b_state_cb = true;
 
     if (input_item_IsPreparsed(p_item))
-        ReadMetaData(p_intf);
+        ReadMetaData(p_intf, p_input);
     /* if the input item was not preparsed, we'll do it in PlayingChange()
      * callback, when "state" == PLAYING_S */
 
-    vlc_object_release(p_input);
     return VLC_SUCCESS;
 }
 
@@ -419,9 +410,15 @@ static int Open(vlc_object_t *p_this)
     vlc_mutex_init(&p_sys->lock);
     vlc_cond_init(&p_sys->wait);
 
-    var_AddCallback(pl_Get(p_intf), "item-current", ItemChange, p_intf);
+    if (vlc_clone(&p_sys->thread, Run, p_intf, VLC_THREAD_PRIORITY_LOW))
+    {
+        vlc_cond_destroy(&p_sys->wait);
+        vlc_mutex_destroy(&p_sys->lock);
+        free(p_sys);
+        return VLC_ENOMEM;
+    }
 
-    p_intf->pf_run = Run;
+    var_AddCallback(pl_Get(p_intf), "input-current", ItemChange, p_intf);
 
     return VLC_SUCCESS;
 }
@@ -431,19 +428,18 @@ static int Open(vlc_object_t *p_this)
  *****************************************************************************/
 static void Close(vlc_object_t *p_this)
 {
-    playlist_t                  *p_playlist = pl_Get(p_this);
-    input_thread_t              *p_input;
     intf_thread_t               *p_intf = (intf_thread_t*) p_this;
     intf_sys_t                  *p_sys  = p_intf->p_sys;
 
-    var_DelCallback(p_playlist, "item-current", ItemChange, p_intf);
+    vlc_cancel(p_sys->thread);
+    vlc_join(p_sys->thread, NULL);
+
+    var_DelCallback(pl_Get(p_intf), "input-current", ItemChange, p_intf);
 
-    p_input = playlist_CurrentInput(p_playlist);
-    if (p_input)
+    if (p_sys->p_input != NULL)
     {
-        if (p_sys->b_state_cb)
-            var_DelCallback(p_input, "intf-event", PlayingChange, p_intf);
-        vlc_object_release(p_input);
+        var_DelCallback(p_sys->p_input, "intf-event", PlayingChange, p_intf);
+        vlc_object_release(p_sys->p_input);
     }
 
     int i;
@@ -483,18 +479,10 @@ static int Handshake(intf_thread_t *p_this)
     intf_sys_t          *p_sys                  = p_this->p_sys;
 
     psz_username = var_InheritString(p_this, "lastfm-username");
-    if (!psz_username)
-        return VLC_ENOMEM;
-
     psz_password = var_InheritString(p_this, "lastfm-password");
-    if (!psz_password)
-    {
-        free(psz_username);
-        return VLC_ENOMEM;
-    }
 
     /* username or password have not been setup */
-    if (!*psz_username || !*psz_password)
+    if (EMPTY_STR(psz_username) || EMPTY_STR(psz_password))
     {
         free(psz_username);
         free(psz_password);
@@ -540,6 +528,7 @@ static int Handshake(intf_thread_t *p_this)
     psz_scrobbler_url = var_InheritString(p_this, "scrobbler-url");
     if (!psz_scrobbler_url)
     {
+        free(psz_auth_token);
         free(psz_username);
         return VLC_ENOMEM;
     }
@@ -548,6 +537,7 @@ static int Handshake(intf_thread_t *p_this)
     "http://%s/?hs=true&p=1.2&c="CLIENT_NAME"&v="CLIENT_VERSION"&u=%s&t=%s&a=%s"
     , psz_scrobbler_url, psz_username, psz_timestamp, psz_auth_token);
 
+    free(psz_auth_token);
     free(psz_scrobbler_url);
     free(psz_username);
     if (i_ret == -1)
@@ -684,15 +674,16 @@ static void HandleInterval(mtime_t *next, unsigned int *i_interval)
 /*****************************************************************************
  * Run : call Handshake() then submit songs
  *****************************************************************************/
-static void Run(intf_thread_t *p_intf)
+static void *Run(void *data)
 {
+    intf_thread_t          *p_intf = data;
     uint8_t                 p_buffer[1024];
     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)*/
+    mtime_t                 next_exchange = -1; /**< when can we send data  */
+    unsigned int            i_interval = 0;     /**< waiting interval (secs)*/
 
     intf_sys_t *p_sys = p_intf->p_sys;
 
@@ -718,7 +709,7 @@ static void Run(intf_thread_t *p_intf)
             switch(Handshake(p_intf))
             {
                 case VLC_ENOMEM:
-                    return;
+                    goto out;
 
                 case VLC_ENOVAR:
                     /* username not set */
@@ -726,12 +717,11 @@ static void Run(intf_thread_t *p_intf)
                         _("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;
+                        "Visit http://www.last.fm/join/ to get an account."));
+                    goto out;
 
                 case VLC_SUCCESS:
-                    msg_Dbg(p_intf, "Handshake successfull :)");
+                    msg_Dbg(p_intf, "Handshake successful :)");
                     b_handshaked = true;
                     i_interval = 0;
                     next_exchange = mdate();
@@ -739,7 +729,7 @@ static void Run(intf_thread_t *p_intf)
 
                 case VLC_AUDIOSCROBBLER_EFATAL:
                     msg_Warn(p_intf, "Exiting...");
-                    return;
+                    goto out;
 
                 case VLC_EGENERIC:
                 default:
@@ -755,7 +745,7 @@ static void Run(intf_thread_t *p_intf)
         msg_Dbg(p_intf, "Going to submit some data...");
         char *psz_submit;
         if (asprintf(&psz_submit, "s=%s", p_sys->psz_auth_token) == -1)
-            return;
+            break;
 
         /* forge the HTTP POST request */
         vlc_mutex_lock(&p_sys->lock);
@@ -786,7 +776,7 @@ static void Run(intf_thread_t *p_intf)
            ) == -1)
             {   /* Out of memory */
                 vlc_mutex_unlock(&p_sys->lock);
-                return;
+                goto out;
             }
             psz_submit_tmp = psz_submit;
             if (asprintf(&psz_submit, "%s%s",
@@ -795,7 +785,7 @@ static void Run(intf_thread_t *p_intf)
                 free(psz_submit_tmp);
                 free(psz_submit_song);
                 vlc_mutex_unlock(&p_sys->lock);
-                return;
+                goto out;
             }
             free(psz_submit_song);
             free(psz_submit_tmp);
@@ -883,5 +873,7 @@ static void Run(intf_thread_t *p_intf)
             HandleInterval(&next_exchange, &i_interval);
         }
     }
+out:
     vlc_restorecancel(canc);
+    return NULL;
 }