Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Steve Lhomme
vlc
Commits
628b01be
Commit
628b01be
authored
Mar 24, 2013
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: remove media library support
parent
acee3359
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
0 additions
and
1675 deletions
+0
-1675
configure.ac
configure.ac
+0
-11
include/vlc_media_library.h
include/vlc_media_library.h
+0
-1130
src/Makefile.am
src/Makefile.am
+0
-1
src/libvlc-module.c
src/libvlc-module.c
+0
-4
src/libvlc.c
src/libvlc.c
+0
-33
src/libvlc.h
src/libvlc.h
+0
-2
src/libvlccore.sym
src/libvlccore.sym
+0
-6
src/misc/media_library.c
src/misc/media_library.c
+0
-417
src/missing.c
src/missing.c
+0
-71
No files found.
configure.ac
View file @
628b01be
...
...
@@ -3959,17 +3959,6 @@ dnl Libnotify notification plugin
dnl
PKG_ENABLE_MODULES_VLC([NOTIFY], [], [libnotify gtk+-2.0], [libnotify notification], [auto])
dnl
dnl media library
dnl
AC_ARG_ENABLE(media-library,
[ --enable-media-library media library (default disabled)])
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")
])
dnl
dnl Endianness check
dnl
...
...
include/vlc_media_library.h
View file @
628b01be
...
...
@@ -32,9 +32,6 @@
extern
"C"
{
# endif
#include <vlc_common.h>
#include <vlc_playlist.h>
/*****************************************************************************
* ML Enums
*****************************************************************************/
...
...
@@ -45,8 +42,6 @@ extern "C" {
#define ML_PERSON_PUBLISHER "Publisher"
#define ml_priv( gc, t ) ((t *)(((char *)(gc)) - offsetof(t, ml_gc_data)))
/** List of Query select types.
* In a query array or variable argument list, each select type is followed
* by an argument (X) of variable type (char* or int, @see ml_element_t).
...
...
@@ -125,1131 +120,6 @@ typedef enum {
ML_TYPE_MEDIA
,
/**< A pointer to a media ml_media_t* */
}
ml_result_type_e
;
/** Arguments for VLC Control for the media library */
typedef
enum
{
ML_SET_DATABASE
,
/**< arg1 = char *psz_host
arg2 = int i_port
arg3 = char *psz_user
arg4 = char *psz_pass */
ML_INIT_DATABASE
,
/**< No arg */
ML_ADD_INPUT_ITEM
,
/**< arg1 = input_item_t* */
ML_ADD_PLAYLIST_ITEM
,
/**< arg1 = playlist_item_t * */
ML_ADD_MONITORED
,
/**< arg1 = char* */
ML_DEL_MONITORED
,
/**< arg1 = char* */
ML_GET_MONITORED
,
/**< arg1 = vlc_array_t* */
}
ml_control_e
;
/* Operations that can be specified between find conditions */
typedef
enum
{
ML_OP_NONE
=
0
,
/**< This is to specify an actual condition */
ML_OP_AND
,
/**< AND condition */
ML_OP_OR
,
/**< OR condition */
ML_OP_NOT
,
/**< NOT condition */
ML_OP_SPECIAL
/**< This is for inclusion of
* special stuffs like LIMIT */
}
ml_op_e
;
/* Comparison operators used in a single find condition */
typedef
enum
{
ML_COMP_NONE
=
0
,
ML_COMP_LESSER
,
///< <
ML_COMP_LESSER_OR_EQUAL
,
///< <=
ML_COMP_EQUAL
,
///< ==
ML_COMP_GREATER_OR_EQUAL
,
///< >=
ML_COMP_GREATER
,
///< >
ML_COMP_HAS
,
///< "Contains", equivalent to SQL "LIKE %x%"
ML_COMP_STARTS_WITH
,
///< Equivalent to SQL "LIKE %x"
ML_COMP_ENDS_WITH
,
///< Equivalent to SQL "LIKE x%"
}
ml_comp_e
;
/*****************************************************************************
* ML Structures and types
*****************************************************************************/
typedef
struct
media_library_t
media_library_t
;
typedef
struct
media_library_sys_t
media_library_sys_t
;
typedef
struct
ml_media_t
ml_media_t
;
typedef
struct
ml_result_t
ml_result_t
;
typedef
struct
ml_element_t
ml_element_t
;
typedef
struct
ml_person_t
ml_person_t
;
typedef
struct
ml_ftree_t
ml_ftree_t
;
typedef
struct
ml_gc_object_t
{
bool
pool
;
uintptr_t
refs
;
void
(
*
pf_destructor
)
(
struct
ml_gc_object_t
*
);
}
ml_gc_object_t
;
#define ML_GC_MEMBERS ml_gc_object_t ml_gc_data;
/** Main structure of the media library. VLC object. */
struct
media_library_t
{
VLC_COMMON_MEMBERS
module_t
*
p_module
;
/**< the media library module */
media_library_sys_t
*
p_sys
;
/**< internal struture */
/** Member functions */
struct
{
/**< Search in the database */
int
(
*
pf_Find
)
(
media_library_t
*
p_media_library
,
vlc_array_t
*
p_result_array
,
va_list
args
);
/**< Search in the database using an array of arguments */
int
(
*
pf_FindAdv
)
(
media_library_t
*
p_media_library
,
vlc_array_t
*
p_result_array
,
ml_select_e
selected_type
,
const
char
*
psz_lvalue
,
ml_ftree_t
*
tree
);
/**< Update the database using an array of arguments */
int
(
*
pf_Update
)
(
media_library_t
*
p_media_library
,
ml_select_e
selected_type
,
const
char
*
psz_lvalue
,
ml_ftree_t
*
where
,
vlc_array_t
*
changes
);
/**< Delete many medias in the database */
int
(
*
pf_Delete
)
(
media_library_t
*
p_media_library
,
vlc_array_t
*
p_array
);
/**< Control the media library */
int
(
*
pf_Control
)
(
media_library_t
*
p_media_library
,
int
i_query
,
va_list
args
);
/**< Create associated input item */
input_item_t
*
(
*
pf_InputItemFromMedia
)
(
media_library_t
*
p_media_library
,
int
i_media
);
/**< Get a media */
ml_media_t
*
(
*
pf_GetMedia
)
(
media_library_t
*
p_media_library
,
int
i_media
,
ml_select_e
select
,
bool
reload
);
}
functions
;
};
/**
* @brief Structure to describe a media
*
* This is the main structure holding the meta data in ML.
* @see b_sparse indicates whether the media struct has valid values
* in its Extra fields. Otherwise, it must be loaded with the API
* function.
* @see i_id indicates whether this struct is saved in the ML if i_id > 0
* Otherwise, it can be added to the database
*/
struct
ml_media_t
{
ML_GC_MEMBERS
vlc_mutex_t
lock
;
/**< Mutex for multithreaded access */
bool
b_sparse
;
/**< Specifies if media is loaded fully */
ml_type_e
i_type
;
/**< Type of the media (ml_type_e) */
int8_t
i_vote
;
/**< User vote */
int16_t
i_disc_number
;
/**< Disc number of media */
int16_t
i_track_number
;
/**< Track number */
int16_t
i_year
;
/**< Year of release */
int32_t
i_id
;
/**< Media ID in the database */
int32_t
i_score
;
/**< Score computed about the media */
int32_t
i_album_id
;
/**< Album id */
int32_t
i_played_count
;
/**< How many time the media was played */
int32_t
i_skipped_count
;
/**< No. of times file was skipped */
int32_t
i_bitrate
;
/**< Extra: Bitrate of the media */
int32_t
i_samplerate
;
/**< Extra: Samplerate of the media */
int32_t
i_bpm
;
/**< Extra: Beats per minute */
char
*
psz_uri
;
/**< URI to find the media */
char
*
psz_title
;
/**< Title of the media */
char
*
psz_orig_title
;
/**< Original title (mainly for movies) */
char
*
psz_album
;
/**< Name of the album */
char
*
psz_cover
;
/**< URI of the cover */
char
*
psz_genre
;
/**< Genre of the media */
char
*
psz_preview
;
/**< Preview thumbnail for video, if any */
char
*
psz_comment
;
/**< Comment or description about media */
char
*
psz_language
;
/**< Extra: Language */
char
*
psz_extra
;
/**< Extra: Some extra datas like lyrics */
ml_person_t
*
p_people
;
/**< Extra: People associated with this
media This meta holds only one
artist if b_sparse = true */
int64_t
i_filesize
;
/**< Size of the file */
mtime_t
i_duration
;
/**< Duration in microseconds */
mtime_t
i_last_played
;
/**< Time when the media was last played */
mtime_t
i_last_skipped
;
/**< Time when the media was last skipped */
mtime_t
i_first_played
;
/**< First played */
mtime_t
i_import_time
;
/**< Time when media was added */
};
/**
* @brief Main communication struct between GUI and sql_media_library.
* Generic representation of an ML/SQL query result.
*/
struct
ml_result_t
{
int32_t
id
;
/**< Media/Album/Artist... ID (if any) */
ml_result_type_e
type
;
/**< Type of value */
union
{
/* Classical results */
int
i
;
char
*
psz
;
mtime_t
time
;
/* Complex result: media descriptor */
ml_media_t
*
p_media
;
}
value
;
/**< Value of the result obtained */
};
/**
* @brief Element of a query: criteria type/value pair
* Used for update and delete queries
*/
struct
ml_element_t
{
ml_select_e
criteria
;
/**< SELECT criteria type. @see ml_select_e */
union
{
int
i
;
char
*
str
;
}
value
;
/**< SELECT criteria value (string or int) */
union
{
int
i
;
char
*
str
;
}
lvalue
;
/**< Refer to @see ml_ftree_t lvalue docs */
};
/**
* Binary tree used to parse the WHERE condition for a search
*
* Let [expr] indicate a valid expression
* [expr] = [expr] AND [expr], where the left and right are respective
* [expr] = [expr] OR [expr]
* [expr] = [expr] NOT [NULL]
* [expr] = [expr] SPEC [spec_expr]
* [expr] = [criteria=val]
* [spec_expr] = [DISTINCT/LIMIT/ASC/DESC = val ]
*/
struct
ml_ftree_t
{
ml_op_e
op
;
/**< Operator. ML_OP_NONE means this is a leaf
* node. Criteria and value gives its data.
* ML_OP_SPECIAL specifies a special node
* that does not form a part of the WHERE.
* The right node consists of the data
* with its criteria set to the special val
* and the left node is the corresponding
* subtree of the parent node.
* ML_OP_NOT only left sub tree is considered
* ML_OP_AND and ML_OP_OR consider both
* left and right subtrees */
ml_ftree_t
*
left
;
/**< Left child of Bin tree */
ml_ftree_t
*
right
;
/**< Right child of Bin tree */
ml_select_e
criteria
;
/**< SELECT criteria type @see ml_select_e
* The criteria value is considered only when
* op = ML_OP_NONE i.e. in leaf nodes */
ml_comp_e
comp
;
/**< Condition between type and value */
union
{
int
i
;
char
*
str
;
}
value
;
/**< SELECT criteria value ( string or int ) */
union
{
int
i
;
char
*
str
;
}
lvalue
;
/**< Used as key value for people types/roles.
An empty string "" denotes ANY person role.
NULL is used for all other criterias */
};
/**
* Person class. Implemented as a linked list
*/
struct
ml_person_t
{
char
*
psz_role
;
/**< Type of person */
char
*
psz_name
;
/**< Name of the person */
int
i_id
;
/**< ID in the database */
ml_person_t
*
p_next
;
/**< Next person in list */
};
/*****************************************************************************
* ML Function headers
*****************************************************************************/
/**
* @brief Acquire a reference to the media library singleton
* @param p_this The object holding the media library
* @return The media library object. NULL if the media library
* object could not be loaded
*/
VLC_API
media_library_t
*
ml_Get
(
vlc_object_t
*
p_this
);
#define ml_Get( a ) ml_Get( VLC_OBJECT(a) )
/**
* @brief Create a Media Library VLC object.
* @param p_this Parent to attach the ML object to.
* @param psz_name Name for the module
* @return The ML object.
*/
media_library_t
*
ml_Create
(
vlc_object_t
*
p_this
,
char
*
psz_name
);
/**
* @brief Destructor for the Media library singleton
* @param p_this Parent the ML object is attached to
*/
void
ml_Destroy
(
vlc_object_t
*
p_this
);
/**
* @brief Control the Media Library
* @param p_media_library the media library object
* @param i_type one of ml_control_e values @see ml_control_e.
* @param ... optional arguments.
* @return VLC_SUCCESS or an error
*/
static
inline
int
ml_ControlVa
(
media_library_t
*
p_media_library
,
ml_control_e
i_type
,
va_list
args
)
{
return
p_media_library
->
functions
.
pf_Control
(
p_media_library
,
i_type
,
args
);
}
/**
* @brief Control the Media Library
* @param i_type one of ml_control_e values @see ml_control_e.
* Variable arguments list equivalent
*/
#define ml_Control( a, b, args... ) __ml_Control( a, b, ## args )
static
inline
int
__ml_Control
(
media_library_t
*
p_media_library
,
ml_control_e
i_type
,
...
)
{
va_list
args
;
int
returned
;
va_start
(
args
,
i_type
);
returned
=
ml_ControlVa
(
p_media_library
,
i_type
,
args
);
va_end
(
args
);
return
returned
;
}
/**
* @brief Determine an attribute's type (int or string)
* @param meta Attribute to test @see ml_select_e
* @return -1 if invalid, 0 if this is an integer, 1 if this is a string
*/
static
inline
int
ml_AttributeIsString
(
ml_select_e
meta
)
{
switch
(
meta
)
{
/* Strings */
case
ML_ALBUM
:
case
ML_ARTIST
:
case
ML_COMMENT
:
case
ML_COVER
:
case
ML_EXTRA
:
case
ML_GENRE
:
case
ML_LANGUAGE
:
case
ML_PREVIEW
:
case
ML_PEOPLE
:
case
ML_PEOPLE_ROLE
:
case
ML_ORIGINAL_TITLE
:
case
ML_TITLE
:
case
ML_URI
:
return
1
;
/* Integers */
case
ML_ALBUM_ID
:
case
ML_ARTIST_ID
:
case
ML_DURATION
:
case
ML_DISC_NUMBER
:
case
ML_COUNT_MEDIA
:
case
ML_COUNT_ALBUM
:
case
ML_COUNT_PEOPLE
:
case
ML_FILESIZE
:
case
ML_FIRST_PLAYED
:
case
ML_ID
:
case
ML_IMPORT_TIME
:
case
ML_LAST_PLAYED
:
case
ML_LIMIT
:
case
ML_PLAYED_COUNT
:
case
ML_PEOPLE_ID
:
case
ML_SCORE
:
case
ML_SKIPPED_COUNT
:
case
ML_TRACK_NUMBER
:
case
ML_TYPE
:
case
ML_VOTE
:
case
ML_YEAR
:
return
0
;
/* Invalid or no following value (in a SELECT statement) */
default:
return
-
1
;
}
}
/* Reference Counting Functions */
/**
* @brief Increment reference count of media
* @param p_media The media object
*/
static
inline
void
ml_gc_incref
(
ml_media_t
*
p_media
)
{
ml_gc_object_t
*
p_gc
=
&
p_media
->
ml_gc_data
;
if
(
p_gc
==
NULL
)
return
;
++
p_gc
->
refs
;
}
/**
* @brief Decrease reference count of media
* @param p_media The media object
*/
static
inline
void
ml_gc_decref
(
ml_media_t
*
p_media
)
{
/* The below code is from vlc_release(). */
unsigned
refs
;
bool
pool
;
ml_gc_object_t
*
p_gc
=
&
p_media
->
ml_gc_data
;
if
(
p_gc
==
NULL
)
return
;
refs
=
--
p_gc
->
refs
;
pool
=
p_gc
->
pool
;
if
(
refs
==
0
&&
!
pool
)
{
p_gc
->
pf_destructor
(
p_gc
);
}
}
/*****************************************************************************
* ML Free Functions
*****************************************************************************/
/**
* @brief Free a person object
* @param p_media Person object to free
* @note This function is NOT threadsafe
*/
static
inline
void
ml_FreePeople
(
ml_person_t
*
p_person
)
{
if
(
p_person
==
NULL
)
return
;
ml_FreePeople
(
p_person
->
p_next
);
free
(
p_person
->
psz_name
);
free
(
p_person
->
psz_role
);
free
(
p_person
);
}
/**
* @brief Free only the content of a media. @see ml_media_t
* @param p_media Media object
* @note This function is NOT threadsafe.
*/
static
inline
void
ml_FreeMediaContent
(
ml_media_t
*
p_media
)
{
FREENULL
(
p_media
->
psz_uri
);
FREENULL
(
p_media
->
psz_title
);
FREENULL
(
p_media
->
psz_orig_title
);
FREENULL
(
p_media
->
psz_cover
);
FREENULL
(
p_media
->
psz_comment
);
FREENULL
(
p_media
->
psz_extra
);
FREENULL
(
p_media
->
psz_genre
);
FREENULL
(
p_media
->
psz_album
);
FREENULL
(
p_media
->
psz_preview
);
FREENULL
(
p_media
->
psz_language
);
ml_FreePeople
(
p_media
->
p_people
);
p_media
->
b_sparse
=
true
;
p_media
->
i_id
=
0
;
p_media
->
i_type
=
ML_UNKNOWN
;
p_media
->
i_album_id
=
0
;
p_media
->
i_disc_number
=
0
;
p_media
->
i_track_number
=
0
;
p_media
->
i_year
=
0
;
p_media
->
i_vote
=
0
;
p_media
->
i_score
=
0
;
p_media
->
i_filesize
=
0
;
p_media
->
i_duration
=
0
;
p_media
->
i_played_count
=
0
;
p_media
->
i_last_played
=
0
;
p_media
->
i_skipped_count
=
0
;
p_media
->
i_last_skipped
=
0
;
p_media
->
i_first_played
=
0
;
p_media
->
i_import_time
=
0
;
p_media
->
i_bitrate
=
0
;
p_media
->
i_samplerate
=
0
;
p_media
->
i_bpm
=
0
;
}
/**
* @brief Free a result item. @see ml_result_t
* @param p_result Result item to free
* @note This will free any strings and decref medias.
*/
static
inline
void
ml_FreeResult
(
ml_result_t
*
p_result
)
{
if
(
p_result
)
{
switch
(
p_result
->
type
)
{
case
ML_TYPE_PSZ
:
free
(
p_result
->
value
.
psz
);
break
;
case
ML_TYPE_MEDIA
:
ml_gc_decref
(
p_result
->
value
.
p_media
);
break
;
default:
break
;
}
free
(
p_result
);
}
}
/**
* @brief Free a ml_element_t item.
* @param p_find Find object to free
* @see ml_element_t */
static
inline
void
ml_FreeElement
(
ml_element_t
*
p_elt
)
{
if
(
p_elt
)
{
if
(
ml_AttributeIsString
(
p_elt
->
criteria
)
)
{
free
(
p_elt
->
value
.
str
);
}
if
(
p_elt
->
criteria
==
ML_PEOPLE
)
{
free
(
p_elt
->
lvalue
.
str
);
}
free
(
p_elt
);
}
}
/**
* @brief Destroy a vlc_array_t of ml_result_t
* @param ml_result_array The result array to free
* @note Frees all results and contents of the results
*/
static
inline
void
ml_DestroyResultArray
(
vlc_array_t
*
p_result_array
)
{
for
(
int
i
=
0
;
i
<
vlc_array_count
(
p_result_array
);
i
++
)
{
ml_FreeResult
(
(
ml_result_t
*
)
vlc_array_item_at_index
(
p_result_array
,
i
)
);
}
}
/*****************************************************************************
* ML Object Management Functions
*****************************************************************************/
/** Helpers for locking and unlocking */
#define ml_LockMedia( a ) vlc_mutex_lock( &a->lock )
#define ml_UnlockMedia( a ) vlc_mutex_unlock( &a->lock )
/**
* @brief Object constructor for ml_media_t
* @param p_ml The media library object
* @param id If 0, this item isn't in database. If non zero, it is and
* it will be a singleton
* @param select Type of object
* @param reload Whether to reload from database
*/
VLC_API
ml_media_t
*
media_New
(
media_library_t
*
p_ml
,
int
id
,
ml_select_e
select
,
bool
reload
);
/* Forward declaration */
static
inline
int
ml_CopyPersons
(
ml_person_t
**
a
,
ml_person_t
*
b
);
/**
* @brief Copy all members of a ml_media_t to another.
* @param b Destination media, already allocated
* @param a Source media, cannot be NULL, const
* @note This does not check memory allocation (for strdup). It is threadsafe
* @todo Free b content, before inserting a?
*/
static
inline
int
ml_CopyMedia
(
ml_media_t
*
b
,
ml_media_t
*
a
)
{
if
(
!
a
||
!
b
)
return
VLC_EGENERIC
;
if
(
a
==
b
)
return
VLC_SUCCESS
;
ml_LockMedia
(
a
);
ml_LockMedia
(
b
);
b
->
b_sparse
=
a
->
b_sparse
;
b
->
i_id
=
a
->
i_id
;
b
->
i_type
=
a
->
i_type
;
b
->
i_album_id
=
a
->
i_album_id
;
b
->
i_disc_number
=
a
->
i_disc_number
;
b
->
i_track_number
=
a
->
i_track_number
;
b
->
i_year
=
a
->
i_year
;
b
->
i_vote
=
a
->
i_vote
;
b
->
i_score
=
a
->
i_score
;
b
->
i_filesize
=
a
->
i_filesize
;
b
->
i_duration
=
a
->
i_duration
;
b
->
i_played_count
=
a
->
i_played_count
;
b
->
i_last_played
=
a
->
i_last_played
;
b
->
i_skipped_count
=
a
->
i_skipped_count
;
b
->
i_last_skipped
=
a
->
i_last_skipped
;
b
->
i_first_played
=
a
->
i_first_played
;
b
->
i_import_time
=
a
->
i_import_time
;
b
->
i_bitrate
=
a
->
i_bitrate
;
b
->
i_samplerate
=
a
->
i_samplerate
;
b
->
i_bpm
=
a
->
i_bpm
;
FREENULL
(
b
->
psz_uri
);
if
(
a
->
psz_uri
)
b
->
psz_uri
=
strdup
(
a
->
psz_uri
);
FREENULL
(
b
->
psz_title
);
if
(
a
->
psz_title
)
b
->
psz_title
=
strdup
(
a
->
psz_title
);
FREENULL
(
b
->
psz_orig_title
);
if
(
a
->
psz_orig_title
)
b
->
psz_orig_title
=
strdup
(
a
->
psz_orig_title
);
FREENULL
(
b
->
psz_album
);
if
(
a
->
psz_album
)
b
->
psz_album
=
strdup
(
a
->
psz_album
);
FREENULL
(
b
->
psz_cover
);
if
(
a
->
psz_cover
)
b
->
psz_cover
=
strdup
(
a
->
psz_cover
);
FREENULL
(
b
->
psz_genre
);
if
(
a
->
psz_genre
)
b
->
psz_genre
=
strdup
(
a
->
psz_genre
);
FREENULL
(
b
->
psz_comment
);
if
(
a
->
psz_comment
)
b
->
psz_comment
=
strdup
(
a
->
psz_comment
);
FREENULL
(
b
->
psz_extra
);
if
(
a
->
psz_extra
)
b
->
psz_extra
=
strdup
(
a
->
psz_extra
);
FREENULL
(
b
->
psz_preview
);
if
(
a
->
psz_preview
)
b
->
psz_preview
=
strdup
(
a
->
psz_preview
);
FREENULL
(
b
->
psz_language
);
if
(
a
->
psz_language
)
b
->
psz_language
=
strdup
(
a
->
psz_language
);
ml_FreePeople
(
b
->
p_people
);
b
->
p_people
=
NULL
;
if
(
a
->
p_people
)
ml_CopyPersons
(
&
(
b
->
p_people
),
a
->
p_people
);
ml_UnlockMedia
(
b
);
ml_UnlockMedia
(
a
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* ML Find Tree Related Functions
*****************************************************************************/
#define ml_FreeFindTree( tree ) ml_GenericFreeFindTree( tree, true )
#define ml_ShallowFreeFindTree( tree ) ml_GenericFreeFindTree( tree, false )
/**
* @brief Free a find tree
* @param Find tree to free
* @param true to free any associated strings, false to not free them
*/
static
inline
void
ml_GenericFreeFindTree
(
ml_ftree_t
*
tree
,
bool
freestrings
)
{
if
(
tree
==
NULL
)
return
;
if
(
tree
->
left
)
{
ml_GenericFreeFindTree
(
tree
->
left
,
freestrings
);
free
(
tree
->
left
);
}
if
(
tree
->
right
)
{
ml_GenericFreeFindTree
(
tree
->
right
,
freestrings
);
free
(
tree
->
right
);
}
if
(
tree
->
op
==
ML_OP_NONE
&&
ml_AttributeIsString
(
tree
->
criteria
)
&&
freestrings
)
{
free
(
tree
->
value
.
str
);
if
(
tree
->
criteria
==
ML_PEOPLE
)
free
(
tree
->
lvalue
.
str
);
}
}
/**
* @brief Checks if a given find tree has leaf nodes
* @param Find tree
* @return Number of leaf nodes
*/
static
inline
int
ml_FtreeHasOp
(
ml_ftree_t
*
tree
)
{
if
(
tree
==
NULL
)
return
0
;
if
(
tree
->
criteria
>
0
&&
tree
->
op
==
ML_OP_NONE
)
return
1
;
else
return
ml_FtreeHasOp
(
tree
->
left
)
+
ml_FtreeHasOp
(
tree
->
right
);
}
/**
* @brief Connect up a find tree
* @param op operator to connect with
* If op = ML_OP_NONE, then you are connecting to a tree consisting of
* only SPECIAL nodes.
* If op = ML_OP_NOT, then right MUST be NULL
* op must not be ML_OP_SPECIAL, @see ml_FtreeSpec
* @param left part of the tree
* @param right part of the tree
* @return Pointer to new tree
* @note Use the helpers!
*/
VLC_API
ml_ftree_t
*
ml_OpConnectChilds
(
ml_op_e
op
,
ml_ftree_t
*
left
,
ml_ftree_t
*
right
);
/**
* @brief Attaches a special node to a tree
* @param tree Tree to attach special node to
* @param crit Criteria may be SORT_ASC, SORT_DESC, LIMIT or DISTINCT
* @param limit Limit used if LIMIT criteria used
* @param Sort string used if SORT criteria is used
* @return Pointer to new tree
* @note Use the helpers
*/
VLC_API
ml_ftree_t
*
ml_FtreeSpec
(
ml_ftree_t
*
tree
,