Commit 79990b94 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

media library: good riddance

Big pile of non-sensical and unmaintained code.
parent 8e3288f9
......@@ -3967,7 +3967,6 @@ AC_ARG_ENABLE(media-library,
AS_IF([test "${enable_media_library}" = "yes"], [
AC_DEFINE([MEDIA_LIBRARY], 1, [Define if you want to use the VLC media library])
VLC_ADD_CPPFLAGS([qt4],"-DMEDIA_LIBRARY")
VLC_ADD_PLUGIN([media_library])
dnl
dnl SQLite
......@@ -4135,7 +4134,6 @@ AC_CONFIG_FILES([
modules/lua/Makefile
modules/meta_engine/Makefile
modules/misc/Makefile
modules/media_library/Makefile
modules/mux/Makefile
modules/notify/Makefile
modules/packetizer/Makefile
......
......@@ -192,7 +192,6 @@ $Id$
* magnify: zoom video filter
* marq: Overlays a marquee on the video
* mash: OpenMash based decoder
* media_library: a sql based media library
* mediacodec: Android Jelly Bean MediaCodec decoder module
* mediadirs: Picture/Music/Video user directories as service discoveries
* minimal_macosx: a minimal Mac OS X GUI, using the FrameWork
......
......@@ -10,7 +10,6 @@ BASE_SUBDIRS = \
gui \
meta_engine \
misc \
media_library \
notify \
packetizer \
services_discovery \
......
SOURCES_media_library = sql_media_library.c \
sql_media_library.h \
sql_monitor.c \
sql_search.c \
sql_add.c \
sql_update.c \
sql_delete.c \
item_list.c \
item_list.h \
ml_watch.c \
media_pool.c
/*****************************************************************************
* item_list.c: An input_item_t+media_id couple list for the media library
*****************************************************************************
* Copyright (C) 2008-2010 the VideoLAN Team and AUTHORS
* $Id$
*
* Authors: Antoine Lejeune <phytos@videolan.org>
* Jean-Philippe André <jpeg@videolan.org>
* Rémi Duraffort <ivoire@videolan.org>
* Adrien Maglo <magsoft@videolan.org>
* Srikanth Raju <srikiraju at gmail dot com>
*
* 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.
*****************************************************************************/
#include "sql_media_library.h"
#include "item_list.h"
/**
* @short item hash list for the media library monitoring system
*/
/**
* @brief Add an item to the head of the list
* @param p_ml
* @param p_media media object. ID must be non zero and valid
* @param p_item input item to add, MUST NOT be NULL
* @param locked flag set if the list is locked. do not use
* @return VLC_SUCCESS or VLC_EGENERIC
*/
int __item_list_add( watch_thread_t *p_wt, ml_media_t* p_media, input_item_t *p_item,
bool locked )
{
if( !locked )
vlc_mutex_lock( &p_wt->list_mutex );
ml_LockMedia( p_media );
assert( p_media->i_id );
/* Ensure duplication does not occur */
il_foreachlist( p_wt->p_hlist[ item_hash( p_item ) ], p_elt )
{
if( p_elt->p_item->i_id == p_item->i_id )
{
ml_UnlockMedia( p_media );
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return VLC_EGENERIC;
}
}
item_list_t *p_new = ( item_list_t* ) calloc( 1, sizeof( item_list_t ) );
if( !p_new )
{
ml_UnlockMedia( p_media );
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return VLC_ENOMEM;
}
p_new->p_next = p_wt->p_hlist[ item_hash( p_item ) ];
p_new->i_refs = 1;
p_new->i_media_id = p_media->i_id;
p_new->p_media = p_media;
p_new->p_item = p_item;
p_wt->p_hlist[ item_hash( p_item ) ] = p_new;
ml_UnlockMedia( p_media );
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return VLC_SUCCESS;
}
/**
* @brief Delete an item from the list
* @param p_ml this media library
* @param i_media_id media library's media ID
*/
item_list_t* item_list_delMedia( watch_thread_t *p_wt, int i_media_id )
{
vlc_mutex_lock( &p_wt->list_mutex );
item_list_t *p_prev = NULL;
il_foreachhashlist( p_wt->p_hlist, p_elt, ixx )
{
if( p_elt->i_media_id == i_media_id )
{
if( p_prev )
p_prev->p_next = p_elt->p_next;
else
p_wt->p_hlist[ixx] = p_elt->p_next;
p_elt->p_next = NULL;
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt;
}
else
{
p_prev = p_elt;
}
}
vlc_mutex_unlock( &p_wt->list_mutex );
return NULL;
}
/**
* @brief Delete an item from the list and return the single element
* @param p_ml this media library
* @param p_item item to delete
* @return The element from the list containing p_item
*/
item_list_t* item_list_delItem( watch_thread_t *p_wt, input_item_t *p_item, bool locked )
{
if( !locked )
vlc_mutex_lock( &p_wt->list_mutex );
item_list_t *p_prev = NULL;
il_foreachlist( p_wt->p_hlist[ item_hash( p_item ) ], p_elt )
{
if( p_elt->p_item == p_item )
{
if( p_prev )
p_prev->p_next = p_elt->p_next;
else
p_wt->p_hlist[ item_hash( p_item ) ] = p_elt->p_next;
p_elt->p_next = NULL;
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt;
}
else
{
p_prev = p_elt;
}
}
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return NULL;
}
/**
* @brief Find an input item
* @param p_ml this media library
* @param i_media_id item to find and gc_incref
* @return input item if found, NULL if not found
*/
input_item_t* item_list_itemOfMediaId( watch_thread_t *p_wt, int i_media_id )
{
item_list_t* p_tmp = item_list_listitemOfMediaId( p_wt, i_media_id );
if( p_tmp )
return p_tmp->p_item;
else
return NULL;
}
/**
* @brief Find an item list item
* @param p_ml this media library
* @param i_media_id item to find and gc_incref
* @return input item if found, NULL if not found
*/
item_list_t* item_list_listitemOfMediaId( watch_thread_t *p_wt, int i_media_id )
{
vlc_mutex_lock( &p_wt->list_mutex );
il_foreachhashlist( p_wt->p_hlist, p_elt, ixx )
{
if( p_elt->i_media_id == i_media_id )
{
p_elt->i_age = 0;
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt;
}
}
vlc_mutex_unlock( &p_wt->list_mutex );
return NULL;
}
/**
* @brief Find a media
* @param p_ml this media library
* @param i_media_id item to find and gc_incref
* @return media if found. NULL otherwise
*/
ml_media_t* item_list_mediaOfMediaId( watch_thread_t *p_wt, int i_media_id )
{
item_list_t* p_tmp = item_list_listitemOfMediaId( p_wt, i_media_id );
if( p_tmp )
return p_tmp->p_media;
else
return NULL;
}
/**
* @brief Find a media ID by its input_item
* @param p_ml this media library
* @param p_item item to find
* @return media_id found, or VLC_EGENERIC
*/
int item_list_mediaIdOfItem( watch_thread_t *p_wt, input_item_t *p_item )
{
vlc_mutex_lock( &p_wt->list_mutex );
il_foreachlist( p_wt->p_hlist[ item_hash( p_item ) ], p_elt )
{
if( p_elt->p_item == p_item )
{
if( p_elt->i_media_id <= 0 )
/* TODO! */
p_elt->i_age = 0;
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt->i_media_id;
}
}
vlc_mutex_unlock( &p_wt->list_mutex );
return VLC_EGENERIC;
}
/**
* @brief Find a media by its input_item
* @param p_ml this media library
* @param p_item item to find
* @return media found, or VLC_EGENERIC
*/
ml_media_t* item_list_mediaOfItem( watch_thread_t *p_wt, input_item_t* p_item,
bool locked )
{
if( !locked )
vlc_mutex_lock( &p_wt->list_mutex );
il_foreachlist( p_wt->p_hlist[ item_hash( p_item ) ], p_elt )
{
if( p_elt->p_item == p_item )
{
p_wt->p_hlist[ item_hash( p_item ) ] = p_elt->p_next;
p_elt->p_next = NULL;
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt->p_media;
}
}
if( !locked )
vlc_mutex_unlock( &p_wt->list_mutex );
return NULL;
}
/**
* @brief Flag an item as updated
* @param p_ml this media library
* @param p_item item to find and flag
* @param b_played raise play count or not, update last play
* @return media_id found, or VLC_EGENERIC
*/
int item_list_updateInput( watch_thread_t *p_wt, input_item_t *p_item,
bool b_played )
{
vlc_mutex_lock( &p_wt->list_mutex );
il_foreachlist( p_wt->p_hlist[ item_hash( p_item ) ], p_elt )
{
if( p_elt->p_item == p_item )
{
/* Item found, flag and return */
p_elt->i_age = 0;
p_elt->i_update |= b_played ? 3 : 1;
vlc_mutex_unlock( &p_wt->list_mutex );
return p_elt->i_media_id;
}
}
vlc_mutex_unlock( &p_wt->list_mutex );
return VLC_EGENERIC;
}
/**
* @brief Free every item in the item list.
* @param p_wt Watch thread
* @note All decref of objects must be handled by watch system
*/
void item_list_destroy( watch_thread_t* p_wt )
{
vlc_mutex_lock( &p_wt->list_mutex );
for( int i = 0; i < ML_ITEMLIST_HASH_LENGTH ; i++ )
{
for( item_list_t* p_elt = p_wt->p_hlist[i] ; p_elt; p_elt = p_wt->p_hlist[i] )
{
p_wt->p_hlist[i] = p_elt->p_next;
free( p_elt );
}
}
vlc_mutex_unlock( &p_wt->list_mutex );
}
/*****************************************************************************
* item_list.h : Item list data structure for Watching system
*****************************************************************************
* Copyright (C) 2008-2010 the VideoLAN team and AUTHORS
* $Id$
*
* Authors: Srikanth Raju <srikiraju at gmail dot com>
*
* 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.
*****************************************************************************/
#ifndef ML_ITEM_LIST_H
#define ML_ITEM_LIST_H
#include <vlc_input.h>
#include <vlc_arrays.h>
struct watch_thread_t;
typedef struct watch_thread_t watch_thread_t;
typedef struct item_list_t item_list_t;
/**
* Definition of item_list_t
*/
struct item_list_t {
input_item_t *p_item; /**< Input item */
ml_media_t *p_media; /**< Media item */
item_list_t *p_next; /**< Next element in the list */
int i_media_id; /**< Media id */
int i_age; /**< Time spent in this list without activity */
int i_refs; /**< Number of important refs */
int i_update; /**< Flag set when the input item is updated:
0: no update,
1: meta update,
2: increment play count,
3: both */
};
#define ML_ITEMLIST_HASH_LENGTH 40
#define il_foreachhashlist( a, b, c ) \
for( int c = 0 ; c < ML_ITEMLIST_HASH_LENGTH ; c++ ) \
for( item_list_t* b = a[c]; b; b = b->p_next )
#define il_foreachlist( a, b ) for( item_list_t* b = a ; b; b = b->p_next )
#define item_list_add( a, b, c ) __item_list_add( a, b, c, false )
int __item_list_add( watch_thread_t *p_wt, ml_media_t* p_media,
input_item_t *p_item, bool );
item_list_t* item_list_delMedia( watch_thread_t *p_wt, int i_media_id );
item_list_t* item_list_delItem( watch_thread_t *p_wt, input_item_t *p_item, bool );
item_list_t* item_list_listitemOfMediaId( watch_thread_t *p_wt, int i_media_id );
input_item_t* item_list_itemOfMediaId( watch_thread_t *p_wt, int i_media_id );
ml_media_t* item_list_mediaOfMediaId( watch_thread_t *p_wt, int i_media_id );
ml_media_t* item_list_mediaOfItem( watch_thread_t *p_wt, input_item_t* p_item, bool );
int item_list_mediaIdOfItem( watch_thread_t *p_wt, input_item_t *p_item );
int item_list_updateInput( watch_thread_t *p_wt, input_item_t *p_item,
bool b_play_count );
void item_list_destroy( watch_thread_t* p_wt );
/**
* @brief Simple hash function
* @param item_id Hash Key
* @return Hash index
*/
static inline int item_hash( input_item_t* p_item )
{
return DictHash( p_item->psz_uri, ML_ITEMLIST_HASH_LENGTH );
}
#endif /* ML_ITEM_LIST_H */
/*****************************************************************************
* media_pool.c : Media pool for watching system
*****************************************************************************
* Copyright (C) 2009-2010 the VideoLAN team and AUTHORS
* $Id$
*
* Authors: Srikanth Raju <srikiraju at gmail dot com>
*
* 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.
*****************************************************************************/
#include "sql_media_library.h"
#define mp_foreachlist( a, b ) for( ml_poolobject_t* b = a; b; b = b->p_next )
static inline int mediapool_hash( int media_id )
{
return media_id % ML_MEDIAPOOL_HASH_LENGTH;
}
/**
* @brief Get a media from the pool
* @param p_ml ML object
* @param media_id The media id of the object to get
* @return the found media or NULL if not found
*/
ml_media_t* pool_GetMedia( media_library_t* p_ml, int media_id )
{
vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
ml_media_t* p_media = NULL;
mp_foreachlist( p_ml->p_sys->p_mediapool[ mediapool_hash( media_id ) ], p_item )
{
if( p_item->p_media->i_id == media_id )
{
p_media = p_item->p_media;
break;
}
}
if( p_media )
ml_gc_incref( p_media );
vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
return p_media;
}
/**
* @brief Insert a media into the media pool
* @param p_ml ML object
* @param p_media Media object to insert
* @return VLC_SUCCESS or VLC_EGENERIC
*/
int pool_InsertMedia( media_library_t* p_ml, ml_media_t* p_media, bool locked )
{
if( !locked )
ml_LockMedia( p_media );
assert( p_media );
assert( p_media->i_id > 0 );
if( p_media->ml_gc_data.pool )
{
msg_Dbg( p_ml, "Already in pool! %s %d", p_media->psz_uri, p_media->i_id );
ml_UnlockMedia( p_media );
return VLC_EGENERIC;
}
p_media->ml_gc_data.pool = true;
int i_ret = VLC_SUCCESS;
vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
mp_foreachlist( p_ml->p_sys->p_mediapool[ (mediapool_hash(p_media->i_id)) ], p_item )
{
if( p_media == p_item->p_media )
{
i_ret = VLC_EGENERIC;
break;
}
else if( p_media->i_id == p_item->p_media->i_id )
{
i_ret = VLC_EGENERIC;
msg_Warn( p_ml, "A media of the same id was found, but in different objects!" );
break;
}
}
if( i_ret == VLC_SUCCESS )
{
ml_poolobject_t* p_new = ( ml_poolobject_t * ) calloc( 1, sizeof( ml_poolobject_t* ) );
if( !p_new )
i_ret = VLC_EGENERIC;
else
{
ml_gc_incref( p_media );
p_new->p_media = p_media;
p_new->p_next = p_ml->p_sys->p_mediapool[ ( mediapool_hash( p_media->i_id ) ) ];
p_ml->p_sys->p_mediapool[ ( mediapool_hash( p_media->i_id ) ) ] = p_new;
}
}
vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
if( !locked )
ml_UnlockMedia( p_media );
return i_ret;
}
/**
* @brief Perform a single garbage collection scan on the media pool
* @param p_ml The ML object
* @note Scans all media and removes any medias not held by any other objects.
*/
void pool_GC( media_library_t* p_ml )
{
vlc_mutex_lock( &p_ml->p_sys->pool_mutex );
ml_poolobject_t* p_prev = NULL;
ml_media_t* p_media = NULL;
for( int i_idx = 0; i_idx < ML_MEDIAPOOL_HASH_LENGTH; i_idx++ )
{
p_prev = NULL;
for( ml_poolobject_t* p_item = p_ml->p_sys->p_mediapool[ i_idx ];
p_item != NULL; p_item = p_item->p_next )
{
p_media = p_item->p_media;
int refs;
refs = p_media->ml_gc_data.refs;
if( refs == 1 )
{
if( p_prev == NULL )
p_ml->p_sys->p_mediapool[i_idx] = p_item->p_next;
else
p_prev->p_next = p_item->p_next;
p_media->ml_gc_data.pool = false;
ml_gc_decref( p_item->p_media );//This should destroy the object
free( p_item );
}
p_prev = p_item;
}
}
vlc_mutex_unlock( &p_ml->p_sys->pool_mutex );
}
/*****************************************************************************
* ml_watch.c: SQL-based media library: Medias watching system
*****************************************************************************
* Copyright (C) 2008-2010 the VideoLAN team and AUTHORS
* $Id$
*
* Authors: Antoine Lejeune <phytos@videolan.org>
* Jean-Philippe André <jpeg@videolan.org>
* Rémi Duraffort <ivoire@videolan.org>
* Adrien Maglo <magsoft@videolan.org>
* Srikanth Raju <srikiraju at gmail dot com>
*
* 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.
*****************************************************************************/
#include "sql_media_library.h"
#include "item_list.h"
#include <vlc_events.h>
static void watch_ItemChange( const vlc_event_t *, void * );
static int watch_PlaylistItemCurrent( vlc_object_t *p_this, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval,
void *data );
static int watch_PlaylistItemAppend( vlc_object_t *p_this, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval,
void *data );
static int watch_PlaylistItemDeleted( vlc_object_t *p_this, char const *psz_var,
vlc_value_t oldval, vlc_value_t newval,
void *data );
static void watch_loop( media_library_t *p_ml, bool b_force );
static void watch_Thread_Cleanup( void* p_object );
static int watch_update_Item( media_library_t *p_ml, int i_media_id,
input_item_t *p_item, bool b_raise_count, bool locked );
static void watch_ProcessAppendQueue( media_library_t* p_ml );
/**
* @brief Watching thread
*/
static void* watch_Thread( void *obj )
{
watch_thread_t *p_watch = ( watch_thread_t* )obj;
media_library_t *p_ml = p_watch->p_ml;
int i_ret = 0;
vlc_mutex_lock( &p_watch->lock );
vlc_cleanup_push( watch_Thread_Cleanup, p_ml );
for( ;; )
{
watch_loop( p_ml, !i_ret );
i_ret = vlc_cond_timedwait( &p_watch->cond, &p_watch->lock,
mdate() + 1000000 * THREAD_SLEEP_DELAY );
}
vlc_cleanup_run();
return NULL;
}
/**
* @brief Callback for thread exit
*/
static void watch_Thread_Cleanup( void* p_object )
{
media_library_t* p_ml = ( media_library_t* )p_object;
watch_loop( p_ml, true );
vlc_mutex_unlock( &p_ml->p_sys->p_watch->lock );
}
/**
* @brief Init watching system
* @return Error if the object or the thread could not be created
*/
int watch_Init( media_library_t *p_ml )
{
/* init and launch watching thread */
p_ml->p_sys->p_watch = calloc( 1, sizeof(*p_ml->p_sys->p_watch) );
if( !p_ml->p_sys->p_watch )
return VLC_ENOMEM;
watch_thread_t* p_wt = p_ml->p_sys->p_watch;
vlc_mutex_init( &p_wt->list_mutex );
p_wt->p_ml = p_ml;
vlc_cond_init( &p_wt->cond );
vlc_mutex_init( &p_wt->lock );
/* Initialise item append queue */
vlc_mutex_init( &p_wt->item_append_queue_lock );
p_wt->item_append_queue = NULL;
p_wt->item_append_queue_count = 0;
if( vlc_clone( &p_wt->thread, watch_Thread, p_wt, VLC_THREAD_PRIORITY_LOW ) )
{
msg_Dbg( p_ml, "unable to launch the auto-updating thread" );
free( p_wt );
return VLC_EGENERIC;
}
/* Wait on playlist events
* playlist-item-append -> entry to playlist
* activity -> to ensure that we catch played item only!
* playlist-item-deleted -> exit from playlist
* item-change -> Currently not required, as we monitor input_item events
*/