Exemple #1
0
/* Enqueue an item for preparsing, and play it, if needed */
static void GoAndPreparse( playlist_t *p_playlist, int i_mode,
                           playlist_item_t *p_item )
{
    PL_ASSERT_LOCKED;
    if( (i_mode & PLAYLIST_GO ) )
    {
        pl_priv(p_playlist)->request.b_request = true;
        pl_priv(p_playlist)->request.i_skip = 0;
        pl_priv(p_playlist)->request.p_item = p_item;
        if( pl_priv(p_playlist)->p_input )
            input_Stop( pl_priv(p_playlist)->p_input, true );
        pl_priv(p_playlist)->request.i_status = PLAYLIST_RUNNING;
        vlc_cond_signal( &pl_priv(p_playlist)->signal );
    }
    /* Preparse if no artist/album info, and hasn't been preparsed allready
       and if user has some preparsing option (auto-preparse variable)
       enabled*/
    char *psz_artist = input_item_GetArtist( p_item->p_input );
    char *psz_album = input_item_GetAlbum( p_item->p_input );
    if( pl_priv(p_playlist)->b_auto_preparse &&
        input_item_IsPreparsed( p_item->p_input ) == false &&
            ( EMPTY_STR( psz_artist ) || ( EMPTY_STR( psz_album ) ) )
          )
        playlist_PreparseEnqueue( p_playlist, p_item->p_input );
    free( psz_artist );
    free( psz_album );
}
static int media_parse(libvlc_media_t *media)
{
    /* TODO: fetcher and parser independent of playlist */
    playlist_t *playlist =
        libvlc_priv (media->p_libvlc_instance->p_libvlc_int)->p_playlist;

    /* TODO: Fetch art on need basis. But how not to break compatibility? */
    playlist_AskForArtEnqueue(playlist, media->p_input_item );
    return playlist_PreparseEnqueue(playlist, media->p_input_item);
}
Exemple #3
0
/**************************************************************************
 * Preparse if not already done (Private)
 **************************************************************************/
static void preparse_if_needed( libvlc_media_t *p_md )
{
    /* XXX: need some locking here */
    if (!p_md->has_asked_preparse)
    {
        playlist_PreparseEnqueue(
                libvlc_priv (p_md->p_libvlc_instance->p_libvlc_int)->p_playlist,
                p_md->p_input_item );
        p_md->has_asked_preparse = true;
    }
}
Exemple #4
0
/**
 * Add a playlist item to a given node (in the category view )
 *
 * \param p_playlist the playlist to insert into
 * \param p_item the playlist item to insert
 * \param i_view the view for which to add or TODO: ALL_VIEWS
 * \param p_parent the parent node
 * \param i_mode the mode used when adding
 * \param i_pos the possition in the node where to add. If this is
 *        PLAYLIST_END the item will be added at the end of the node
 ** \return The id of the playlist item
 */
int playlist_NodeAddItem( playlist_t *p_playlist, playlist_item_t *p_item,
                          int i_view,playlist_item_t *p_parent,
                          int i_mode, int i_pos)
{
    vlc_value_t val;
    int i_position;
    playlist_view_t *p_view;

    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));

    vlc_mutex_lock( &p_playlist->object_lock );

    if ( i_pos == PLAYLIST_END ) i_pos = -1;

    /* Sanity checks */
    if( !p_parent || p_parent->i_children == -1 )
    {
        msg_Err( p_playlist, "invalid node" );
    }

    /*
     * CHECK_INSERT : checks if the item is already enqued before
     * enqueing it
     */
    if ( i_mode & PLAYLIST_CHECK_INSERT )
    {
         int j;

        if ( p_playlist->pp_items )
        {
            for ( j = 0; j < p_playlist->i_size; j++ )
            {
                if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri,
                              p_item->input.psz_uri ) )
                {
                    playlist_ItemDelete( p_item );
                    vlc_mutex_unlock( &p_playlist->object_lock );
                    free( p_add );
                    return -1;
                }
            }
        }
        i_mode &= ~PLAYLIST_CHECK_INSERT;
        i_mode |= PLAYLIST_APPEND;
    }

    msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )",
             p_item->input.psz_name, p_item->input.psz_uri );

    p_item->input.i_id = ++p_playlist->i_last_id;

    /* First, add the item at the right position in the item bank */
    /* WHY THAT ? */
     //i_position = p_playlist->i_index == -1 ? 0 : p_playlist->i_index;
    i_position = p_playlist->i_size ;

    INSERT_ELEM( p_playlist->pp_items,
                 p_playlist->i_size,
                 i_position,
                 p_item );
    INSERT_ELEM( p_playlist->pp_all_items,
                 p_playlist->i_all_size,
                 p_playlist->i_all_size,
                 p_item );
    p_playlist->i_enabled ++;

    /* TODO: Handle modes */
    playlist_NodeInsert( p_playlist, i_view, p_item, p_parent, i_pos );

    p_add->i_item = p_item->input.i_id;
    p_add->i_node = p_parent->input.i_id;
    p_add->i_view = i_view;
    val.p_address = p_add;
    var_Set( p_playlist, "item-append", val );

    /* We update the ALL view directly */
    p_view = playlist_ViewFind( p_playlist, VIEW_ALL );
    playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root );
    playlist_ViewUpdate( p_playlist, VIEW_ALL );

    /* TODO : Update sorted views*/

    if( i_mode & PLAYLIST_GO )
    {
        p_playlist->request.b_request = VLC_TRUE;
        p_playlist->request.i_view = VIEW_CATEGORY;
        p_playlist->request.p_node = p_parent;
        p_playlist->request.p_item = p_item;
        if( p_playlist->p_input )
        {
            input_StopThread( p_playlist->p_input );
        }
        p_playlist->status.i_status = PLAYLIST_RUNNING;
    }
    if( i_mode & PLAYLIST_PREPARSE &&
        var_CreateGetBool( p_playlist, "auto-preparse" ) )
    {
        playlist_PreparseEnqueue( p_playlist, &p_item->input );
    }

    vlc_mutex_unlock( &p_playlist->object_lock );

    val.b_bool = VLC_TRUE;
//    var_Set( p_playlist, "intf-change", val );
//
    free( p_add );

    return p_item->input.i_id;
}
Exemple #5
0
/**
 * Add a playlist item into a playlist
 *
 * \param p_playlist the playlist to insert into
 * \param p_item the playlist item to insert
 * \param i_mode the mode used when adding
 * \param i_pos the possition in the playlist where to add. If this is
 *        PLAYLIST_END the item will be added at the end of the playlist
 *        regardless of it's size
 * \return The id of the playlist item
 */
