⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audioscrobbler.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************** * audioscrobbler.c : audioscrobbler submission plugin ***************************************************************************** * Copyright © 2006-2008 the VideoLAN team * $Id: 711fec7c961649406c9e47b5ad780f1f3659ac24 $ * * Author: Rafaël Carré <funman at videolanorg> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//* audioscrobbler protocol version: 1.2 * http://www.audioscrobbler.net/development/protocol/ * * TODO:    "Now Playing" feature (not mandatory) *//***************************************************************************** * Preamble *****************************************************************************/#if defined( WIN32 ) #include <time.h> #endif #ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_interface.h>#include <vlc_meta.h>#include <vlc_md5.h>#include <vlc_block.h>#include <vlc_stream.h>#include <vlc_url.h>#include <vlc_network.h>#include <vlc_interface.h>#include <vlc_playlist.h>/***************************************************************************** * Local prototypes *****************************************************************************/#define QUEUE_MAX 50/* Keeps track of metadata to be submitted */typedef struct audioscrobbler_song_t{    char        *psz_a;             /**< track artist     */    char        *psz_t;             /**< track title      */    char        *psz_b;             /**< track album      */    char        *psz_n;             /**< track number     */    int         i_l;                /**< track length     */    char        *psz_m;             /**< musicbrainz id   */    time_t      date;               /**< date since epoch */    mtime_t     i_start;            /**< playing start    */} audioscrobbler_song_t;struct intf_sys_t{    audioscrobbler_song_t   p_queue[QUEUE_MAX]; /**< songs not submitted yet*/    int                     i_songs;            /**< number of songs        */    vlc_mutex_t             lock;               /**< p_sys mutex            */    /* data about audioscrobbler session */    mtime_t                 next_exchange;      /**< when can we send data  */    unsigned int            i_interval;         /**< waiting interval (secs)*/    /* submission of played songs */    char                    *psz_submit_host;   /**< where to submit data   */    int                     i_submit_port;      /**< port to which submit   */    char                    *psz_submit_file;   /**< file to which submit   */    /* submission of playing song */#if 0 //NOT USED    char                    *psz_nowp_host;     /**< where to submit data   */    int                     i_nowp_port;        /**< port to which submit   */    char                    *psz_nowp_file;     /**< file to which submit   */#endif    bool                    b_handshaked;       /**< are we authenticated ? */    char                    psz_auth_token[33]; /**< Authentication token */    /* data about song currently playing */    audioscrobbler_song_t   p_current_song;     /**< song being played      */    mtime_t                 time_pause;         /**< time when vlc paused   */    mtime_t                 time_total_pauses;  /**< total time in pause    */    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 int ItemChange       ( vlc_object_t *, const char *, vlc_value_t,                                vlc_value_t, void * );static int PlayingChange    ( vlc_object_t *, const char *, vlc_value_t,                                vlc_value_t, void * );static void AddToQueue      ( intf_thread_t * );static int Handshake        ( intf_thread_t * );static int ReadMetaData     ( intf_thread_t * );static void DeleteSong      ( audioscrobbler_song_t* );static int ParseURL         ( char *, char **, char **, int * );static void HandleInterval  ( mtime_t *, unsigned int * );/***************************************************************************** * Module descriptor ****************************************************************************/#define USERNAME_TEXT       N_("Username")#define USERNAME_LONGTEXT   N_("The username of your last.fm account")#define PASSWORD_TEXT       N_("Password")#define PASSWORD_LONGTEXT   N_("The password of your last.fm account")/* This error value is used when last.fm plugin has to be unloaded. */#define VLC_AUDIOSCROBBLER_EFATAL -69/* last.fm client identifier */#define CLIENT_NAME     PACKAGE#define CLIENT_VERSION  VERSION/* HTTP POST request : to submit data */#define    POST_REQUEST "POST /%s HTTP/1.1\n"                               \                        "Accept-Encoding: identity\n"                       \                        "Content-length: %u\n"                              \                        "Connection: close\n"                               \                        "Content-type: application/x-www-form-urlencoded\n" \                        "Host: %s\n"                                        \                        "User-agent: VLC Media Player/%s\r\n"               \                        "\r\n"                                              \                        "%s\r\n"                                            \                        "\r\n"vlc_module_begin();    set_category( CAT_INTERFACE );    set_subcategory( SUBCAT_INTERFACE_CONTROL );    set_shortname( N_( "Audioscrobbler" ) );    set_description( N_("Submission of played songs to last.fm") );    add_string( "lastfm-username", "", NULL,                USERNAME_TEXT, USERNAME_LONGTEXT, false );    add_password( "lastfm-password", "", NULL,                PASSWORD_TEXT, PASSWORD_LONGTEXT, false );    set_capability( "interface", 0 );    set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Open: initialize and create stuff *****************************************************************************/static int Open( vlc_object_t *p_this ){    playlist_t      *p_playlist;    intf_thread_t   *p_intf     = ( intf_thread_t* ) p_this;    intf_sys_t      *p_sys      = calloc( 1, sizeof( intf_sys_t ) );    if( !p_sys )        return VLC_ENOMEM;    p_intf->p_sys = p_sys;    vlc_mutex_init( &p_sys->lock );    p_playlist = pl_Yield( p_intf );    PL_LOCK;    var_AddCallback( p_playlist, "playlist-current", ItemChange, p_intf );    PL_UNLOCK;    pl_Release( p_intf );    p_intf->pf_run = Run;    return VLC_SUCCESS;}/***************************************************************************** * Close: destroy interface stuff *****************************************************************************/static void Close( vlc_object_t *p_this ){    playlist_t                  *p_playlist;    input_thread_t              *p_input;    intf_thread_t               *p_intf = ( intf_thread_t* ) p_this;    intf_sys_t                  *p_sys  = p_intf->p_sys;    p_playlist = pl_Yield( p_intf );    if( p_playlist )    {        PL_LOCK;        var_DelCallback( p_playlist, "playlist-current", ItemChange, p_intf );        p_input = p_playlist->p_input;        if ( p_input )        {            vlc_object_yield( p_input );            if( p_sys->b_state_cb )                var_DelCallback( p_input, "state", PlayingChange, p_intf );            vlc_object_release( p_input );        }        PL_UNLOCK;        pl_Release( p_intf );    }    p_intf->b_dead = true;    /* we lock the mutex in case p_sys is being accessed from a callback */    vlc_mutex_lock ( &p_sys->lock );    int i;    for( i = 0; i < p_sys->i_songs; i++ )        DeleteSong( &p_sys->p_queue[i] );    free( p_sys->psz_submit_host );    free( p_sys->psz_submit_file );#if 0 //NOT USED    free( p_sys->psz_nowp_host );    free( p_sys->psz_nowp_file );#endif    vlc_mutex_unlock ( &p_sys->lock );    vlc_mutex_destroy( &p_sys->lock );    free( p_sys );}/***************************************************************************** * Run : call Handshake() then submit songs *****************************************************************************/static void Run( intf_thread_t *p_intf ){    char                    *psz_submit, *psz_submit_song, *psz_submit_tmp;    int                     i_net_ret;    int                     i_song;    uint8_t                 p_buffer[1024];    char                    *p_buffer_pos;    int                     i_post_socket;    intf_sys_t *p_sys = p_intf->p_sys;    /* main loop */    for( ;; )    {        bool b_wait = false;        vlc_object_lock( p_intf );        if( !vlc_object_alive( p_intf ) )        {            vlc_object_unlock( p_intf );            msg_Dbg( p_intf, "audioscrobbler is dying");            return;        }        if( mdate() < p_sys->next_exchange )            /* wait until we can resubmit, i.e.  */            b_wait = vlc_object_timedwait( p_intf, p_sys->next_exchange ) == 0;        else            /* wait for data to submit */            /* we are signaled each time there is a song to submit */            vlc_object_wait( p_intf );        vlc_object_unlock( p_intf );        if( b_wait )            continue; /* holding on until next_exchange */        /* handshake if needed */        if( p_sys->b_handshaked == false )        {            msg_Dbg( p_intf, "Handshaking with last.fm ..." );            switch( Handshake( p_intf ) )            {                case VLC_ENOMEM:                    return;                case VLC_ENOVAR:                    /* username not set */                    intf_UserFatal( p_intf, false,                        _("Last.fm username not set"),                        _("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_intf, "Handshake successfull :)" );                    p_sys->b_handshaked = true;                    p_sys->i_interval = 0;                    p_sys->next_exchange = mdate();                    break;                case VLC_AUDIOSCROBBLER_EFATAL:                    msg_Warn( p_intf, "Exiting..." );                    return;                case VLC_EGENERIC:                default:                    /* protocol error : we'll try later */                    HandleInterval( &p_sys->next_exchange, &p_sys->i_interval );                    break;            }            /* if handshake failed let's restart the loop */            if( p_sys->b_handshaked == false )                continue;        }        msg_Dbg( p_intf, "Going to submit some data..." );        /* The session may be invalid if there is a trailing \n */        char *psz_ln = strrchr( p_sys->psz_auth_token, '\n' );        if( psz_ln )            *psz_ln = '\0';        if( !asprintf( &psz_submit, "s=%s", p_sys->psz_auth_token ) )        {   /* Out of memory */            return;        }        /* forge the HTTP POST request */        vlc_mutex_lock( &p_sys->lock );        audioscrobbler_song_t *p_song;        for( i_song = 0 ; i_song < p_sys->i_songs ; i_song++ )        {            p_song = &p_sys->p_queue[i_song];            if( !asprintf( &psz_submit_song,                    "&a%%5B%d%%5D=%s"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -