[vlc-devel] [PATCH] Add module to submit listens to ListenBrainz

Kartik Ohri kartikohri13 at gmail.com
Sun Mar 8 18:19:21 CET 2020


Hi, The reply to option is now working properly for me. I ended mailing up
the fixed patch as a new one twice. I could try sending as a reply again
but I do not want to spam the list in case it doesn't work out. Can you
check out this email
https://mailman.videolan.org/pipermail/vlc-devel/2020-March/131919.html instead
and continue further discussion in it or should I try to send as a reply
again here?

On Sat, Mar 7, 2020 at 1:17 PM Kartik Ohri <kartikohri13 at gmail.com> wrote:

> On Wed, Mar 4, 2020 at 2:19 AM Thomas Guillem <thomas at gllm.fr> wrote:
>
>>
>>
>> On Tue, Mar 3, 2020, at 20:05, Kartik Ohri kartikohri13 at gmail.com wrote:
>> > VLC already has the audioscrobbler module to submit scrobbles to
>> > last.fm and other services with a similar API. This module extends
>> > that functionality to allow submission of listens to ListenBrainz.
>> > The existing audioscrobbler module is incompatible with ListenBrainz
>> > due to difference in authentication procedures and REST API for
>> > submissions.
>> >
>> > The term scrobble is a trademarked term by Last.fm, therefore the
>> > term listen used instead. More information about ListenBrainz is
>> > available at listenbrainz [dot] org.
>>
>> Hello,
>> Thanks a lot for this rewrite.
>> cf. my coments below:
>>
>> > ---
>> >  modules/misc/Makefile.am    |   4 +
>> >  modules/misc/listenbrainz.c | 537 ++++++++++++++++++++++++++++++++++++
>> >  2 files changed, 541 insertions(+)
>> >  create mode 100755 modules/misc/listenbrainz.c
>> >
>> > diff --git a/modules/misc/Makefile.am b/modules/misc/Makefile.am
>> > index 78f9b09710..ed3ef24ee6 100644
>> > --- a/modules/misc/Makefile.am
>> > +++ b/modules/misc/Makefile.am
>> > @@ -8,6 +8,10 @@ libaudioscrobbler_plugin_la_SOURCES =
>> misc/audioscrobbler.c
>> >  libaudioscrobbler_plugin_la_LIBADD = $(SOCKET_LIBS)
>> >  misc_LTLIBRARIES += libaudioscrobbler_plugin.la
>> >
>> > +liblistenbrainz_plugin_la_SOURCES = misc/listenbrainz.c
>> > +liblistenbrainz_plugin_la_LIBADD = $(SOCKET_LIBS)
>> > +misc_LTLIBRARIES += liblistenbrainz_plugin.la
>> > +
>> >  libexport_plugin_la_SOURCES = \
>> >       misc/playlist/html.c \
>> >       misc/playlist/m3u.c \
>> > diff --git a/modules/misc/listenbrainz.c b/modules/misc/listenbrainz.c
>> > new file mode 100755
>> > index 0000000000..a000bcc6ac
>> > --- /dev/null
>> > +++ b/modules/misc/listenbrainz.c
>> > @@ -0,0 +1,537 @@
>> >
>> +/*****************************************************************************
>> > + * listenbrainz.c : ListenBrainz submission plugin
>> > + * ListenBrainz Submit Listens API 1
>> > + * https://api.listenbrainz.org/1/submit-listens
>>
>> Missing license header, you can take it from any LGPL file.
>>
>> > +
>> >
>> *****************************************************************************
>> > + * Author: Kartik Ohri <kartikohri13 at gmail dot com>
>> > +
>> >
>> *****************************************************************************/
>> > +
>> > +#ifdef HAVE_CONFIG_H
>> > +# include "config.h"
>> > +#endif
>> > +
>> > +#include <assert.h>
>> > +#include <time.h>
>> > +
>> > +#include <vlc_common.h>
>> > +#include <vlc_plugin.h>
>> > +#include <vlc_interface.h>
>> > +#include <vlc_input_item.h>
>> > +#include <vlc_dialog.h>
>> > +#include <vlc_meta.h>
>> > +#include <vlc_memstream.h>
>> > +#include <vlc_stream.h>
>> > +#include <vlc_url.h>
>> > +#include <vlc_tls.h>
>> > +#include <vlc_player.h>
>> > +#include <vlc_playlist.h>
>> > +
>> > +#define CAPACITY 50
>>
>> use vlc_vector instead of limiting the capacity.
>>
>> > +
>> > +typedef struct listen_t
>> > +{
>> > +    char *psz_artist;
>> > +    char *psz_title;
>> > +    char *psz_album;
>> > +    char *psz_track_number;
>> > +    int i_length;
>> > +    char *psz_musicbrainz_id;
>> > +    time_t date;
>> > +    vlc_tick_t time_start;
>> > +} listen_t;
>> > +
>> > +struct intf_sys_t
>> > +{
>> > +
>> stray line
>> > +    listen_t p_queue[CAPACITY];
>> > +    int i_songs;                    // number of songs
>> > +
>> > +    vlc_playlist_t *playlist;
>> > +    struct vlc_playlist_listener_id *playlist_listener;
>> > +    struct vlc_player_listener_id *player_listener;
>> > +
>> > +    vlc_mutex_t lock;
>> > +    vlc_cond_t wait;                // song to submit event
>> > +    vlc_thread_t thread;            // thread to submit song
>> > +
>> > +    vlc_url_t p_submit_url;         // where to submit data
>> > +    char *psz_user_token;           // authentication token
>> > +
>> > +
>> stray line
>>
>> > +    listen_t p_current_song;
>> > +    bool b_meta_read;               // check if song metadata is
>> > already read
>> > +
>> > +    vlc_tick_t time_pause;          // time when vlc paused
>> > +    vlc_tick_t time_total_pauses;   // total time in pause
>> > +
>> > +};
>> > +
>> > +static int Open (vlc_object_t *);
>> > +static void Close (vlc_object_t *);
>> > +static void *Run (void *);
>> > +
>> > +#define USER_TOKEN_TEXT      N_("User token")
>> > +#define USER_TOKEN_LONGTEXT  N_("The user token of your ListenBrainz
>> > account")
>> > +#define URL_TEXT             N_("Submission URL")
>> > +#define URL_LONGTEXT         N_("The URL set for an alternative
>> > ListenBrainz instance")
>> > +
>> >
>> +/****************************************************************************
>> > + * Module descriptor
>> > +
>> >
>> ****************************************************************************/
>> > +
>> > +vlc_module_begin ()
>> > +    set_category(CAT_INTERFACE)
>> > +    set_subcategory(SUBCAT_INTERFACE_CONTROL)
>> > +    set_shortname (N_ ("ListenBrainz"))
>> > +    set_description (N_ ("Submit listens to ListenBrainz"))
>> > +    add_string("listenbrainz_user_token", "", USER_TOKEN_TEXT,
>> > USER_TOKEN_LONGTEXT, false)
>> > +    add_string("listenbrainz_submission_url", "api.listenbrainz.org",
>> > URL_TEXT, URL_LONGTEXT, false)
>>
>> options name use generally '-' instead of '_'.
>>
>> > +    set_capability("interface", 0)
>> > +    set_callbacks(Open, Close)
>> > +vlc_module_end ()
>> > +
>> > +static void DeleteSong (listen_t *p_song)
>> > +{
>> > +    p_song->psz_artist = NULL;
>> > +    p_song->psz_album = NULL;
>> > +    p_song->psz_title = NULL;
>> > +    p_song->psz_musicbrainz_id = NULL;
>> > +    p_song->psz_track_number = NULL;
>>
>> You are missing some free here.
>> RETRIEVE_METADATA return an allocated str.
>>
>> > +}
>> > +
>> > +static void ReadMetaData (intf_thread_t *p_this)
>> > +{
>> > +    bool b_skip = 0;
>> > +    intf_sys_t *p_sys = p_this->p_sys;
>> > +
>> > +    vlc_player_t *player = vlc_playlist_GetPlayer (p_sys->playlist);
>> > +    input_item_t *item = vlc_player_GetCurrentMedia (player);
>> > +    if ( item == NULL )
>> > +        return;
>> > +
>> > +    vlc_mutex_lock (&p_sys->lock);
>> > +
>> > +    p_sys->b_meta_read = true;
>> > +
>> > +#define RETRIEVE_METADATA(a, b) do { \
>> > +        char *psz_data = input_item_Get##b(item); \
>> > +        if (psz_data && *psz_data) \
>> > +            a = vlc_uri_encode(psz_data); \
>> > +        free(psz_data); \
>> > +    } while (0)
>> > +
>> > +    RETRIEVE_METADATA(p_sys->p_current_song.psz_artist, Artist);
>> > +    if ( !p_sys->p_current_song.psz_artist )
>> > +    {
>> > +        msg_Dbg (p_this, "Artist missing.");
>> > +        DeleteSong (&p_sys->p_current_song);
>> > +        b_skip = 1;
>> > +    }
>> > +
>> > +    RETRIEVE_METADATA(p_sys->p_current_song.psz_title, Title);
>> > +    if ( b_skip || !p_sys->p_current_song.psz_title )
>> > +    {
>> > +        msg_Dbg (p_this, "Track name missing.");
>> > +        DeleteSong (&p_sys->p_current_song);
>> > +        b_skip = 1;
>> > +    }
>> > +
>> > +    if ( !b_skip )
>> > +    {
>> > +        RETRIEVE_METADATA(p_sys->p_current_song.psz_album, Album);
>> > +        RETRIEVE_METADATA(p_sys->p_current_song.psz_musicbrainz_id,
>> > TrackID);
>> > +        RETRIEVE_METADATA(p_sys->p_current_song.psz_track_number,
>> > TrackNum);
>> > +        p_sys->p_current_song.i_length = SEC_FROM_VLC_TICK
>> > (input_item_GetDuration (item));
>> > +        msg_Dbg (p_this, "Meta data registered");
>> > +        vlc_cond_signal (&p_sys->wait);
>> > +    }
>> > +    vlc_mutex_unlock (&p_sys->lock);
>> > +
>> > +#undef RETRIEVE_METADATA
>> > +
>> > +}
>> > +
>> > +static void Enqueue (intf_thread_t *p_this)
>> > +{
>> > +    bool b_skip = 0;
>> > +    int64_t i_played_time;
>> > +    intf_sys_t *p_sys = p_this->p_sys;
>> > +
>> > +    vlc_mutex_lock (&p_sys->lock);
>> > +
>> > +    if ( !p_sys->p_current_song.psz_artist ||
>> > !*p_sys->p_current_song.psz_artist ||
>> > +         !p_sys->p_current_song.psz_title ||
>> > !*p_sys->p_current_song.psz_title )
>> > +    {
>> > +        msg_Dbg (p_this, "Missing artist or title, not submitting");
>> > +        b_skip = 1;
>> > +    }
>> > +
>> > +    i_played_time = SEC_FROM_VLC_TICK (vlc_tick_now () -
>> > p_sys->p_current_song.time_start - p_sys->time_total_pauses);
>> > +
>> > +    if ( p_sys->p_current_song.i_length == 0 )
>> > +        p_sys->p_current_song.i_length = i_played_time;
>> > +
>> > +    if ( !b_skip && i_played_time < 30 )
>> > +    {
>> > +        msg_Dbg (p_this, "Song not listened long enough, not
>> > submitting");
>> > +        b_skip = 1;
>> > +    }
>> > +
>> > +    if ( !b_skip && p_sys->i_songs >= CAPACITY )
>> > +    {
>> > +        msg_Warn (p_this, "Submission queue is full, not submitting");
>> > +        b_skip = 1;
>> > +    }
>> > +
>> > +    if ( !b_skip )
>> > +    {
>> > +        msg_Dbg (p_this, "Song will be submitted.");
>> > +
>> > +        p_sys->p_queue[p_sys->i_songs].psz_artist =
>> > p_sys->p_current_song.psz_artist;
>> > +        p_sys->p_queue[p_sys->i_songs].psz_title =
>> > p_sys->p_current_song.psz_title;
>> > +        p_sys->p_queue[p_sys->i_songs].psz_album =
>> > p_sys->p_current_song.psz_album;
>> > +        p_sys->p_queue[p_sys->i_songs].psz_musicbrainz_id =
>> > p_sys->p_current_song.psz_musicbrainz_id;
>> > +        p_sys->p_queue[p_sys->i_songs].psz_track_number =
>> > p_sys->p_current_song.psz_track_number;
>> > +        p_sys->p_queue[p_sys->i_songs].i_length =
>> > p_sys->p_current_song.i_length;
>> > +        p_sys->p_queue[p_sys->i_songs].date =
>> > p_sys->p_current_song.date;
>> > +
>> > +        p_sys->i_songs++;
>> > +    }
>> > +
>> > +    vlc_cond_signal (&p_sys->wait);
>> > +    DeleteSong (&p_sys->p_current_song);
>> > +    vlc_mutex_unlock (&p_sys->lock);
>> > +}
>> > +
>> > +static void PlayerStateChanged (vlc_player_t *player, enum
>> > vlc_player_state state, void *data)
>> > +{
>> > +    intf_thread_t *intf = data;
>> > +    intf_sys_t *p_sys = intf->p_sys;
>> > +
>> > +    if ( vlc_player_GetVideoTrackCount (player) )
>> > +    {
>> > +        msg_Dbg (intf, "Not an audio-only input, not submitting");
>> > +        return;
>> > +    }
>> > +
>> > +    if ( !p_sys->b_meta_read && state >= VLC_PLAYER_STATE_PLAYING )
>> > +    {
>> > +        ReadMetaData (intf);
>> > +        return;
>> > +    }
>> > +
>> > +    switch (state)
>> > +    {
>> > +        case VLC_PLAYER_STATE_STOPPED:
>> > +            Enqueue (intf);
>> > +            break;
>> > +        case VLC_PLAYER_STATE_PAUSED:
>> > +            p_sys->time_pause = vlc_tick_now ();
>> > +            break;
>> > +        case VLC_PLAYER_STATE_PLAYING:
>> > +            if ( p_sys->time_pause > 0 )
>> > +            {
>> > +                vlc_tick_t time_current = vlc_tick_now ();
>> > +                vlc_tick_t time_paused = time_current -
>> > p_sys->time_pause;
>> > +                p_sys->time_total_pauses += time_paused;
>> > +
>> > +                // If pause duration more than 60s, check for if
>> > played part qualifies for individual listen
>> > +                if ( SEC_FROM_VLC_TICK (time_paused) > 60 )
>> > +                {
>> > +                    int64_t i_played_time = SEC_FROM_VLC_TICK (
>> > +                            time_current -
>> > p_sys->p_current_song.time_start - p_sys->time_total_pauses);
>> > +
>> > +                    // check whether the item as of now qualifies as a
>> > listen
>> > +                    if ( i_played_time > 30 )
>> > +                    {
>> > +                        Enqueue (intf);
>> > +                        ReadMetaData (intf); // Enqueueing deletes the
>> > current song so reset the song for the next listen.
>> > +                        p_sys->p_current_song.time_start =
>> > time_current;
>> > +                        time (&p_sys->p_current_song.date);
>> > +                        p_sys->time_total_pauses = 0;
>> > +                    }
>> > +                }
>> > +                p_sys->time_pause = 0;
>>
>> YOu should listen to the player time event instead. Cf. the
>> vlc_player_timer API.
>>
> To confirm, while checking the time for which a song is played I should
> vlc_player_timer API instead of manually calculating it.
>
>>
>> > +            }
>> > +            break;
>> > +        default:
>> > +            break;
>> > +    }
>> > +}
>> > +
>> > +static void PlaylistItemChanged (vlc_playlist_t *playlist, ssize_t
>> > index, void *data)
>> > +{
>> > +    VLC_UNUSED (index);
>> > +
>> > +    intf_thread_t *intf = data;
>> > +    if ( index > 0 )
>> > +        Enqueue (intf);
>> > +
>> > +    intf_sys_t *p_sys = intf->p_sys;
>> > +    p_sys->b_meta_read = false;
>> > +
>> > +    vlc_player_t *player = vlc_playlist_GetPlayer (playlist);
>> > +    input_item_t *item = vlc_player_GetCurrentMedia (player);
>> > +
>> > +    if ( !item || vlc_player_GetVideoTrackCount (player) )
>> > +    {
>> > +        msg_Dbg (intf, "Invalid item or not an audio-only input.");
>> > +        return;
>> > +    }
>> > +
>> > +    p_sys->time_total_pauses = 0;
>> > +    time (&p_sys->p_current_song.date);                   // time sent
>> > to ListenBrainz
>> > +    p_sys->p_current_song.time_start = vlc_tick_now ();   // time used
>> > locally to check duration of play
>> > +
>> > +    if ( input_item_IsPreparsed (item) )
>> > +        ReadMetaData (intf);
>> > +}
>> > +
>> > +static int Open (vlc_object_t *p_this)
>> > +{
>> > +
>> > +    intf_thread_t *p_intf = (intf_thread_t *) p_this;
>> > +    intf_sys_t *p_sys = calloc (1, sizeof (intf_sys_t));
>> > +    bool b_fail = 0;
>> > +
>> > +    if ( !p_sys )
>> > +        return VLC_ENOMEM;
>> > +
>> > +    p_intf->p_sys = p_sys;
>> > +
>> > +    static struct vlc_playlist_callbacks const playlist_cbs =
>> > +            {
>> > +                    .on_current_index_changed = PlaylistItemChanged,
>> > +            };
>> > +    static struct vlc_player_cbs const player_cbs =
>> > +            {
>> > +                    .on_state_changed = PlayerStateChanged,
>> > +            };
>> > +
>> > +    vlc_playlist_t *playlist = p_sys->playlist =
>> > vlc_intf_GetMainPlaylist (p_intf);
>> > +    vlc_player_t *player = vlc_playlist_GetPlayer (playlist);
>> > +
>> > +    vlc_playlist_Lock (playlist);
>> > +    p_sys->playlist_listener = vlc_playlist_AddListener (playlist,
>> > &playlist_cbs, p_intf, false);
>> > +    if ( !p_sys->playlist_listener )
>> > +    {
>> > +        vlc_playlist_Unlock (playlist);
>> > +        b_fail = 1;
>> > +    } else
>> > +    {
>> > +        p_sys->player_listener = vlc_player_AddListener (player,
>> > &player_cbs, p_intf);
>> > +        vlc_playlist_Unlock (playlist);
>> > +        if ( !p_sys->player_listener )
>> > +            b_fail = 1;
>> > +    }
>> > +    if ( !b_fail )
>> > +    {
>> > +        vlc_mutex_init (&p_sys->lock);
>> > +        vlc_cond_init (&p_sys->wait);
>> > +
>> > +        if ( vlc_clone (&p_sys->thread, Run, p_intf,
>> > VLC_THREAD_PRIORITY_LOW) )
>> > +            b_fail = 1;
>> > +    }
>> > +    if ( b_fail )
>> > +    {
>> > +        if ( p_sys->playlist_listener )
>> > +        {
>> > +            vlc_playlist_Lock (playlist);
>> > +            if ( p_sys->player_listener )
>> > +                vlc_player_RemoveListener (player,
>> > p_sys->player_listener);
>> > +            vlc_playlist_RemoveListener (playlist,
>> > p_sys->playlist_listener);
>> > +            vlc_playlist_Unlock (playlist);
>> > +        }
>> > +        free (p_sys);
>> > +        return VLC_EGENERIC;
>> > +    }
>> > +    return VLC_SUCCESS;
>> > +}
>> > +
>> > +static void Close (vlc_object_t *p_this)
>> > +{
>> > +    intf_thread_t *p_intf = (intf_thread_t *) p_this;
>> > +    intf_sys_t *p_sys = p_intf->p_sys;
>> > +    vlc_playlist_t *playlist = p_sys->playlist;
>> > +
>> > +    vlc_cancel (p_sys->thread);
>> > +    vlc_join (p_sys->thread, NULL);
>> > +
>> > +    int i;
>> > +    for ( i = 0; i < p_sys->i_songs; i++ )
>> > +        DeleteSong (&p_sys->p_queue[i]);
>> > +    vlc_UrlClean (&p_sys->p_submit_url);
>> > +
>> > +    vlc_playlist_Lock (playlist);
>> > +    vlc_player_RemoveListener (vlc_playlist_GetPlayer (playlist),
>> > p_sys->player_listener);
>> > +    vlc_playlist_RemoveListener (playlist, p_sys->playlist_listener);
>> > +    vlc_playlist_Unlock (playlist);
>> > +
>> > +    free (p_sys);
>> > +}
>> > +
>> > +static void *Run (void *data)
>> > +{
>> > +    intf_thread_t *p_intf = data;
>> > +    uint8_t p_buffer[1024];
>> > +    int canc = vlc_savecancel ();
>> > +    char *psz_url, *psz_submission_url;
>> > +    int i_ret;
>> > +    bool b_wait = 1;
>> > +
>> > +    intf_sys_t *p_sys = p_intf->p_sys;
>> > +
>> > +    while ( 1 )
>> > +    {
>> > +        vlc_restorecancel (canc);
>> > +        if ( b_wait )
>> > +            vlc_tick_wait (vlc_tick_now () + VLC_TICK_FROM_SEC (60));
>> > // wait for 1 min
>>
>> Why are you waiting for 1min here ?
>>
> If the http request fails, wait for 1 min before retrying.
>
>>
>> > +
>> > +        vlc_mutex_lock (&p_sys->lock);
>> > +        mutex_cleanup_push (&p_sys->lock) ;
>> > +
>> > +        while ( p_sys->i_songs == 0 )
>> > +            vlc_cond_wait (&p_sys->wait, &p_sys->lock);
>> > +
>> > +        msg_Dbg (p_intf, "Waiting Over");
>> > +        vlc_cleanup_pop ();
>> > +        vlc_mutex_unlock (&p_sys->lock);
>> > +        canc = vlc_savecancel ();
>> > +
>> > +        p_sys->psz_user_token = var_InheritString (p_intf,
>> > "listenbrainz_user_token");
>> > +        msg_Dbg (p_intf, "Begin");
>> > +
>> > +        if ( EMPTY_STR (p_sys->psz_user_token) )
>> > +        {
>> > +            free (p_sys->psz_user_token);
>> > +            vlc_dialog_display_error (p_intf,
>> > +                                      _ ("Listenbrainz User Token not
>> > set"), "%s",
>> > +                                      _ ("Please set a user token or
>> > disable the ListenBrainz plugin, and restart VLC.\n"
>> > +                                         " Visit
>> > https://listenbrainz.org/profile/ to get a user token."));
>> > +            break;
>> > +        }
>>
>> It should be checked from Open() instead (and return VLC_EGENERIC from
>> Open() in that case).
>>
>> > +
>> > +        psz_submission_url = var_InheritString (p_intf,
>> > "listenbrainz_submission_url");
>> > +        if ( !psz_submission_url )
>> > +            break;
>> > +        msg_Dbg (p_intf, "Submission URL Retrieved");
>> > +
>> > +        i_ret = asprintf (&psz_url, "https://%s/1/submit-listens",
>> > psz_submission_url);
>> > +        free (psz_submission_url);
>> > +        if ( i_ret == -1 )
>> > +            break;
>> > +        msg_Dbg (p_intf, "Submission URL Parsed");
>> > +
>> > +        vlc_UrlParse (&p_sys->p_submit_url, psz_url);
>> > +        free (psz_url);
>> > +        msg_Dbg (p_intf, "Submit data");
>> > +
>> > +        vlc_url_t *url;
>> > +        struct vlc_memstream req, payload;
>> > +        vlc_memstream_open (&payload);
>> > +
>> > +        vlc_mutex_lock (&p_sys->lock);
>> > +
>> > +        url = &p_sys->p_submit_url;
>> > +        b_wait = 0;
>> > +
>> > +        if ( p_sys->i_songs == 1 )
>> > +            vlc_memstream_printf (&payload,
>> > "{\"listen_type\":\"single\",\"payload\":[");
>> > +        else
>> > +            vlc_memstream_printf (&payload,
>> > "{\"listen_type\":\"import\",\"payload\":[");
>> > +
>> > +        for ( int i_song = 0; i_song < p_sys->i_songs; i_song++ )
>> > +        {
>> > +            listen_t *p_song = &p_sys->p_queue[i_song];
>> > +
>> > +            vlc_memstream_printf (&payload, "{\"listened_at\": %"
>> > +                                            PRIu64, (uint64_t)
>> > p_song->date);
>> > +            vlc_memstream_printf (&payload, ", \"track_metadata\":
>> > {\"artist_name\": \"%s\", ",
>> > +                                  vlc_uri_decode (p_song->psz_artist));
>> > +            vlc_memstream_printf (&payload, " \"track_name\": \"%s\",
>> > ", vlc_uri_decode (p_song->psz_title));
>> > +            if ( p_song->psz_album != NULL )
>> > +                vlc_memstream_printf (&payload, " \"release_name\":
>> > \"%s\"", vlc_uri_decode (p_song->psz_album));
>> > +            if ( p_song->psz_musicbrainz_id != NULL )
>> > +                vlc_memstream_printf (&payload, ",
>> > \"additional_info\": {\"recording_mbid\":\"%s\"} ",
>> > +                                      vlc_uri_decode
>> > (p_song->psz_musicbrainz_id));
>> > +            vlc_memstream_printf (&payload, "}}");
>> > +        }
>> > +
>> > +        vlc_memstream_printf (&payload, "]}");
>> > +        vlc_mutex_unlock (&p_sys->lock);
>> > +
>> > +        if ( vlc_memstream_close (&payload) )
>> > +            break;
>> > +
>> > +        vlc_memstream_open (&req);
>> > +        vlc_memstream_printf (&req, "POST %s HTTP/1.1\r\n",
>> > url->psz_path);
>> > +        vlc_memstream_printf (&req, "Host: %s\r\n", url->psz_host);
>> > +        vlc_memstream_printf (&req, "Authorization: Token %s\r\n",
>> > p_sys->psz_user_token);
>> > +        vlc_memstream_puts (&req, "User-Agent:
>> > "PACKAGE"/"VERSION"\r\n");
>> > +        vlc_memstream_puts (&req, "Connection: close\r\n");
>> > +        vlc_memstream_puts (&req, "Accept-Encoding: identity\r\n");
>> > +        vlc_memstream_printf (&req, "Content-Length: %zu\r\n",
>> > payload.length);
>> > +        vlc_memstream_puts (&req, "\r\n");
>> > +        vlc_memstream_write (&req, payload.ptr, payload.length);
>> > +        vlc_memstream_puts (&req, "\r\n\r\n");
>> > +
>> > +        free (payload.ptr);
>> > +
>> > +        if ( vlc_memstream_close (&req) )
>> > +            break;
>> > +
>> > +        msg_Dbg (p_intf, "%s", req.ptr);
>> > +        msg_Dbg (p_intf, "Open socket");
>> > +        vlc_tls_client_t *creds = vlc_tls_ClientCreate (VLC_OBJECT
>> > (p_intf));
>> > +        vlc_tls_t *sock = vlc_tls_SocketOpenTLS (creds, url->psz_host,
>> > 443, NULL, NULL, NULL);
>> > +
>> > +        if ( sock == NULL )
>> > +        {
>> > +            b_wait = 1;
>> > +            free (req.ptr);
>> > +            continue;
>> > +        }
>> > +
>> > +        msg_Warn (p_intf, "Begin transmission");
>> > +        i_ret = vlc_tls_Write (sock, req.ptr, req.length);
>> > +        msg_Warn (p_intf, "Transmission End");
>> > +        free (req.ptr);
>> > +
>> > +        if ( i_ret == -1 )
>> > +        {
>> > +            b_wait = 1;
>> > +            vlc_tls_Close (sock);
>> > +            msg_Dbg (p_intf, "Close socket");
>> > +            continue;
>> > +        }
>> > +
>> > +        msg_Warn (p_intf, "Checking response");
>> > +        i_ret = vlc_tls_Read (sock, p_buffer, sizeof (p_buffer) - 1,
>> > false);
>> > +        msg_Warn (p_intf, "Response: %s", (char *) p_buffer);
>> > +        vlc_tls_Close (sock);
>> > +        if ( i_ret <= 0 )
>> > +        {
>> > +            msg_Warn (p_intf, "No response");
>> > +            continue;
>> > +        }
>> > +        p_buffer[i_ret] = '\0';
>> > +        if ( strstr ((char *) p_buffer, "OK") )
>> > +        {
>> > +            for ( int i = 0; i < p_sys->i_songs; i++ )
>> > +                DeleteSong (&p_sys->p_queue[i]);
>> > +            p_sys->i_songs = 0;
>> > +
>> > +            b_wait = 1;
>> > +            msg_Dbg (p_intf, "Submission successful!");
>> > +        } else
>> > +        {
>> > +            msg_Warn (p_intf, "Error: %s", (char *) p_buffer);
>> > +            b_wait = 1;
>> > +            continue;
>> > +        }
>>
>> YOu should split the Run function into several one:
>>  - prepare payload
>>  - prepare http request
>>  - tls/http post
>>  - etc...
>>
>> > +    }
>> > +
>> > +    vlc_restorecancel (canc);
>> > +    return NULL;
>> > +}
>> > +
>> > --
>> > 2.20.1
>> >
>> > _______________________________________________
>> > vlc-devel mailing list
>> > To unsubscribe or modify your subscription options:
>> > https://mailman.videolan.org/listinfo/vlc-devel
>> _______________________________________________
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20200308/941b3a7f/attachment-0001.html>


More information about the vlc-devel mailing list