int playlist_AddItem( playlist_t *p_playlist, playlist_item_t *p_item,
                      int i_mode, int i_pos)
{
    vlc_value_t val;
    vlc_bool_t b_end = VLC_FALSE;
    playlist_view_t *p_view = NULL;

    playlist_add_t *p_add = (playlist_add_t *)malloc(sizeof( playlist_add_t));

    vlc_mutex_lock( &p_playlist->object_lock );

    /*
     * CHECK_INSERT : checks if the item is already enqued before
     * enqueing it
     */

    /* That should not change */
    if ( i_mode & PLAYLIST_CHECK_INSERT )
    {
         int j;

        if ( p_playlist->pp_items )
        {
            for ( j = 0; j < p_playlist->i_size; j++ )
            {
                if ( !strcmp( p_playlist->pp_items[j]->input.psz_uri,
                               p_item->input.psz_uri ) )
                {
                    playlist_ItemDelete( p_item );
                    vlc_mutex_unlock( &p_playlist->object_lock );
                    return -1;
                }
             }
         }
         i_mode &= ~PLAYLIST_CHECK_INSERT;
         i_mode |= PLAYLIST_APPEND;
    }

    msg_Dbg( p_playlist, "adding playlist item `%s' ( %s )",
             p_item->input.psz_name, p_item->input.psz_uri );

    p_item->input.i_id = ++p_playlist->i_last_id;

    /* Do a few boundary checks and allocate space for the item */
    if( i_pos == PLAYLIST_END )
    {
        b_end = VLC_TRUE;
        if( i_mode & PLAYLIST_INSERT )
        {
            i_mode &= ~PLAYLIST_INSERT;
            i_mode |= PLAYLIST_APPEND;
        }

        i_pos = p_playlist->i_size - 1;
    }

    if( !(i_mode & PLAYLIST_REPLACE)
         || i_pos < 0 || i_pos >= p_playlist->i_size )
    {
        /* Additional boundary checks */
        if( i_mode & PLAYLIST_APPEND )
        {
            i_pos++;
        }

        if( i_pos < 0 )
        {
            i_pos = 0;
        }
        else if( i_pos > p_playlist->i_size )
        {
            i_pos = p_playlist->i_size;
        }

        INSERT_ELEM( p_playlist->pp_items, p_playlist->i_size, i_pos, p_item );
        INSERT_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size,
                     p_playlist->i_all_size, p_item );
        p_playlist->i_enabled ++;

        /* We update the ALL view directly */
        playlist_ViewUpdate( p_playlist, VIEW_ALL );

        /* Add the item to the General category */
        if( b_end == VLC_TRUE )
        {
            playlist_NodeAppend( p_playlist, VIEW_CATEGORY, p_item,
                                 p_playlist->p_general );
            p_add->i_item = p_item->input.i_id;
            p_add->i_node = p_playlist->p_general->input.i_id;
            p_add->i_view = VIEW_CATEGORY;
            val.p_address = p_add;
            var_Set( p_playlist, "item-append", val );
        }
        else
        {
            playlist_NodeInsert( p_playlist, VIEW_CATEGORY, p_item,
                                 p_playlist->p_general, i_pos );
        }


        p_view = playlist_ViewFind( p_playlist, VIEW_ALL );
        playlist_ItemAddParent( p_item, VIEW_ALL, p_view->p_root );

        /* FIXME : Update sorted views */

        if( p_playlist->i_index >= i_pos )
        {
            p_playlist->i_index++;
        }
    }
    else
    {
        msg_Err( p_playlist, "Insert mode not implemented" );
    }

    if( (i_mode & PLAYLIST_GO ) && p_view )
    {
        p_playlist->request.b_request = VLC_TRUE;
        /* FIXME ... */
        p_playlist->request.i_view = VIEW_CATEGORY;
        p_playlist->request.p_node = p_view->p_root;
        p_playlist->request.p_item = p_item;

        if( p_playlist->p_input )
        {
            input_StopThread( p_playlist->p_input );
        }
        p_playlist->status.i_status = PLAYLIST_RUNNING;
    }

    if( i_mode & PLAYLIST_PREPARSE &&
        var_CreateGetBool( p_playlist, "auto-preparse" ) )
    {
        playlist_PreparseEnqueue( p_playlist, &p_item->input );
    }

    vlc_mutex_unlock( &p_playlist->object_lock );

    if( b_end == VLC_FALSE )
    {
        val.b_bool = VLC_TRUE;
        var_Set( p_playlist, "intf-change", val );
    }

    free( p_add );

    return p_item->input.i_id;
}
Exemple #6
0
/**
 * @brief Scan files in a particular directory
 */
