/** * Update all the MetaData and art on an "item-changed" event **/ void MetaPanel::update( input_item_t *p_item ) { if( !p_item ) { clear(); return; } /* Don't update if you are in edit mode */ if( b_inEditMode ) return; p_input = p_item; char *psz_meta; #define UPDATE_META( meta, widget ) { \ psz_meta = input_item_Get##meta( p_item ); \ widget->setText( !EMPTY_STR( psz_meta ) ? qfu( psz_meta ) : "" ); \ free( psz_meta ); } #define UPDATE_META_INT( meta, widget ) { \ psz_meta = input_item_Get##meta( p_item ); \ if( !EMPTY_STR( psz_meta ) ) \ widget->setValue( atoi( psz_meta ) ); } \ free( psz_meta ); /* Name / Title */ psz_meta = input_item_GetTitleFbName( p_item ); if( psz_meta ) { title_text->setText( qfu( psz_meta ) ); free( psz_meta ); } else title_text->setText( "" ); /* URL / URI */ psz_meta = input_item_GetURI( p_item ); if( !EMPTY_STR( psz_meta ) ) emit uriSet( qfu( psz_meta ) ); fingerprintButton->setVisible( Chromaprint::isSupported( QString( psz_meta ) ) ); free( psz_meta ); /* Other classic though */ UPDATE_META( Artist, artist_text ); UPDATE_META( Genre, genre_text ); UPDATE_META( Copyright, copyright_text ); UPDATE_META( Album, collection_text ); UPDATE_META( Description, description_text ); UPDATE_META( Language, language_text ); UPDATE_META( NowPlaying, nowplaying_text ); UPDATE_META( Publisher, publisher_text ); UPDATE_META( EncodedBy, encodedby_text ); UPDATE_META( Date, date_text ); UPDATE_META( TrackNum, seqnum_text ); UPDATE_META( TrackTotal, seqtot_text ); // UPDATE_META( Setting, setting_text ); // UPDATE_META_INT( Rating, rating_text ); /* URL */ psz_meta = input_item_GetURL( p_item ); if( !EMPTY_STR( psz_meta ) ) { QString newURL = qfu(psz_meta); if( currentURL != newURL ) { currentURL = newURL; lblURL->setText( "<a href='" + currentURL + "'>" + currentURL.remove( QRegExp( ".*://") ) + "</a>" ); } } free( psz_meta ); #undef UPDATE_META_INT #undef UPDATE_META // If a artURL is available as a local file, directly display it ! QString file; char *psz_art = input_item_GetArtURL( p_item ); if( psz_art ) { char *psz = make_path( psz_art ); free( psz_art ); file = qfu( psz ); free( psz ); } art_cover->showArtUpdate( file ); art_cover->setItem( p_item ); }
/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static int ItemChange( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ) { VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval); char psz_tmp[MAX_LENGTH]; char psz_notify[MAX_LENGTH]; char *psz_title; char *psz_artist; char *psz_album; char *psz_arturl; input_thread_t *p_input = playlist_CurrentInput( (playlist_t*)p_this ); intf_thread_t *p_intf = param; intf_sys_t *p_sys = p_intf->p_sys; if( !p_input ) return VLC_SUCCESS; if( p_input->b_dead ) { /* Not playing anything ... */ vlc_object_release( p_input ); return VLC_SUCCESS; } /* Wait a tad so the meta has been fetched * FIXME that's awfully wrong */ msleep( 10000 ); /* Playing something ... */ input_item_t *p_input_item = input_GetItem( p_input ); psz_title = input_item_GetTitleFbName( p_input_item ); /* We need at least a title */ if( EMPTY_STR( psz_title ) ) { free( psz_title ); vlc_object_release( p_input ); return VLC_SUCCESS; } psz_artist = input_item_GetArtist( p_input_item ); psz_album = input_item_GetAlbum( p_input_item ); if( !EMPTY_STR( psz_artist ) ) { if( !EMPTY_STR( psz_album ) ) snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s\n[%s]", psz_title, psz_artist, psz_album ); else snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s", psz_title, psz_artist ); } else snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>", psz_title ); free( psz_title ); free( psz_artist ); free( psz_album ); GdkPixbuf *pix = NULL; psz_arturl = input_item_GetArtURL( p_input_item ); vlc_object_release( p_input ); if( psz_arturl ) { char *psz = make_path( psz_arturl ); free( psz_arturl ); psz_arturl = psz; } if( psz_arturl ) { /* scale the art to show it in notify popup */ GError *p_error = NULL; pix = gdk_pixbuf_new_from_file_at_scale( psz_arturl, 72, 72, TRUE, &p_error ); } else /* else we show state-of-the art logo */ { /* First try to get an icon from the current theme. */ GtkIconTheme* p_theme = gtk_icon_theme_get_default(); pix = gtk_icon_theme_load_icon( p_theme, "vlc", 72, 0, NULL); if( !pix ) { /* Load icon from share/ */ GError *p_error = NULL; char *psz_pixbuf; char *psz_data = config_GetDataDir( p_this ); if( asprintf( &psz_pixbuf, "%s/icons/48x48/vlc.png", psz_data ) >= 0 ) { pix = gdk_pixbuf_new_from_file( psz_pixbuf, &p_error ); free( psz_pixbuf ); } free( psz_data ); } } free( psz_arturl ); /* we need to replace '&' with '&' because '&' is a keyword of * notification-daemon parser */ const int i_len = strlen( psz_tmp ); int i_notify = 0; for( int i = 0; i < i_len && i_notify < ( MAX_LENGTH - 5 ); i++ ) { /* we use MAX_LENGTH - 5 because if the last char of psz_tmp is '&' * we will need 5 more characters: 'amp;\0' . * however that's unlikely to happen because the last char is '\0' */ if( psz_tmp[i] != '&' ) { psz_notify[i_notify] = psz_tmp[i]; } else { strcpy( &psz_notify[i_notify], "&" ); i_notify += 4; } i_notify++; } psz_notify[i_notify] = '\0'; vlc_mutex_lock( &p_sys->lock ); Notify( p_this, psz_notify, pix, p_intf ); vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; }
static int Demux( demux_t *p_demux ) { char *psz_line; char *psz_name = NULL; char *psz_artist = NULL; char *psz_album_art = NULL; int i_parsed_duration = 0; mtime_t i_duration = -1; const char**ppsz_options = NULL; char * (*pf_dup) (const char *) = p_demux->p_sys->pf_dup; int i_options = 0; bool b_cleanup = false; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); input_item_node_t *p_subitems = input_item_node_Create( p_current_input ); psz_line = stream_ReadLine( p_demux->s ); while( psz_line ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; if( *psz_parse == '#' ) { /* Parse extra info */ /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' || *psz_parse == '#' ) psz_parse++; if( !*psz_parse ) goto error; if( !strncasecmp( psz_parse, "EXTINF:", sizeof("EXTINF:") -1 ) ) { /* Extended info */ psz_parse += sizeof("EXTINF:") - 1; FREENULL( psz_name ); FREENULL( psz_artist ); parseEXTINF( psz_parse, &psz_artist, &psz_name, &i_parsed_duration ); if( i_parsed_duration >= 0 ) i_duration = i_parsed_duration * INT64_C(1000000); if( psz_name ) psz_name = pf_dup( psz_name ); if( psz_artist ) psz_artist = pf_dup( psz_artist ); } else if( !strncasecmp( psz_parse, "EXTVLCOPT:", sizeof("EXTVLCOPT:") -1 ) ) { /* VLC Option */ char *psz_option; psz_parse += sizeof("EXTVLCOPT:") -1; if( !*psz_parse ) goto error; psz_option = pf_dup( psz_parse ); if( psz_option ) INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); } /* Special case for jamendo which provide the albumart */ else if( !strncasecmp( psz_parse, "EXTALBUMARTURL:", sizeof( "EXTALBUMARTURL:" ) -1 ) ) { psz_parse += sizeof( "EXTALBUMARTURL:" ) - 1; free( psz_album_art ); psz_album_art = pf_dup( psz_parse ); } } else if( !strncasecmp( psz_parse, "RTSPtext", sizeof("RTSPtext") -1 ) ) { ;/* special case to handle QuickTime RTSPtext redirect files */ } else if( *psz_parse ) { char *psz_mrl; psz_parse = pf_dup( psz_parse ); if( !psz_name && psz_parse ) /* Use filename as name for relative entries */ psz_name = strdup( psz_parse ); psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix ); b_cleanup = true; if( !psz_mrl ) { free( psz_parse ); goto error; } p_input = input_item_NewExt( psz_mrl, psz_name, i_options, ppsz_options, 0, i_duration ); free( psz_parse ); free( psz_mrl ); if ( !EMPTY_STR(psz_artist) ) input_item_SetArtist( p_input, psz_artist ); if( psz_name ) input_item_SetTitle( p_input, psz_name ); if( !EMPTY_STR(psz_album_art) ) input_item_SetArtURL( p_input, psz_album_art ); input_item_node_AppendItem( p_subitems, p_input ); vlc_gc_decref( p_input ); } error: /* Fetch another line */ free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); if( !psz_line ) b_cleanup = true; if( b_cleanup ) { /* Cleanup state */ while( i_options-- ) free( (char*)ppsz_options[i_options] ); FREENULL( ppsz_options ); i_options = 0; FREENULL( psz_name ); FREENULL( psz_artist ); FREENULL( psz_album_art ); i_parsed_duration = 0; i_duration = -1; b_cleanup = false; } } input_item_node_PostAndDelete( p_subitems ); vlc_gc_decref(p_current_input); var_Destroy( p_demux, "m3u-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
/***************************************************************************** * Handshake : Init audioscrobbler connection *****************************************************************************/ static int Handshake(intf_thread_t *p_this) { char *psz_username, *psz_password; char *psz_scrobbler_url; time_t timestamp; char psz_timestamp[21]; struct md5_s p_struct_md5; stream_t *p_stream; char *psz_handshake_url; uint8_t p_buffer[1024]; char *p_buffer_pos; int i_ret; char *psz_url; intf_thread_t *p_intf = (intf_thread_t*) p_this; intf_sys_t *p_sys = p_this->p_sys; psz_username = var_InheritString(p_this, "lastfm-username"); psz_password = var_InheritString(p_this, "lastfm-password"); /* username or password have not been setup */ if (EMPTY_STR(psz_username) || EMPTY_STR(psz_password)) { free(psz_username); free(psz_password); return VLC_ENOVAR; } time(×tamp); /* generates a md5 hash of the password */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password, strlen(psz_password)); EndMD5(&p_struct_md5); free(psz_password); char *psz_password_md5 = psz_md5_hash(&p_struct_md5); if (!psz_password_md5) { free(psz_username); return VLC_ENOMEM; } snprintf(psz_timestamp, sizeof(psz_timestamp), "%"PRIu64, (uint64_t)timestamp); /* generates a md5 hash of : * - md5 hash of the password, plus * - timestamp in clear text */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password_md5, 32); AddMD5(&p_struct_md5, (uint8_t*) psz_timestamp, strlen(psz_timestamp)); EndMD5(&p_struct_md5); free(psz_password_md5); char *psz_auth_token = psz_md5_hash(&p_struct_md5); if (!psz_auth_token) { free(psz_username); return VLC_ENOMEM; } psz_scrobbler_url = var_InheritString(p_this, "scrobbler-url"); if (!psz_scrobbler_url) { free(psz_auth_token); free(psz_username); return VLC_ENOMEM; } i_ret = asprintf(&psz_handshake_url, "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) return VLC_ENOMEM; /* send the http handshake request */ p_stream = stream_UrlNew(p_intf, psz_handshake_url); free(psz_handshake_url); if (!p_stream) return VLC_EGENERIC; /* read answer */ i_ret = stream_Read(p_stream, p_buffer, sizeof(p_buffer) - 1); if (i_ret <= 0) { stream_Delete(p_stream); return VLC_EGENERIC; } p_buffer[i_ret] = '\0'; stream_Delete(p_stream); p_buffer_pos = strstr((char*) p_buffer, "FAILED "); if (p_buffer_pos) { /* handshake request failed, sorry */ msg_Err(p_this, "last.fm handshake failed: %s", p_buffer_pos + 7); return VLC_EGENERIC; } if (strstr((char*) p_buffer, "BADAUTH")) { /* authentication failed, bad username/password combination */ dialog_Fatal(p_this, _("last.fm: Authentication failed"), "%s", _("last.fm username or password is incorrect. " "Please verify your settings and relaunch VLC.")); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BANNED")) { /* oops, our version of vlc has been banned by last.fm servers */ msg_Err(p_intf, "This version of VLC has been banned by last.fm. " "You should upgrade VLC, or disable the last.fm plugin."); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BADTIME")) { /* The system clock isn't good */ msg_Err(p_intf, "last.fm handshake failed because your clock is too " "much shifted. Please correct it, and relaunch VLC."); return VLC_AUDIOSCROBBLER_EFATAL; } p_buffer_pos = strstr((char*) p_buffer, "OK"); if (!p_buffer_pos) goto proto; p_buffer_pos = strstr(p_buffer_pos, "\n"); if (!p_buffer_pos || strlen(p_buffer_pos) < 33) goto proto; p_buffer_pos++; /* we skip the '\n' */ /* save the session ID */ memcpy(p_sys->psz_auth_token, p_buffer_pos, 32); p_sys->psz_auth_token[32] = '\0'; p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the nowplaying url */ p_buffer_pos += 7; /* we skip "http://" */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; vlc_UrlParse(&p_sys->p_nowp_url, psz_url); free(psz_url); if (p_sys->p_nowp_url.psz_host == NULL || p_sys->p_nowp_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); goto proto; } p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the submission url */ p_buffer_pos += 7; /* we skip "http://" */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; /* parse the submission url */ vlc_UrlParse(&p_sys->p_submit_url, psz_url); free(psz_url); if (p_sys->p_submit_url.psz_host == NULL || p_sys->p_submit_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); vlc_UrlClean(&p_sys->p_submit_url); goto proto; } return VLC_SUCCESS; oom: return VLC_ENOMEM; proto: msg_Err(p_intf, "Handshake: can't recognize server protocol"); return VLC_EGENERIC; }
/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static int ItemChange( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ) { VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval); char psz_tmp[MAX_LENGTH]; char psz_notify[MAX_LENGTH]; char *psz_title; char *psz_artist; char *psz_album; char *psz_arturl; input_thread_t *p_input = newval.p_address; intf_thread_t *p_intf = param; intf_sys_t *p_sys = p_intf->p_sys; if( !p_input ) return VLC_SUCCESS; /* Playing something ... */ input_item_t *p_input_item = input_GetItem( p_input ); /* Checking for click on directories */ if(p_input_item->i_type == ITEM_TYPE_DIRECTORY || p_input_item->i_type == ITEM_TYPE_PLAYLIST || p_input_item->i_type == ITEM_TYPE_NODE || p_input_item->i_type== ITEM_TYPE_UNKNOWN || p_input_item->i_type == ITEM_TYPE_CARD){ return VLC_SUCCESS; } psz_title = input_item_GetTitleFbName( p_input_item ); /* We need at least a title */ if( EMPTY_STR( psz_title ) ) { free( psz_title ); return VLC_SUCCESS; } psz_artist = input_item_GetArtist( p_input_item ); psz_album = input_item_GetAlbum( p_input_item ); if( !EMPTY_STR( psz_artist ) ) { if( !EMPTY_STR( psz_album ) ) snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s\n[%s]", psz_title, psz_artist, psz_album ); else snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s", psz_title, psz_artist ); } else snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>", psz_title ); free( psz_title ); free( psz_artist ); free( psz_album ); GdkPixbuf *pix = NULL; psz_arturl = input_item_GetArtURL( p_input_item ); if( psz_arturl ) { char *psz = vlc_uri2path( psz_arturl ); free( psz_arturl ); psz_arturl = psz; } if( psz_arturl ) { /* scale the art to show it in notify popup */ GError *p_error = NULL; pix = gdk_pixbuf_new_from_file_at_scale( psz_arturl, 72, 72, TRUE, &p_error ); } else /* else we show state-of-the art logo */ { /* First try to get an icon from the current theme. */ GtkIconTheme* p_theme = gtk_icon_theme_get_default(); pix = gtk_icon_theme_load_icon( p_theme, "vlc", 72, 0, NULL); if( !pix ) { /* Load icon from share/ */ GError *p_error = NULL; char *psz_pixbuf = config_GetSysPath(VLC_SYSDATA_DIR, "icons/hicolor/48x48/"PACKAGE_NAME".png"); if (psz_pixbuf != NULL) { pix = gdk_pixbuf_new_from_file( psz_pixbuf, &p_error ); free( psz_pixbuf ); } } } free( psz_arturl ); /* we need to replace '&' with '&' because '&' is a keyword of * notification-daemon parser */ const int i_len = strlen( psz_tmp ); int i_notify = 0; for( int i = 0; i < i_len && i_notify < ( MAX_LENGTH - 5 ); i++ ) { /* we use MAX_LENGTH - 5 because if the last char of psz_tmp is '&' * we will need 5 more characters: 'amp;\0' . * however that's unlikely to happen because the last char is '\0' */ if( psz_tmp[i] != '&' ) { psz_notify[i_notify] = psz_tmp[i]; } else { strcpy( &psz_notify[i_notify], "&" ); i_notify += 4; } i_notify++; } psz_notify[i_notify] = '\0'; vlc_mutex_lock( &p_sys->lock ); Notify( p_this, psz_notify, pix, p_intf ); vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; }
/** * Update all the MetaData and art on an "item-changed" event **/ void MetaPanel::update( input_item_t *p_item ) { if( !p_item ) { clear(); return; } /* Don't update if you are in edit mode */ if( b_inEditMode ) return; else p_input = p_item; char *psz_meta; #define UPDATE_META( meta, widget ) { \ psz_meta = input_item_Get##meta( p_item ); \ if( !EMPTY_STR( psz_meta ) ) \ widget->setText( qfu( psz_meta ) ); \ else \ widget->setText( "" ); } \ free( psz_meta ); #define UPDATE_META_INT( meta, widget ) { \ psz_meta = input_item_Get##meta( p_item ); \ if( !EMPTY_STR( psz_meta ) ) \ widget->setValue( atoi( psz_meta ) ); } \ free( psz_meta ); /* Name / Title */ psz_meta = input_item_GetTitleFbName( p_item ); if( psz_meta ) { title_text->setText( qfu( psz_meta ) ); free( psz_meta ); } else title_text->setText( "" ); /* URL / URI */ psz_meta = input_item_GetURL( p_item ); if( !EMPTY_STR( psz_meta ) ) emit uriSet( qfu( psz_meta ) ); else { free( psz_meta ); psz_meta = input_item_GetURI( p_item ); if( !EMPTY_STR( psz_meta ) ) emit uriSet( qfu( psz_meta ) ); } free( psz_meta ); /* Other classic though */ UPDATE_META( Artist, artist_text ); UPDATE_META( Genre, genre_text ); UPDATE_META( Copyright, copyright_text ); UPDATE_META( Album, collection_text ); UPDATE_META( Description, description_text ); UPDATE_META( Language, language_text ); UPDATE_META( NowPlaying, nowplaying_text ); UPDATE_META( Publisher, publisher_text ); // UPDATE_META( Setting, setting_text ); //FIXME this is wrong if has Publisher and EncodedBy fields UPDATE_META( EncodedBy, publisher_text ); UPDATE_META( Date, date_text ); UPDATE_META( TrackNum, seqnum_text ); // UPDATE_META_INT( Rating, rating_text ); #undef UPDATE_META_INT #undef UPDATE_META // If a artURL is available as a local file, directly display it ! QString file; char *psz_art = input_item_GetArtURL( p_item ); if( psz_art ) { char *psz = make_path( psz_art ); free( psz_art ); file = qfu( psz ); free( psz ); } art_cover->showArtUpdate( file ); }
/** * Start the input for an item * * \param p_playlist the playlist object * \param p_item the item to play * \return nothing */ static int PlayItem( playlist_t *p_playlist, playlist_item_t *p_item ) { playlist_private_t *p_sys = pl_priv(p_playlist); input_item_t *p_input = p_item->p_input; PL_ASSERT_LOCKED; msg_Dbg( p_playlist, "creating new input thread" ); p_input->i_nb_played++; set_current_status_item( p_playlist, p_item ); p_sys->status.i_status = PLAYLIST_RUNNING; assert( p_sys->p_input == NULL ); input_thread_t *p_input_thread = input_Create( p_playlist, p_input, NULL, p_sys->p_input_resource ); if( p_input_thread ) { p_sys->p_input = p_input_thread; var_AddCallback( p_input_thread, "intf-event", InputEvent, p_playlist ); var_SetAddress( p_playlist, "input-current", p_input_thread ); if( input_Start( p_sys->p_input ) ) { vlc_object_release( p_input_thread ); p_sys->p_input = p_input_thread = NULL; } } bool b_find_art = var_GetInteger( p_playlist, "album-art" ) == ALBUM_ART_WHEN_PLAYED; if( b_find_art ) { char *psz_uri = input_item_GetURI( p_item->p_input ); if( psz_uri != NULL && (!strncmp( psz_uri, "directory:", 10 ) || !strncmp( psz_uri, "vlc:", 4 )) ) b_find_art = false; free( psz_uri ); } /* TODO store art policy in playlist private data */ if( b_find_art ) { char *psz_arturl = input_item_GetArtURL( p_input ); char *psz_name = input_item_GetName( p_input ); /* p_input->p_meta should not be null after a successful CreateThread */ bool b_has_art = !EMPTY_STR( psz_arturl ); if( !b_has_art || strncmp( psz_arturl, "attachment://", 13 ) ) { PL_DEBUG( "requesting art for %s", psz_name ); playlist_AskForArtEnqueue( p_playlist, p_input ); } free( psz_arturl ); free( psz_name ); } PL_UNLOCK; var_TriggerCallback( p_playlist, "activity" ); PL_LOCK; return VLC_SUCCESS; }
/***************************************************************************** * CreateFilter: Create the filter and open the definition file *****************************************************************************/ static int CreateFilter ( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; filter_sys_t *p_sys = NULL; msg_Dbg( p_filter, "Creating vnc osd filter..." ); p_filter->p_sys = p_sys = calloc( 1, sizeof(*p_sys) ); if( !p_filter->p_sys ) return VLC_ENOMEM; /* Populating struct */ vlc_mutex_init( &p_sys->lock ); p_sys->b_continue = true; p_sys->i_socket = -1; p_sys->p_pic = NULL; p_sys->psz_host = var_CreateGetString( p_this, RMTOSD_CFG "host" ); if( EMPTY_STR(p_sys->psz_host) ) { msg_Err( p_filter, "unable to get vnc host" ); goto error; } p_sys->psz_passwd = var_CreateGetString( p_this, RMTOSD_CFG "password" ); if( !p_sys->psz_passwd ) { msg_Err( p_filter, "unable to get vnc password" ); goto error; } p_sys->i_port = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "port" ); p_sys->i_alpha = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "alpha" ); /* in milliseconds, 0 disables polling, should not be lower than 100 */ p_sys->i_vnc_poll_interval = var_CreateGetIntegerCommand( p_this, RMTOSD_CFG "update" ); if ( p_sys->i_vnc_poll_interval < 100) { p_sys->i_vnc_poll_interval = 100; } for ( int i = 0; i < 256; i++ ) { p_sys->ar_color_table_yuv[i][0] = 255; p_sys->ar_color_table_yuv[i][1] = 255; p_sys->ar_color_table_yuv[i][2] = 255; p_sys->ar_color_table_yuv[i][3] = 255; } p_sys->b_vnc_poll = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "vnc-polling" ); p_sys->b_vnc_mouse_events = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "mouse-events" ); p_sys->b_vnc_key_events = var_CreateGetBoolCommand( p_this, RMTOSD_CFG "key-events" ); /* Keep track of OSD Events */ p_sys->b_need_update = false; /* Attach subpicture source callback */ p_filter->pf_sub_source = Filter; p_filter->pf_sub_mouse = MouseEvent; var_AddCallback( p_filter->p_libvlc, "key-pressed", KeyEvent, p_this ); es_format_Init( &p_filter->fmt_out, SPU_ES, VLC_CODEC_SPU ); p_filter->fmt_out.i_priority = 0; vlc_gcrypt_init(); /* create the vnc worker thread */ if( vlc_clone( &p_sys->worker_thread, vnc_worker_thread, p_filter, VLC_THREAD_PRIORITY_LOW ) ) { msg_Err( p_filter, "cannot spawn vnc message reader thread" ); goto error; } msg_Dbg( p_filter, "osdvnc filter started" ); return VLC_SUCCESS; error: msg_Err( p_filter, "osdvnc filter discarded" ); stop_osdvnc( p_filter ); vlc_mutex_destroy( &p_sys->lock ); free( p_sys->psz_host ); free( p_sys->psz_passwd ); free( p_sys ); return VLC_EGENERIC; }
static int Demux( demux_t *p_demux ) { char *psz_line; mtime_t i_duration = -1; char *psz_title = NULL, *psz_genre = NULL, *psz_tracknum = NULL, *psz_language = NULL, *psz_artist = NULL, *psz_album = NULL, *psz_date = NULL, *psz_publicher = NULL, *psz_encodedby = NULL, *psz_description = NULL, *psz_url = NULL, *psz_copyright = NULL, *psz_mrl = NULL; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_line = stream_ReadLine( p_demux->s ); char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; /* if the 1st line is "AC", skip it */ /* TODO: using this information ? */ if( !strncasecmp( psz_parse, "AC", strlen( "AC" ) ) ) { free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); } /* Loop on all lines */ while( psz_line ) { psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; /* filename */ if( !strncasecmp( psz_parse, "NM", strlen( "NM" ) ) ) { char *psz_tabvalue = ParseTabValue( psz_parse ); if( !EMPTY_STR(psz_tabvalue) ) { psz_mrl = ProcessMRL( psz_tabvalue, p_demux->p_sys->psz_prefix ); if( psz_mrl ) MaybeFromLocaleRep( &psz_mrl ); } free( psz_tabvalue ); } /* duration */ else if( !strncasecmp( psz_parse, "DR", strlen( "DR" ) ) ) { char *psz_tabvalue = ParseTabValue( psz_parse ); if( !EMPTY_STR(psz_tabvalue) ) { int i_parsed_duration = atoi( psz_tabvalue ); if( i_parsed_duration >= 0 ) i_duration = i_parsed_duration * INT64_C(1000); } free( psz_tabvalue ); } #define PARSE(tag,variable) \ else if( !strncasecmp( psz_parse, tag, strlen( tag ) ) ) \ variable = ParseTabValue( psz_parse ); PARSE( "TT", psz_title ) PARSE( "TG", psz_genre ) PARSE( "TR", psz_tracknum ) PARSE( "TL", psz_language ) PARSE( "TA", psz_artist ) PARSE( "TB", psz_album ) PARSE( "TY", psz_date ) PARSE( "TH", psz_publicher ) PARSE( "TE", psz_encodedby ) PARSE( "TC", psz_description ) PARSE( "TU", psz_url ) PARSE( "TO", psz_copyright ) #undef PARSE /* force a duration ? */ else if( !strncasecmp( psz_parse, "FD", strlen( "FD" ) ) ) {} /* end of file entry */ else if( !strncasecmp( psz_parse, "BR!", strlen( "BR!" ) ) ) { /* create the input item */ input_item_t *p_input = input_item_NewExt( p_demux, psz_mrl, psz_title, 0, NULL, 0, i_duration ); input_item_AddSubItem( p_current_input, p_input ); FREENULL( psz_mrl ); FREENULL( psz_title ); i_duration = -1; #define SET(variable, type) \ if( !EMPTY_STR(variable) ) \ { \ input_item_Set##type( p_input, variable ); \ FREENULL( variable ); \ } /* set the meta */ SET( psz_genre, Genre ); SET( psz_tracknum, TrackNum ); SET( psz_language, Language ); SET( psz_artist, Artist ); SET( psz_album, Album ); SET( psz_date, Date ); SET( psz_encodedby, EncodedBy ); SET( psz_description, Description ); SET( psz_copyright, Copyright ); #undef SET } else msg_Warn( p_demux, "invalid line '%s'", psz_parse ); /* Fetch another line */ free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); } vlc_gc_decref(p_current_input); var_Destroy( p_demux, "zpl-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
/** * Main demux callback function * @param p_demux: this demux object */ static int Demux( demux_t *p_demux ) { char *psz_line; char *psz_artist = NULL, *psz_album = NULL, *psz_genre = NULL, *psz_year = NULL; char *psz_author = NULL, *psz_title = NULL, *psz_copyright = NULL, *psz_cdnum = NULL, *psz_comments = NULL; int i_parsed_duration = 0; mtime_t i_duration = -1; const char **ppsz_options = NULL; int i_options = 0, i_start = 0, i_stop = 0; bool b_cleanup = false; input_item_t *p_input; input_item_t *p_current_input = GetCurrentItem(p_demux); psz_line = stream_ReadLine( p_demux->s ); while( psz_line ) { char *psz_parse = psz_line; /* Skip leading tabs and spaces */ while( *psz_parse == ' ' || *psz_parse == '\t' || *psz_parse == '\n' || *psz_parse == '\r' ) psz_parse++; if( *psz_parse == '#' ) { /* Ignore comments */ } else if( *psz_parse ) { char *psz_mrl, *psz_option_next, *psz_option; char *psz_param, *psz_value; /* Get the MRL from the file. Note that this might contain parameters of form ?param1=value1¶m2=value2 in a RAM file */ psz_mrl = ProcessMRL( psz_parse, p_demux->p_sys->psz_prefix ); b_cleanup = true; if ( !psz_mrl ) goto error; /* We have the MRL, now we have to check for options and parse them from MRL */ psz_option = strchr( psz_mrl, '?' ); /* Look for start of options */ if( psz_option ) { /* Remove options from MRL because VLC can't get the file otherwise */ *psz_option = '\0'; psz_option++; psz_option_next = psz_option; while( 1 ) /* Process each option */ { /* Look for end of first option which maybe a & or \0 */ psz_option = psz_option_next; psz_option_next = strchr( psz_option, '&' ); if( psz_option_next ) { *psz_option_next = '\0'; psz_option_next++; } else psz_option_next = strchr( psz_option, '\0' ); /* Quit if options are over */ if( psz_option_next == psz_option ) break; /* Parse out param and value */ psz_param = psz_option; psz_value = strchr( psz_option, '=' ); if( psz_value == NULL ) break; *psz_value = '\0'; psz_value++; /* Take action based on parameter value in the below if else structure */ /* TODO: Remove any quotes surrounding values if required */ if( !strcmp( psz_param, "clipinfo" ) ) { ParseClipInfo( psz_value, &psz_artist, &psz_title, &psz_album, &psz_genre, &psz_year, &psz_cdnum, &psz_comments ); /* clipinfo has various sub parameters, which is parsed by this function */ } else if( !strcmp( psz_param, "author" ) ) psz_author = decode_URI(psz_value); else if( !strcmp( psz_param, "start" ) ) { i_start = ParseTime( psz_value, strlen( psz_value ) ); char *temp; if( i_start ) { if( asprintf( &temp, ":start-time=%d", i_start ) != -1 ) INSERT_ELEM( ppsz_options, i_options, i_options, temp ); } } else if( !strcmp( psz_param, "end" ) ) { i_stop = ParseTime( psz_value, strlen( psz_value ) ); char *temp; if( i_stop ) { if( asprintf( &temp, ":stop-time=%d", i_stop ) != -1 ) INSERT_ELEM( ppsz_options, i_options, i_options, temp ); } } else if( !strcmp( psz_param, "title" ) ) psz_title = decode_URI(psz_value); else if( !strcmp( psz_param, "copyright" ) ) psz_copyright = decode_URI(psz_value); else { /* TODO: insert option anyway? Currently ignores*/ /* INSERT_ELEM( ppsz_options, i_options, i_options, psz_option ); */ } } } /* Create the input item and pump in all the options into playlist item */ p_input = input_item_NewExt( p_demux, psz_mrl, psz_title, i_options, ppsz_options, 0, i_duration ); if( !EMPTY_STR( psz_artist ) ) input_item_SetArtist( p_input, psz_artist ); if( !EMPTY_STR( psz_author ) ) input_item_SetPublisher( p_input, psz_author ); if( !EMPTY_STR( psz_title ) ) input_item_SetTitle( p_input, psz_title ); if( !EMPTY_STR( psz_copyright ) ) input_item_SetCopyright( p_input, psz_copyright ); if( !EMPTY_STR( psz_album ) ) input_item_SetAlbum( p_input, psz_album ); if( !EMPTY_STR( psz_genre ) ) input_item_SetGenre( p_input, psz_genre ); if( !EMPTY_STR( psz_year ) ) input_item_SetDate( p_input, psz_copyright ); if( !EMPTY_STR( psz_cdnum ) ) input_item_SetTrackNum( p_input, psz_cdnum ); if( !EMPTY_STR( psz_comments ) ) input_item_SetDescription( p_input, psz_comments ); input_item_AddSubItem( p_current_input, p_input ); vlc_gc_decref( p_input ); free( psz_mrl ); } error: /* Fetch another line */ free( psz_line ); psz_line = stream_ReadLine( p_demux->s ); if( !psz_line ) b_cleanup = true; if( b_cleanup ) { /* Cleanup state */ while( i_options-- ) free( (char*)ppsz_options[i_options] ); FREENULL( ppsz_options ); FREENULL( psz_artist ); FREENULL( psz_title ); FREENULL( psz_author ); FREENULL( psz_copyright ); FREENULL( psz_album ); FREENULL( psz_genre ); FREENULL( psz_year ); FREENULL( psz_cdnum ); FREENULL( psz_comments ); i_options = 0; i_parsed_duration = 0; i_duration = -1; i_start = 0; i_stop = 0; b_cleanup = false; } } vlc_gc_decref(p_current_input); var_Destroy( p_demux, "m3u-extvlcopt" ); return 0; /* Needed for correct operation of go back */ }
/***************************************************************************** * ItemChange: Playlist item change callback *****************************************************************************/ static int ItemChange( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ) { VLC_UNUSED(psz_var); VLC_UNUSED(oldval); VLC_UNUSED(newval); char psz_tmp[MAX_LENGTH]; char psz_notify[MAX_LENGTH]; char *psz_title = NULL; char *psz_artist = NULL; char *psz_album = NULL; char *psz_arturl = NULL; input_thread_t *p_input = playlist_CurrentInput( (playlist_t*) p_this ); intf_thread_t *p_intf = param; intf_sys_t *p_sys = p_intf->p_sys; if( !p_input ) return VLC_SUCCESS; if( p_input->b_dead ) { /* Not playing anything ... */ vlc_object_release( p_input ); return VLC_SUCCESS; } /* Wait a tad so the meta has been fetched * FIXME that's awfully wrong */ msleep( 1000*4 ); /* Playing something ... */ input_item_t *p_input_item = input_GetItem( p_input ); psz_artist = input_item_GetArtist( p_input_item ); psz_album = input_item_GetAlbum( p_input_item ); psz_title = input_item_GetTitleFbName( p_input_item ); if( EMPTY_STR( psz_title ) ) { /* Not enough metadata ... */ free( psz_title ); free( psz_artist ); free( psz_album ); vlc_object_release( p_input ); return VLC_SUCCESS; } if( EMPTY_STR( psz_artist ) ) { free( psz_artist ); psz_artist = NULL; } if( EMPTY_STR( psz_album ) ) { free( psz_album ); psz_album = NULL; } if( psz_artist && psz_album ) snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s\n[%s]", psz_title, psz_artist, psz_album ); else if( psz_artist ) snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>\n%s", psz_title, psz_artist ); else snprintf( psz_tmp, MAX_LENGTH, "<b>%s</b>", psz_title ); free( psz_title ); free( psz_artist ); free( psz_album ); GdkPixbuf *pix = NULL; psz_arturl = input_item_GetArtURL( p_input_item ); vlc_object_release( p_input ); if( psz_arturl && !strncmp( psz_arturl, "file://", 7 ) && decode_URI( psz_arturl + 7 ) ) { /* scale the art to show it in notify popup */ GError *p_error = NULL; pix = gdk_pixbuf_new_from_file_at_scale( &psz_arturl[7], 72, 72, TRUE, &p_error ); } else /* else we show state-of-the art logo */ { GError *p_error = NULL; char *psz_pixbuf; if( asprintf( &psz_pixbuf, "%s/vlc48x48.png", config_GetDataDir() ) >= 0 ) { pix = gdk_pixbuf_new_from_file( psz_pixbuf, &p_error ); free( psz_pixbuf ); } } free( psz_arturl ); /* we need to replace '&' with '&' because '&' is a keyword of * notification-daemon parser */ const int i_len = strlen( psz_tmp ); int i_notify = 0; for( int i = 0; i < i_len && i_notify < ( MAX_LENGTH - 5 ); i++ ) { /* we use MAX_LENGTH - 5 because if the last char of psz_tmp is '&' * we will need 5 more characters: 'amp;\0' . * however that's unlikely to happen because the last char is '\0' */ if( psz_tmp[i] != '&' ) { psz_notify[i_notify] = psz_tmp[i]; } else { snprintf( &psz_notify[i_notify], 6, "&" ); i_notify += 4; } i_notify++; } psz_notify[i_notify] = '\0'; vlc_mutex_lock( &p_sys->lock ); Notify( p_this, psz_notify, pix, p_intf ); vlc_mutex_unlock( &p_sys->lock ); return VLC_SUCCESS; }
static int WriteCatalog( addons_storage_t *p_storage, addon_entry_t **pp_entries, int i_entries ) { addon_entry_t *p_entry; char *psz_file; char *psz_tempstring = NULL; char *psz_userdir = config_GetUserDir( VLC_DATA_DIR ); if ( !psz_userdir ) return VLC_ENOMEM; if ( asprintf( &psz_file, "%s%s", psz_userdir, ADDONS_CATALOG ) < 1 ) { free( psz_userdir ); return VLC_ENOMEM; } free( psz_userdir ); char *psz_path = strdup( psz_file ); if ( !psz_path ) { free( psz_file ); return VLC_ENOMEM; } char *psz_buf = strrchr( psz_path, DIR_SEP_CHAR ); if( psz_buf ) { *++psz_buf = '\0'; /* ensure directory exists */ if( !EMPTY_STR( psz_path ) ) recursive_mkdir( VLC_OBJECT(p_storage), psz_path ); free( psz_path ); } FILE *p_catalog = vlc_fopen( psz_file, "wt" ); free( psz_file ); if ( !p_catalog ) return VLC_EGENERIC; /* write XML header */ fprintf( p_catalog, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); fprintf( p_catalog, "<videolan xmlns=\"http://videolan.org/ns/vlc/addons/1.0\">\n" ); fprintf( p_catalog, "\t<addons>\n" ); for ( int i=0; i<i_entries; i++ ) { p_entry = pp_entries[i]; vlc_mutex_lock( &p_entry->lock ); if ( ( p_entry->e_state != ADDON_INSTALLED ) || !( p_entry->e_flags & ADDON_MANAGEABLE ) ) { vlc_mutex_unlock( &p_entry->lock ); continue; } if ( p_entry->psz_source_module ) psz_tempstring = convert_xml_special_chars( p_entry->psz_source_module ); char *psz_uuid = addons_uuid_to_psz( ( const addon_uuid_t * ) & p_entry->uuid ); fprintf( p_catalog, "\t\t<addon source=\"%s\" type=\"%s\" id=\"%s\" " "downloads=\"%ld\" score=\"%ld\"", ( psz_tempstring ) ? psz_tempstring : "", getTypePsz( p_entry->e_type ), psz_uuid, p_entry->i_downloads, p_entry->i_score ); free( psz_uuid ); free( psz_tempstring ); WRITE_WITH_ENTITIES( " version=\"%s\">\n", p_entry->psz_version ) WRITE_WITH_ENTITIES( "\t\t\t<name>%s</name>\n", p_entry->psz_name ) WRITE_WITH_ENTITIES( "\t\t\t<summary>%s</summary>\n", p_entry->psz_summary ) if ( p_entry->psz_description ) { psz_tempstring = p_entry->psz_description; /* FIXME: do real escaping */ while( ( psz_tempstring = strstr( psz_tempstring, "]]>" ) ) ) *psz_tempstring = ' '; fprintf( p_catalog, "\t\t\t<description><![CDATA[%s]]></description>\n", p_entry->psz_description ); } WRITE_WITH_ENTITIES( "\t\t\t<image>%s</image>\n", p_entry->psz_image_data ) WRITE_WITH_ENTITIES( "\t\t\t<archive>%s</archive>\n", p_entry->psz_archive_uri ) fprintf( p_catalog, "\t\t\t<authorship>\n" ); WRITE_WITH_ENTITIES( "\t\t\t\t<creator>%s</creator>\n", p_entry->psz_author ) WRITE_WITH_ENTITIES( "\t\t\t\t<sourceurl>%s</sourceurl>\n", p_entry->psz_source_uri ) fprintf( p_catalog, "\t\t\t</authorship>\n" ); FOREACH_ARRAY( addon_file_t *p_file, p_entry->files ) psz_tempstring = convert_xml_special_chars( p_file->psz_filename ); fprintf( p_catalog, "\t\t\t<resource type=\"%s\">%s</resource>\n", getTypePsz( p_file->e_filetype ), psz_tempstring ); free( psz_tempstring ); FOREACH_END(); fprintf( p_catalog, "\t\t</addon>\n" ); vlc_mutex_unlock( &p_entry->lock ); } fprintf( p_catalog, "\t</addons>\n" ); fprintf( p_catalog, "</videolan>\n" ); fclose( p_catalog ); return VLC_SUCCESS; }