static void ScanFiles( monitoring_thread_t *p_mon, int i_dir_id,
                       bool b_recursive, stat_list_t *stparent )
{
    int i_rows, i_cols, i_dir_content, i, i_mon_rows, i_mon_cols;
    char **ppsz_monitored_files;
    char **pp_results, *psz_dir;
    char **pp_dir_content;
    bool *pb_processed;
    input_item_t *p_input;
    struct stat s_stat;
    media_library_t *p_ml = (media_library_t *)p_mon->p_ml;

    Query( p_ml, &pp_results, &i_rows, &i_cols,
              "SELECT uri AS directory_uri FROM directories WHERE id = '%d'",
              i_dir_id );
    if( i_rows < 1 )
    {
        msg_Dbg( p_mon, "query returned no directory for dir_id: %d (%s:%d)",
                 i_dir_id, __FILE__, __LINE__ );
        return;
    }
    psz_dir = strdup( pp_results[1] );
    FreeSQLResult( p_ml, pp_results );

    struct stat_list_t stself;

    if( vlc_stat( psz_dir, &stself.st ) == -1 )
    {
        msg_Err( p_ml, "Cannot stat `%s': %m", psz_dir );
        free( psz_dir );
        return;
    }
#ifndef WIN32
    for( stat_list_t *stats = stparent; stats != NULL; stats = stats->parent )
    {
        if( ( stself.st.st_ino == stats->st.st_ino ) &&
            ( stself.st.st_dev == stats->st.st_dev ) )
        {
            msg_Warn( p_ml, "Ignoring infinitely recursive directory `%s'",
                      psz_dir );
            free( psz_dir );
            return;
        }
    }
#else
    /* Windows has st_dev (driver letter - 'A'), but it zeroes st_ino,
     * so that the test above will always incorrectly succeed.
     * Besides, Windows does not have dirfd(). */
#endif
    stself.parent = stparent;

    QuerySimple( p_ml, "UPDATE directories SET timestamp=%d WHERE id = %d",
                    stself.st.st_mtime, i_dir_id );
    Query( p_ml, &ppsz_monitored_files, &i_mon_rows, &i_mon_cols,
              "SELECT id AS media_id, timestamp AS media_ts, uri AS media_uri "
              "FROM media WHERE directory_id = %d",
              i_dir_id );
    pb_processed = malloc(sizeof(bool) * i_mon_rows);
    for( i = 0; i < i_mon_rows ; i++)
        pb_processed[i] = false;

    i_dir_content = vlc_scandir( psz_dir, &pp_dir_content, NULL, Sort );
    if( i_dir_content == -1 )
    {
        msg_Err( p_mon, "Cannot read `%s': %m", psz_dir );
        free( pb_processed );
        free( psz_dir );
        return;
    }
    else if( i_dir_content == 0 )
    {
        msg_Dbg( p_mon, "Nothing in directory `%s'", psz_dir );
        free( pb_processed );
        free( psz_dir );
        return;
    }

    for( i = 0; i < i_dir_content; i++ )
    {
        const char *psz_entry = pp_dir_content[i];

        if( psz_entry[0] != '.' )
        {
            /* 7 is the size of "file://" */
            char psz_uri[strlen(psz_dir) + strlen(psz_entry) + 2 + 7];
            sprintf( psz_uri, "%s/%s", psz_dir, psz_entry );

            if( vlc_stat( psz_uri, &s_stat ) == -1 )
            {
                msg_Err( p_mon, "%s: %m", psz_uri );
                free( pb_processed );
                free( psz_dir );
                return;
            }

            if( S_ISREG( s_stat.st_mode ) )
            {
                const char *psz_dot = strrchr( psz_uri, '.' );
                if( psz_dot++ && *psz_dot )
                {
                    int i_is_media = 0;
                    for( int a = 0; ppsz_MediaExtensions[a]; a++ )
                    {
                        if( !strcasecmp( psz_dot, ppsz_MediaExtensions[a] ) )
                        {
                            i_is_media = 1;
                            break;
                        }
                    }
                    if( !i_is_media )
                    {
                        msg_Dbg( p_mon, "ignoring file %s", psz_uri );
                        continue;
                    }
                }

                char * psz_tmp = encode_URI_component( psz_uri );
                char * psz_encoded_uri = ( char * )calloc( strlen( psz_tmp ) + 9, 1 );
                strcpy( psz_encoded_uri, "file:///" );
                strcat( psz_encoded_uri, psz_tmp );
                free( psz_tmp );

                /* Check if given media is already in DB and it has been updated */
                bool b_skip = false;
                bool b_update = false;
                int j = 1;
                for( j = 1; j <= i_mon_rows; j++ )
                {
                    if( strcasecmp( ppsz_monitored_files[ j * i_mon_cols + 2 ],
                                    psz_encoded_uri ) != 0 )
                        continue;
                    b_update = true;
                    pb_processed[ j - 1 ] = true;
                    if( atoi( ppsz_monitored_files[ j * i_mon_cols + 1 ] )
                        < s_stat.st_mtime )
                    {
                        b_skip = false;
                        break;
                    }
                    else
                    {
                        b_skip = true;
                        break;
                    }
                }
                msg_Dbg( p_ml , "Checking if %s is in DB. Found: %d", psz_encoded_uri,
                         b_skip? 1 : 0 );
                if( b_skip )
                    continue;

                p_input = input_item_New( psz_encoded_uri, psz_entry );

                playlist_t* p_pl = pl_Get( p_mon );
                preparsed_item_t* p_itemobject;
                p_itemobject = malloc( sizeof( preparsed_item_t ) );
                p_itemobject->i_dir_id = i_dir_id;
                p_itemobject->psz_uri = psz_encoded_uri;
                p_itemobject->i_mtime = s_stat.st_mtime;
                p_itemobject->p_mon = p_mon;
                p_itemobject->b_update = b_update;
                p_itemobject->i_update_id = b_update ?
                    atoi( ppsz_monitored_files[ j * i_mon_cols + 0 ] ) : 0 ;

                vlc_event_manager_t *p_em = &p_input->event_manager;
                vlc_event_attach( p_em, vlc_InputItemPreparsedChanged,
                      PreparseComplete, p_itemobject );
                playlist_PreparseEnqueue( p_pl, p_input );
            }
            else if( S_ISDIR( s_stat.st_mode ) && b_recursive )
            {
                Query( p_ml, &pp_results, &i_rows, &i_cols,
                        "SELECT id AS directory_id FROM directories "
                        "WHERE uri=%Q", psz_uri );
                FreeSQLResult( p_ml, pp_results );

                if( i_rows <= 0 )
                {
                    msg_Dbg( p_mon, "New directory `%s' in dir of id %d",
                             psz_uri, i_dir_id );
                    QuerySimple( p_ml,
                                    "INSERT INTO directories (uri, timestamp, "
                                    "recursive) VALUES(%Q, 0, 1)", psz_uri );

                    // We get the id of the directory we've just added
                    Query( p_ml, &pp_results, &i_rows, &i_cols,
                    "SELECT id AS directory_id FROM directories WHERE uri=%Q",
                              psz_uri );
                    if( i_rows <= 0 )
                    {
                        msg_Err( p_mon, "Directory `%s' was not sucessfully"
                                " added to the database", psz_uri );
                        FreeSQLResult( p_ml, pp_results );
                        continue;
                    }

                    ScanFiles( p_mon, atoi( pp_results[1] ), b_recursive,
                               &stself );
                    FreeSQLResult( p_ml, pp_results );
                }
            }
        }
    }

    vlc_array_t* delete_ids = vlc_array_new();
    for( i = 0; i < i_mon_rows; i++ )
    {
       if( !pb_processed[i] )
        {
            /* This file doesn't exist anymore. Let's...urm...delete it. */
            ml_element_t* find = ( ml_element_t* ) calloc( 1, sizeof( ml_element_t ) );
            find->criteria = ML_ID;
            find->value.i = atoi( ppsz_monitored_files[ (i + 1) * i_mon_cols ] );
            vlc_array_append( delete_ids, find );
       }
    }

    /* Delete the unfound media */
    if( Delete( p_ml, delete_ids ) != VLC_SUCCESS )
        msg_Dbg( p_ml, "Something went wrong in multi delete" );

    for( i = 0; i < vlc_array_count( delete_ids ); i++ )
    {
       free( vlc_array_item_at_index( delete_ids, i ) );
    }
    vlc_array_destroy( delete_ids );

    FreeSQLResult( p_ml, ppsz_monitored_files );
    for( i = 0; i < i_dir_content; i++ )
        free( pp_dir_content[i] );
    free( pp_dir_content );
    free( psz_dir );
    free( pb_processed );
}