vlc_media_library.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * vlc_media_library.h: SQL-based media library
00003  *****************************************************************************
00004  * Copyright (C) 2008-2010 the VideoLAN Team and AUTHORS
00005  * $Id: 2529dd51c1c6b95061828b21b3ea0d0daf81710b $
00006  *
00007  * Authors: Antoine Lejeune <phytos@videolan.org>
00008  *          Jean-Philippe André <jpeg@videolan.org>
00009  *          Rémi Duraffort <ivoire@videolan.org>
00010  *          Adrien Maglo <magsoft@videolan.org>
00011  *          Srikanth Raju <srikiraju at gmail dot com>
00012  *
00013  * This program is free software; you can redistribute it and/or modify it
00014  * under the terms of the GNU Lesser General Public License as published by
00015  * the Free Software Foundation; either version 2.1 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00021  * GNU Lesser General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program; if not, write to the Free Software Foundation,
00025  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
00026  *****************************************************************************/
00027 
00028 #ifndef VLC_MEDIA_LIBRARY_H
00029 # define VLC_MEDIA_LIBRARY_H
00030 
00031 # ifdef __cplusplus
00032 extern "C" {
00033 # endif
00034 
00035 #include <vlc_common.h>
00036 #include <vlc_playlist.h>
00037 
00038 /*****************************************************************************
00039  * ML Enums
00040  *****************************************************************************/
00041 
00042 #define ML_PERSON_ARTIST        "Artist"
00043 #define ML_PERSON_ALBUM_ARTIST  "Album Artist"
00044 #define ML_PERSON_ENCODER       "Encoder"
00045 #define ML_PERSON_PUBLISHER     "Publisher"
00046 
00047 
00048 #define ml_priv( gc, t ) ((t *)(((char *)(gc)) - offsetof(t, ml_gc_data)))
00049 
00050 /** List of Query select types.
00051  * In a query array or variable argument list, each select type is followed
00052  * by an argument (X) of variable type (char* or int, @see ml_element_t).
00053  * These types can be used either in the query list or in the result array.
00054  * Some types are reserved for the result array:
00055  */
00056 typedef enum
00057 {
00058     ML_ALBUM = 1,              /**< Album Title */
00059     ML_ALBUM_ID,               /**< Album ID */
00060     ML_ALBUM_COVER,            /**< Album Cover art url */
00061     /* FIXME: Remove ML_ARTIST */
00062     ML_ARTIST,                 /**< Artist, interpreted as ML_PEOPLE
00063                                     && ML_PEOPLE_ROLE = ML_PERSON_ARTIST */
00064     ML_ARTIST_ID,              /**< Artist ID, interpreted as ML_PEOPLE_ID
00065                                     && ML_PEOPLE_ROLE = ML_PERSON_ARTIST */
00066     ML_COMMENT,                /**< Comment about media */
00067     ML_COUNT_MEDIA,            /**< Number of medias */
00068     ML_COUNT_ALBUM,            /**< Number of albums */
00069     ML_COUNT_PEOPLE,           /**< Number of people */
00070     ML_COVER,                  /**< Cover art url */
00071     ML_DURATION,               /**< Duration in ms */
00072     ML_DISC_NUMBER,            /**< Disc number of the track */
00073     ML_EXTRA,                  /**< Extra/comment (string) on the media */
00074     ML_FIRST_PLAYED,           /**< First time media was played */
00075     ML_FILESIZE,               /**< Size of the media file */
00076     ML_GENRE,                  /**< Genre of the media (if any) */
00077     ML_ID,                     /**< Media ID */
00078     ML_IMPORT_TIME,            /**< Date when media was imported */
00079     ML_LANGUAGE,               /**< Language */
00080     ML_LAST_PLAYED,            /**< Last play UNIX timestamp */
00081     ML_LAST_SKIPPED,           /**< Time when media was last skipped */
00082     ML_ORIGINAL_TITLE,         /**< Media original title (if any) */
00083     ML_PEOPLE,                 /**< Any People associated with this media */
00084     ML_PEOPLE_ID,              /**< Id of a person */
00085     ML_PEOPLE_ROLE,            /**< Person role */
00086     ML_PLAYED_COUNT,           /**< Media play count */
00087     ML_PREVIEW,                /**< Url of the video preview */
00088     ML_SKIPPED_COUNT,          /**< Number of times skipped */
00089     ML_SCORE,                  /**< Computed media score */
00090     ML_TITLE,                  /**< Media title */
00091     ML_TRACK_NUMBER,           /**< Media track number (if any) */
00092     ML_TYPE,                   /**< Media type. @see ml_type_e */
00093     ML_URI,                    /**< Media full URI. */
00094     ML_VOTE,                   /**< Media user vote value */
00095     ML_YEAR,                   /**< Media publishing year */
00096     ML_DIRECTORY,              /**< Monitored directory */
00097     ML_MEDIA,                  /**< Full media descriptor. @see ml_media_t */
00098     ML_MEDIA_SPARSE,           /**< Sparse media. @see ml_media_t */
00099     ML_MEDIA_EXTRA,            /**< Sparse + Extra = Full media */
00100 
00101     /* Some special elements */
00102     ML_LIMIT     = -1,         /**< Limit a query to X results */
00103     ML_SORT_DESC = -2,         /**< Sort a query descending on argument X */
00104     ML_SORT_ASC  = -3,         /**< Sort a query ascending on argument X */
00105     ML_DISTINCT  = -4,         /**< Add DISTINCT to SELECT statements. */
00106     ML_END       = -42         /**< End of argument list */
00107 } ml_select_e;
00108 
00109 /** Media types (audio, video, etc...) */
00110 typedef enum
00111 {
00112     ML_UNKNOWN   = 0,       /**< Unknown media type */
00113     ML_AUDIO     = 1 << 0,  /**< Audio only media */
00114     ML_VIDEO     = 1 << 1,  /**< Video media. May contain audio channels */
00115     ML_STREAM    = 1 << 2,  /**< Streamed media = not a local file */
00116     ML_NODE      = 1 << 3,  /**< Nodes like simple nodes, directories, playlists, etc */
00117     ML_REMOVABLE = 1 << 4,  /**< Removable media: CD/DVD/Card/... */
00118 } ml_type_e;
00119 
00120 /** Query result item/list type: integers, strings, medias, timestamps */
00121 typedef enum {
00122     ML_TYPE_INT,        /**< Object is an int */
00123     ML_TYPE_PSZ,        /**< A string char* */
00124     ML_TYPE_TIME,       /**< A timestamp mtime_t */
00125     ML_TYPE_MEDIA,      /**< A pointer to a media ml_media_t* */
00126 } ml_result_type_e;
00127 
00128 /** Arguments for VLC Control for the media library */
00129 typedef enum
00130 {
00131     ML_SET_DATABASE,      /**< arg1 = char *psz_host
00132                                arg2 = int i_port
00133                                arg3 = char *psz_user
00134                                arg4 = char *psz_pass */
00135     ML_INIT_DATABASE,     /**< No arg */
00136     ML_ADD_INPUT_ITEM,    /**< arg1 = input_item_t* */
00137     ML_ADD_PLAYLIST_ITEM, /**< arg1 = playlist_item_t * */
00138     ML_ADD_MONITORED,     /**< arg1 = char* */
00139     ML_DEL_MONITORED,     /**< arg1 = char* */
00140     ML_GET_MONITORED,     /**< arg1 = vlc_array_t* */
00141 } ml_control_e;
00142 
00143 /* Operations that can be specified between find conditions */
00144 typedef enum
00145 {
00146     ML_OP_NONE = 0,       /**< This is to specify an actual condition */
00147     ML_OP_AND,            /**< AND condition */
00148     ML_OP_OR,             /**< OR condition */
00149     ML_OP_NOT,            /**< NOT condition */
00150     ML_OP_SPECIAL         /**< This is for inclusion of
00151                             *  special stuffs like LIMIT */
00152 } ml_op_e;
00153 
00154 /* Comparison operators used in a single find condition */
00155 typedef enum
00156 {
00157     ML_COMP_NONE = 0,
00158     ML_COMP_LESSER,              ///< <
00159     ML_COMP_LESSER_OR_EQUAL,     ///< <=
00160     ML_COMP_EQUAL,               ///< ==
00161     ML_COMP_GREATER_OR_EQUAL,    ///< >=
00162     ML_COMP_GREATER,             ///< >
00163     ML_COMP_HAS,                 ///< "Contains", equivalent to SQL "LIKE %x%"
00164     ML_COMP_STARTS_WITH,         ///< Equivalent to SQL "LIKE %x"
00165     ML_COMP_ENDS_WITH,           ///< Equivalent to SQL "LIKE x%"
00166 } ml_comp_e;
00167 
00168 /*****************************************************************************
00169  * ML Structures and types
00170  *****************************************************************************/
00171 
00172 typedef struct media_library_t media_library_t;
00173 typedef struct media_library_sys_t media_library_sys_t;
00174 
00175 typedef struct ml_media_t      ml_media_t;
00176 typedef struct ml_result_t     ml_result_t;
00177 typedef struct ml_element_t    ml_element_t;
00178 typedef struct ml_person_t     ml_person_t;
00179 typedef struct ml_ftree_t      ml_ftree_t;
00180 
00181 
00182 typedef struct ml_gc_object_t
00183 {
00184     vlc_spinlock_t spin;
00185     bool           pool;
00186     uintptr_t      refs;
00187     void          (*pf_destructor) (struct ml_gc_object_t *);
00188 } ml_gc_object_t;
00189 
00190 #define ML_GC_MEMBERS ml_gc_object_t ml_gc_data;
00191 
00192 /** Main structure of the media library. VLC object. */
00193 struct media_library_t
00194 {
00195     VLC_COMMON_MEMBERS
00196 
00197     module_t             *p_module;  /**< the media library module */
00198     media_library_sys_t  *p_sys;     /**< internal struture */
00199 
00200     /** Member functions */
00201     struct
00202     {
00203         /**< Search in the database */
00204         int ( * pf_Find )            ( media_library_t *p_media_library,
00205                                        vlc_array_t *p_result_array,
00206                                        va_list args );
00207 
00208         /**< Search in the database using an array of arguments */
00209         int ( * pf_FindAdv )         ( media_library_t *p_media_library,
00210                                        vlc_array_t *p_result_array,
00211                                        ml_select_e selected_type,
00212                                        const char *psz_lvalue,
00213                                        ml_ftree_t *tree );
00214 
00215         /**< Update the database using an array of arguments */
00216         int ( * pf_Update )          ( media_library_t *p_media_library,
00217                                        ml_select_e selected_type,
00218                                        const char *psz_lvalue,
00219                                        ml_ftree_t *where,
00220                                        vlc_array_t *changes );
00221 
00222         /**< Delete many medias in the database */
00223         int ( * pf_Delete )    ( media_library_t *p_media_library,
00224                                        vlc_array_t *p_array );
00225 
00226         /**< Control the media library */
00227         int ( * pf_Control ) ( media_library_t *p_media_library,
00228                                int i_query, va_list args );
00229 
00230         /**< Create associated input item */
00231         input_item_t* ( * pf_InputItemFromMedia ) (
00232                     media_library_t *p_media_library, int i_media );
00233 
00234         /**< Get a media */
00235         ml_media_t* ( * pf_GetMedia ) (
00236                     media_library_t *p_media_library, int i_media,
00237                     ml_select_e select, bool reload );
00238     } functions;
00239 };
00240 
00241 
00242 /**
00243  * @brief Structure to describe a media
00244  *
00245  * This is the main structure holding the meta data in ML.
00246  * @see b_sparse indicates whether the media struct has valid values
00247  * in its Extra fields. Otherwise, it must be loaded with the API
00248  * function.
00249  * @see i_id indicates whether this struct is saved in the ML if i_id > 0
00250  * Otherwise, it can be added to the database
00251  */
00252 struct ml_media_t
00253 {
00254     ML_GC_MEMBERS
00255     vlc_mutex_t     lock;               /**< Mutex for multithreaded access */
00256     bool            b_sparse;           /**< Specifies if media is loaded fully */
00257     ml_type_e       i_type;             /**< Type of the media (ml_type_e) */
00258     int8_t          i_vote;             /**< User vote */
00259     int16_t         i_disc_number;      /**< Disc number of media */
00260     int16_t         i_track_number;     /**< Track number */
00261     int16_t         i_year;             /**< Year of release */
00262     int32_t         i_id;               /**< Media ID in the database */
00263     int32_t         i_score;            /**< Score computed about the media */
00264     int32_t         i_album_id;         /**< Album id */
00265     int32_t         i_played_count;     /**< How many time the media was played */
00266     int32_t         i_skipped_count;    /**< No. of times file was skipped */
00267     int32_t         i_bitrate;          /**< Extra: Bitrate of the media */
00268     int32_t         i_samplerate;       /**< Extra: Samplerate of the media */
00269     int32_t         i_bpm;              /**< Extra: Beats per minute */
00270     char            *psz_uri;           /**< URI to find the media */
00271     char            *psz_title;         /**< Title of the media */
00272     char            *psz_orig_title;    /**< Original title (mainly for movies) */
00273     char            *psz_album;         /**< Name of the album */
00274     char            *psz_cover;         /**< URI of the cover */
00275     char            *psz_genre;         /**< Genre of the media */
00276     char            *psz_preview;       /**< Preview thumbnail for video, if any */
00277     char            *psz_comment;       /**< Comment or description about media */
00278     char            *psz_language;      /**< Extra: Language */
00279     char            *psz_extra;         /**< Extra: Some extra datas like lyrics */
00280     ml_person_t     *p_people;          /**< Extra: People associated with this
00281                                              media This meta holds only one
00282                                              artist if b_sparse = true */
00283     int64_t         i_filesize;         /**< Size of the file */
00284     mtime_t         i_duration;         /**< Duration in microseconds */
00285     mtime_t         i_last_played;      /**< Time when the media was last played */
00286     mtime_t         i_last_skipped;     /**< Time when the media was last skipped */
00287     mtime_t         i_first_played;     /**< First played */
00288     mtime_t         i_import_time;      /**< Time when media was added */
00289 
00290 };
00291 
00292 
00293 /**
00294  * @brief Main communication struct between GUI and sql_media_library.
00295  * Generic representation of an ML/SQL query result.
00296  */
00297 struct ml_result_t
00298 {
00299     int32_t          id;        /**< Media/Album/Artist... ID (if any) */
00300     ml_result_type_e type;      /**< Type of value */
00301     union
00302     {
00303         /* Classical results */
00304         int             i;
00305         char           *psz;
00306         mtime_t         time;
00307 
00308         /* Complex result: media descriptor */
00309         ml_media_t     *p_media;
00310     } value;                    /**< Value of the result obtained */
00311 };
00312 
00313 
00314 /**
00315  * @brief Element of a query: criteria type/value pair
00316  * Used for update and delete queries
00317  */
00318 struct ml_element_t
00319 {
00320     ml_select_e    criteria;    /**< SELECT criteria type. @see ml_select_e */
00321     union
00322     {
00323         int     i;
00324         char*   str;
00325     } value;                    /**< SELECT criteria value (string or int) */
00326     union
00327     {
00328         int     i;
00329         char*   str;
00330     } lvalue;                   /**< Refer to @see ml_ftree_t lvalue docs */
00331 };
00332 
00333 /**
00334  * Binary tree used to parse the WHERE condition for a search
00335  *
00336  * Let [expr] indicate a valid expression
00337  * [expr] = [expr] AND [expr], where the left and right are respective
00338  * [expr] = [expr] OR [expr]
00339  * [expr] = [expr] NOT [NULL]
00340  * [expr] = [expr] SPEC [spec_expr]
00341  * [expr] = [criteria=val]
00342  * [spec_expr] = [DISTINCT/LIMIT/ASC/DESC = val ]
00343  */
00344 struct ml_ftree_t
00345 {
00346     ml_op_e         op;         /**< Operator. ML_OP_NONE means this is a leaf
00347                                   *  node. Criteria and value gives its data.
00348                                   *  ML_OP_SPECIAL specifies a special node
00349                                   *  that does not form a part of the WHERE.
00350                                   *  The right node consists of the data
00351                                   *  with its criteria set to the special val
00352                                   *  and the left node is the corresponding
00353                                   *  subtree of the parent node.
00354                                   *  ML_OP_NOT only left sub tree is considered
00355                                   *  ML_OP_AND and ML_OP_OR consider both
00356                                   *  left and right subtrees */
00357     ml_ftree_t      *left;      /**< Left child of Bin tree */
00358     ml_ftree_t      *right;     /**< Right child of Bin tree */
00359     ml_select_e     criteria;   /**< SELECT criteria type @see ml_select_e
00360                                   *  The criteria value is considered only when
00361                                   *  op = ML_OP_NONE i.e. in leaf nodes */
00362     ml_comp_e       comp;       /**< Condition between type and value */
00363     union
00364     {
00365         int     i;
00366         char    *str;
00367     } value;                    /**< SELECT criteria value ( string or int ) */
00368     union
00369     {
00370         int     i;
00371         char    *str;
00372     } lvalue;                   /**< Used as key value for people types/roles.
00373                                      An empty string "" denotes ANY person role.
00374                                      NULL is used for all other criterias */
00375 };
00376 
00377 
00378 /**
00379  * Person class. Implemented as a linked list
00380  */
00381 struct ml_person_t
00382 {
00383     char               *psz_role;   /**< Type of person */
00384     char               *psz_name;   /**< Name of the person */
00385     int                 i_id;       /**< ID in the database */
00386     ml_person_t        *p_next;     /**< Next person in list */
00387 };
00388 
00389 
00390 /*****************************************************************************
00391  * ML Function headers
00392  *****************************************************************************/
00393 
00394 /**
00395  * @brief Acquire a reference to the media library singleton
00396  * @param p_this The object holding the media library
00397  * @return The media library object. NULL if the media library
00398  * object could not be loaded
00399  */
00400 VLC_API media_library_t* ml_Get( vlc_object_t* p_this );
00401 #define ml_Get( a ) ml_Get( VLC_OBJECT(a) )
00402 
00403 /**
00404  * @brief Create a Media Library VLC object.
00405  * @param p_this Parent to attach the ML object to.
00406  * @param psz_name Name for the module
00407  * @return The ML object.
00408  */
00409 VLC_API media_library_t* ml_Create( vlc_object_t *p_this, char* psz_name );
00410 
00411 /**
00412  * @brief Destructor for the Media library singleton
00413  * @param p_this Parent the ML object is attached to
00414  */
00415 VLC_API void ml_Destroy( vlc_object_t* p_this );
00416 
00417 /**
00418  * @brief Control the Media Library
00419  * @param p_media_library the media library object
00420  * @param i_type one of ml_control_e values @see ml_control_e.
00421  * @param ... optional arguments.
00422  * @return VLC_SUCCESS or an error
00423  */
00424 static inline int ml_ControlVa( media_library_t *p_media_library,
00425                                 ml_control_e i_type, va_list args )
00426 {
00427     return p_media_library->functions.pf_Control( p_media_library,
00428                                                   i_type,
00429                                                   args );
00430 }
00431 
00432 /**
00433  * @brief Control the Media Library
00434  * @param i_type one of ml_control_e values @see ml_control_e.
00435  * Variable arguments list equivalent
00436  */
00437 #define ml_Control( a, b, args... )     __ml_Control( a, b, ## args )
00438 static inline int __ml_Control( media_library_t *p_media_library,
00439                                 ml_control_e i_type, ... )
00440 {
00441     va_list args;
00442     int returned;
00443 
00444     va_start( args, i_type );
00445     returned = ml_ControlVa( p_media_library, i_type, args );
00446     va_end( args );
00447 
00448     return returned;
00449 }
00450 
00451 /**
00452  * @brief Determine an attribute's type (int or string)
00453  * @param meta Attribute to test @see ml_select_e
00454  * @return -1 if invalid, 0 if this is an integer, 1 if this is a string
00455  */
00456 static inline int ml_AttributeIsString( ml_select_e meta )
00457 {
00458     switch( meta )
00459     {
00460     /* Strings */
00461     case ML_ALBUM:
00462     case ML_ARTIST:
00463     case ML_COMMENT:
00464     case ML_COVER:
00465     case ML_EXTRA:
00466     case ML_GENRE:
00467     case ML_LANGUAGE:
00468     case ML_PREVIEW:
00469     case ML_PEOPLE:
00470     case ML_PEOPLE_ROLE:
00471     case ML_ORIGINAL_TITLE:
00472     case ML_TITLE:
00473     case ML_URI:
00474         return 1;
00475 
00476     /* Integers */
00477     case ML_ALBUM_ID:
00478     case ML_ARTIST_ID:
00479     case ML_DURATION:
00480     case ML_DISC_NUMBER:
00481     case ML_COUNT_MEDIA:
00482     case ML_COUNT_ALBUM:
00483     case ML_COUNT_PEOPLE:
00484     case ML_FILESIZE:
00485     case ML_FIRST_PLAYED:
00486     case ML_ID:
00487     case ML_IMPORT_TIME:
00488     case ML_LAST_PLAYED:
00489     case ML_LIMIT:
00490     case ML_PLAYED_COUNT:
00491     case ML_PEOPLE_ID:
00492     case ML_SCORE:
00493     case ML_SKIPPED_COUNT:
00494     case ML_TRACK_NUMBER:
00495     case ML_TYPE:
00496     case ML_VOTE:
00497     case ML_YEAR:
00498         return 0;
00499 
00500     /* Invalid or no following value (in a SELECT statement) */
00501     default:
00502         return -1;
00503     }
00504 }
00505 
00506 /* Reference Counting Functions */
00507 /**
00508  * @brief Increment reference count of media
00509  * @param p_media The media object
00510  */
00511 static inline void ml_gc_incref( ml_media_t* p_media )
00512 {
00513     ml_gc_object_t* p_gc = &p_media->ml_gc_data;
00514     if( p_gc == NULL )
00515         return;
00516 
00517     vlc_spin_lock (&p_gc->spin);
00518     ++p_gc->refs;
00519     vlc_spin_unlock (&p_gc->spin);
00520 }
00521 
00522 /**
00523  * @brief Decrease reference count of media
00524  * @param p_media The media object
00525  */
00526 static inline void ml_gc_decref( ml_media_t* p_media )
00527 {
00528     /* The below code is from vlc_release(). */
00529     unsigned refs;
00530     bool pool;
00531     ml_gc_object_t* p_gc = &p_media->ml_gc_data;
00532     if( p_gc == NULL )
00533         return;
00534 
00535     vlc_spin_lock (&p_gc->spin);
00536     refs = --p_gc->refs;
00537     pool = p_gc->pool;
00538     vlc_spin_unlock (&p_gc->spin);
00539 
00540     if( refs == 0 && !pool )
00541     {
00542         vlc_spin_destroy (&p_gc->spin);
00543         p_gc->pf_destructor (p_gc);
00544     }
00545 }
00546 
00547 /*****************************************************************************
00548  * ML Free Functions
00549  *****************************************************************************/
00550 
00551 /**
00552  * @brief Free a person object
00553  * @param p_media Person object to free
00554  * @note This function is NOT threadsafe
00555  */
00556 static inline void ml_FreePeople( ml_person_t *p_person )
00557 {
00558     if( p_person == NULL )
00559         return;
00560     ml_FreePeople( p_person->p_next );
00561     free( p_person->psz_name );
00562     free( p_person->psz_role );
00563     free( p_person );
00564 }
00565 
00566 /**
00567  * @brief Free only the content of a media. @see ml_media_t
00568  * @param p_media Media object
00569  * @note This function is NOT threadsafe.
00570  */
00571 static inline void ml_FreeMediaContent( ml_media_t *p_media )
00572 {
00573     free( p_media->psz_uri );
00574     free( p_media->psz_title );
00575     free( p_media->psz_orig_title );
00576     free( p_media->psz_cover );
00577     free( p_media->psz_comment );
00578     free( p_media->psz_extra );
00579     free( p_media->psz_genre );
00580     free( p_media->psz_album );
00581     free( p_media->psz_preview );
00582     free( p_media->psz_language );
00583     ml_FreePeople( p_media->p_people );
00584     p_media->b_sparse = true;
00585     p_media->i_id = 0;
00586     p_media->i_type = ML_UNKNOWN;
00587     p_media->i_album_id = 0;
00588     p_media->i_disc_number = 0;
00589     p_media->i_track_number = 0;
00590     p_media->i_year = 0;
00591     p_media->i_vote = 0;
00592     p_media->i_score = 0;
00593     p_media->i_filesize = 0;
00594     p_media->i_duration = 0;
00595     p_media->i_played_count = 0;
00596     p_media->i_last_played = 0;
00597     p_media->i_skipped_count = 0;
00598     p_media->i_last_skipped = 0;
00599     p_media->i_first_played = 0;
00600     p_media->i_import_time = 0;
00601     p_media->i_bitrate = 0;
00602     p_media->i_samplerate = 0;
00603     p_media->i_bpm = 0;
00604 }
00605 
00606 /**
00607  * @brief Free a result item. @see ml_result_t
00608  * @param p_result Result item to free
00609  * @note This will free any strings and decref medias.
00610  */
00611 static inline void ml_FreeResult( ml_result_t *p_result )
00612 {
00613     if( p_result )
00614     {
00615         switch( p_result->type )
00616         {
00617             case ML_TYPE_PSZ:
00618                 free( p_result->value.psz );
00619                 break;
00620             case ML_TYPE_MEDIA:
00621                 ml_gc_decref( p_result->value.p_media );
00622                 break;
00623             default:
00624                 break;
00625         }
00626         free( p_result );
00627     }
00628 }
00629 
00630 
00631 /**
00632  * @brief Free a ml_element_t item.
00633  * @param p_find Find object to free
00634  * @see ml_element_t */
00635 static inline void ml_FreeElement( ml_element_t *p_elt )
00636 {
00637     if( p_elt )
00638     {
00639         if( ml_AttributeIsString( p_elt->criteria ) )
00640         {
00641             free( p_elt->value.str );
00642         }
00643         if( p_elt->criteria == ML_PEOPLE )
00644         {
00645             free( p_elt->lvalue.str );
00646         }
00647         free( p_elt );
00648     }
00649 }
00650 
00651 
00652 /**
00653  * @brief Destroy a vlc_array_t of ml_result_t
00654  * @param ml_result_array The result array to free
00655  * @note Frees all results and contents of the results
00656  */
00657 static inline void ml_DestroyResultArray( vlc_array_t *p_result_array )
00658 {
00659     for( int i = 0; i < vlc_array_count( p_result_array ); i++ )
00660     {
00661         ml_FreeResult( ( ml_result_t* ) vlc_array_item_at_index(
00662                 p_result_array, i ) );
00663     }
00664 }
00665 
00666 
00667 
00668 /*****************************************************************************
00669  * ML Object Management Functions
00670  *****************************************************************************/
00671 
00672 /** Helpers for locking and unlocking */
00673 #define ml_LockMedia( a )      vlc_mutex_lock( &a->lock )
00674 #define ml_UnlockMedia( a )    vlc_mutex_unlock( &a->lock )
00675 
00676 /**
00677  * @brief Object constructor for ml_media_t
00678  * @param p_ml The media library object
00679  * @param id If 0, this item isn't in database. If non zero, it is and
00680  * it will be a singleton
00681  * @param select Type of object
00682  * @param reload Whether to reload from database
00683  */
00684 VLC_API ml_media_t *media_New( media_library_t* p_ml, int id,
00685         ml_select_e select, bool reload );
00686 
00687 
00688 /* Forward declaration */
00689 static inline int ml_CopyPersons( ml_person_t** a, ml_person_t* b );
00690 
00691 /**
00692  * @brief Copy all members of a ml_media_t to another.
00693  * @param b Destination media, already allocated
00694  * @param a Source media, cannot be NULL, const
00695  * @note This does not check memory allocation (for strdup). It is threadsafe
00696  * @todo Free b content, before inserting a?
00697  */
00698 static inline int ml_CopyMedia( ml_media_t *b, ml_media_t *a )
00699 {
00700     if( !a || !b ) return VLC_EGENERIC;
00701     if( a == b ) return VLC_SUCCESS;
00702     ml_LockMedia( a );
00703     ml_LockMedia( b );
00704     b->b_sparse = a->b_sparse;
00705     b->i_id = a->i_id;
00706     b->i_type = a->i_type;
00707     b->i_album_id = a->i_album_id;
00708     b->i_disc_number = a->i_disc_number;
00709     b->i_track_number = a->i_track_number;
00710     b->i_year = a->i_year;
00711     b->i_vote = a->i_vote;
00712     b->i_score = a->i_score;
00713     b->i_filesize = a->i_filesize;
00714     b->i_duration = a->i_duration;
00715     b->i_played_count = a->i_played_count;
00716     b->i_last_played = a->i_last_played;
00717     b->i_skipped_count = a->i_skipped_count;
00718     b->i_last_skipped = a->i_last_skipped;
00719     b->i_first_played = a->i_first_played;
00720     b->i_import_time = a->i_import_time;
00721     b->i_bitrate = a->i_bitrate;
00722     b->i_samplerate = a->i_samplerate;
00723     b->i_bpm = a->i_bpm;
00724     free( b->psz_uri );
00725     if( a->psz_uri )
00726         b->psz_uri = strdup( a->psz_uri );
00727     free( b->psz_title );
00728     if( a->psz_title )
00729         b->psz_title = strdup( a->psz_title );
00730     free( b->psz_orig_title );
00731     if( a->psz_orig_title )
00732         b->psz_orig_title = strdup( a->psz_orig_title );
00733     free( b->psz_album );
00734     if( a->psz_album )
00735         b->psz_album = strdup( a->psz_album );
00736     free( b->psz_cover );
00737     if( a->psz_cover )
00738         b->psz_cover = strdup( a->psz_cover );
00739     free( b->psz_genre );
00740     if( a->psz_genre )
00741         b->psz_genre = strdup( a->psz_genre );
00742     free( b->psz_comment );
00743     if( a->psz_comment )
00744         b->psz_comment = strdup( a->psz_comment );
00745     free( b->psz_extra );
00746     if( a->psz_extra )
00747         b->psz_extra = strdup( a->psz_extra );
00748     free( b->psz_preview );
00749     if( a->psz_preview )
00750         b->psz_preview = strdup( a->psz_preview );
00751     free( b->psz_language );
00752     if( a->psz_language )
00753         b->psz_language = strdup( a->psz_language );
00754     ml_FreePeople( b->p_people );
00755     if( a->p_people )        ml_CopyPersons( &( b->p_people ), a->p_people );
00756     ml_UnlockMedia( b );
00757     ml_UnlockMedia( a );
00758     return VLC_SUCCESS;
00759 }
00760 
00761 /*****************************************************************************
00762  * ML Find Tree Related Functions
00763  *****************************************************************************/
00764 #define ml_FreeFindTree( tree )          ml_GenericFreeFindTree( tree, true )
00765 #define ml_ShallowFreeFindTree( tree )   ml_GenericFreeFindTree( tree, false )
00766 /**
00767  * @brief Free a find tree
00768  * @param Find tree to free
00769  * @param true to free any associated strings, false to not free them
00770  */
00771 static inline void ml_GenericFreeFindTree( ml_ftree_t* tree, bool freestrings )
00772 {
00773     if( tree == NULL )
00774         return;
00775     if( tree->left )
00776     {
00777         ml_GenericFreeFindTree( tree->left, freestrings );
00778         free( tree->left );
00779     }
00780     if( tree->right )
00781     {
00782         ml_GenericFreeFindTree( tree->right, freestrings );
00783         free( tree->right );
00784     }
00785     if( tree->op == ML_OP_NONE && ml_AttributeIsString( tree->criteria )
00786             && freestrings)
00787     {
00788         free( tree->value.str );
00789         if( tree->criteria == ML_PEOPLE )
00790             free( tree->lvalue.str );
00791     }
00792 }
00793 
00794 /**
00795  * @brief Checks if a given find tree has leaf nodes
00796  * @param Find tree
00797  * @return Number of leaf nodes
00798  */
00799 static inline int ml_FtreeHasOp( ml_ftree_t* tree )
00800 {
00801     if( tree == NULL )
00802         return 0;
00803     if( tree->criteria > 0 && tree->op == ML_OP_NONE )
00804         return 1;
00805     else
00806         return ml_FtreeHasOp( tree->left ) + ml_FtreeHasOp( tree->right );
00807 }
00808 
00809 
00810 /**
00811  * @brief Connect up a find tree
00812  * @param op operator to connect with
00813  * If op = ML_OP_NONE, then you are connecting to a tree consisting of
00814  * only SPECIAL nodes.
00815  * If op = ML_OP_NOT, then right MUST be NULL
00816  * op must not be ML_OP_SPECIAL, @see ml_FtreeSpec
00817  * @param left part of the tree
00818  * @param right part of the tree
00819  * @return Pointer to new tree
00820  * @note Use the helpers!
00821  */
00822 VLC_API ml_ftree_t *ml_OpConnectChilds( ml_op_e op, ml_ftree_t* left,
00823         ml_ftree_t* right );
00824 
00825 /**
00826  * @brief Attaches a special node to a tree
00827  * @param tree Tree to attach special node to
00828  * @param crit Criteria may be SORT_ASC, SORT_DESC, LIMIT or DISTINCT
00829  * @param limit Limit used if LIMIT criteria used
00830  * @param Sort string used if SORT criteria is used
00831  * @return Pointer to new tree
00832  * @note Use the helpers
00833  */
00834 VLC_API ml_ftree_t *ml_FtreeSpec( ml_ftree_t* tree,
00835                                           ml_select_e crit,
00836                                           int limit,
00837                                           char* sort );
00838 
00839 /**
00840  * @brief This function gives quick sequential adding capability
00841  * @param left Tree to add to. This may be NULL
00842  * @param right Tree to append. May not be NULL
00843  * @return Pointer to new tree.*/
00844 static inline ml_ftree_t* ml_FtreeFastAnd( ml_ftree_t* left,
00845                                            ml_ftree_t* right )
00846 {
00847     if( ml_FtreeHasOp( left ) == 0 )
00848     {
00849         return ml_OpConnectChilds( ML_OP_NONE, left, right );
00850     }
00851     else
00852     {
00853         return ml_OpConnectChilds( ML_OP_AND, left, right );
00854     }
00855 }
00856 #define ml_FtreeAnd( left, right ) ml_OpConnectChilds( ML_OP_AND, left, right )
00857 #define ml_FtreeOr( left, right )  ml_OpConnectChilds( ML_OP_OR, left, right )
00858 #define ml_FtreeNot( left )        ml_OpConnectChilds( ML_OP_NOT, left, NULL )
00859 
00860 #define ml_FtreeSpecAsc( tree, str )        ml_FtreeSpec( tree, ML_SORT_ASC, 0, str )
00861 #define ml_FtreeSpecDesc( tree, str )       ml_FtreeSpec( tree, ML_SORT_DESC, 0, str )
00862 #define ml_FtreeSpecLimit( tree, limit )    ml_FtreeSpec( tree, ML_LIMIT, limit, NULL )
00863 #define ml_FtreeSpecDistinct( tree )        ml_FtreeSpec( tree, ML_DISTINCT, 0, NULL )
00864 
00865 
00866 /*****************************************************************************
00867  * ML Core Functions
00868  *****************************************************************************/
00869 
00870 /**
00871  * @brief Create input item from media
00872  * @param p_media_library This ML instance.
00873  * @param i_media_id ID of the media to use to create an input_item.
00874  * @return The media item.
00875  */
00876 static inline input_item_t* ml_CreateInputItem(
00877         media_library_t *p_media_library, int i_media_id )
00878 {
00879     return p_media_library->functions.pf_InputItemFromMedia( p_media_library,
00880                                                              i_media_id );
00881 }
00882 
00883 /**
00884  * @brief Search in the database according some criterias
00885  *
00886  * @param p_media_library the media library object
00887  * @param result a pointer to a result array
00888  * @param ... parameters to select the data
00889  * @return VLC_SUCCESS or an error
00890  */
00891 static inline int __ml_Find( media_library_t *p_media_library,
00892                              vlc_array_t *p_result_array, ... )
00893 {
00894     va_list args;
00895     int returned;
00896 
00897     va_start( args, p_result_array );
00898     returned = p_media_library->functions.pf_Find( p_media_library,
00899                                                    p_result_array, args );
00900     va_end( args );
00901 
00902     return returned;
00903 }
00904 
00905 
00906 /**
00907  * @brief Search in the database according some criterias (threaded)
00908  * @param p_media_library the media library object
00909  * @param result_array a pointer to a result array
00910  * @param result_type type of data to retrieve
00911  * @param psz_lvalue This should contain any necessary lvalue/key
00912  * for the given result_type. Used for ML_PEOPLE. Otherwise NULL
00913  * @param args parameters to select the data
00914  * @return VLC_SUCCESS or an error
00915  */
00916 static inline int ml_FindAdv( media_library_t *p_media_library,
00917                               vlc_array_t *p_result_array,
00918                               ml_select_e result_type,
00919                               char* psz_lvalue,
00920                               ml_ftree_t *tree )
00921 {
00922     return p_media_library->functions.pf_FindAdv( p_media_library,
00923                                                   p_result_array,
00924                                                   result_type,
00925                                                   psz_lvalue,
00926                                                   tree );
00927 }
00928 
00929 
00930 /**
00931  * @brief Find a value in the ML database, fill p_result with it.
00932  * @param p_media_library Media library object
00933  * @param p_result Object to put result into
00934  * @param Args [ SelectType [ PersonType ] Value ] ... ML_END
00935  * @note Do not use this function directly.
00936  */
00937 static inline int __ml_GetValue( media_library_t *p_media_library,
00938                                   ml_result_t *p_result,
00939                                   va_list args )
00940 {
00941     vlc_array_t *p_result_array = vlc_array_new();
00942     int i_ret = p_media_library->functions.pf_Find( p_media_library,
00943                                                     p_result_array,
00944                                                     args );
00945     if( i_ret != VLC_SUCCESS )
00946         goto exit;
00947     if( vlc_array_count( p_result_array ) > 0 )
00948         memcpy( p_result,
00949                 ( ml_result_t* ) vlc_array_item_at_index( p_result_array, 0 ),
00950                 sizeof( ml_result_t) );
00951     else
00952         i_ret = VLC_EGENERIC;
00953 
00954 exit:
00955     /* Note: Do not free the results, because of memcpy */
00956     vlc_array_destroy( p_result_array );
00957     return i_ret;
00958 }
00959 
00960 /**
00961  * @brief Search an INTEGER in the database
00962  * This uses a Query but returns only one integer (>0), or an error code.
00963  *
00964  * @param p_media_library the media library object
00965  * @param va_args parameters to select the data
00966  * @return Found INTEGER >= 0 or an error
00967  */
00968 #define ml_GetInt( ml, ... ) __ml_GetInt( ml, __VA_ARGS__, ML_LIMIT, 1, ML_END )
00969 static inline int __ml_GetInt( media_library_t *p_media_library, ... )
00970 {
00971     va_list args;
00972     va_start( args, p_media_library );
00973     ml_result_t result;
00974     int i_ret = __ml_GetValue( p_media_library, &result, args );
00975     va_end( args );
00976     if( i_ret != VLC_SUCCESS )
00977         return i_ret;
00978     else
00979         return result.value.i;
00980 }
00981 
00982 
00983 /**
00984  * @brief Search a string (VARCHAR) in the database
00985  * This uses a Query but returns only one integer (>0), or an error code.
00986  *
00987  * @param p_media_library the media library object
00988  * @param va_args parameters to select the data
00989  * @return Found string, or NULL if not found or in case of error
00990  */
00991 #define ml_FindPsz( ml, ... ) __ml_GetPsz( ml, __VA_ARGS__, ML_LIMIT, 1, ML_END )
00992 static inline char* __ml_GetPsz( media_library_t *p_media_library, ... )
00993 {
00994     va_list args;
00995     va_start( args, p_media_library );
00996     ml_result_t result;
00997     int i_ret = __ml_GetValue( p_media_library, &result, args );
00998     va_end( args );
00999     if( i_ret != VLC_SUCCESS )
01000         return NULL;
01001     else
01002         return result.value.psz; // no need to duplicate
01003 }
01004 
01005 /**
01006  * @brief Generic update in Media Library database
01007  *
01008  * @param p_media_library the media library object
01009  * @param selected_type the type of the element we're selecting
01010  * @param where list of ids/uris to be changed
01011  * @param changes list of changes to make in the entries
01012  * @return VLC_SUCCESS or VLC_EGENERIC
01013  */
01014 static inline int ml_Update( media_library_t *p_media_library,
01015                              ml_select_e selected_type,
01016                              const char* psz_lvalue,
01017                              ml_ftree_t *where,
01018                              vlc_array_t *changes )
01019 {
01020     return p_media_library->functions.pf_Update( p_media_library,
01021                                                  selected_type, psz_lvalue,
01022                                                  where, changes );
01023 }
01024 
01025 /**
01026  * @brief Update a given table
01027  * @param p_media_library The media library object
01028  * @param selected_type The table to update
01029  * @param psz_lvalue The role of the person if selected_type = ML_PEOPLE
01030  * @param id The id of the row to update
01031  * @param ... The update data. [SelectType [RoleType] Value]
01032  */
01033 VLC_API int ml_UpdateSimple( media_library_t *p_media_library,
01034                                      ml_select_e selected_type,
01035                                      const char* psz_lvalue,
01036                                      int id, ... );
01037 #define ml_UpdateSimple( ml, sel, lval, id, ... ) \
01038         ml_UpdateSimple( ml, sel, lval, id, __VA_ARGS__, ML_END )
01039 
01040 /**
01041  * @brief Generic DELETE function
01042  * Delete a media and all its references which don't point
01043  * to anything else.
01044  *
01045  * @param p_media_library This media_library_t object
01046  * @param id the id of the media to delete
01047  * @return VLC_SUCCESS or VLC_EGENERIC
01048  */
01049 static inline int
01050 ml_DeleteSimple( media_library_t *p_media_library, int id )
01051 {
01052     vlc_array_t* p_where = vlc_array_new();
01053     ml_element_t* p_find = (ml_element_t *) calloc( 1, sizeof( ml_element_t ) );
01054     p_find->criteria = ML_ID;
01055     p_find->value.i = id;
01056     vlc_array_append( p_where, p_find );
01057     int i_return =  p_media_library->functions.pf_Delete( p_media_library,
01058             p_where );
01059     free( p_find );
01060     vlc_array_destroy( p_where );
01061     return i_return;
01062 }
01063 
01064 /**
01065  * @brief Delete many medias in the media library
01066  * @param p_media_library Media library object
01067  * @param p_array Array of ids to delete
01068  * @return VLC_SUCCESS or VLC_EGENERIC
01069  */
01070 static inline int
01071 ml_Delete( media_library_t *p_media_library, vlc_array_t* p_array )
01072 {
01073     return p_media_library->functions.pf_Delete( p_media_library,
01074                                                         p_array );
01075 }
01076 
01077 
01078 /*****************************************************************************
01079  * ML Person Related Functions
01080  *****************************************************************************/
01081 
01082 /**
01083  * @brief Create and append a person object to the given list
01084  * @param pp_person pointer to person list. Set the address to null to create new list
01085  * @param i_role The role of the person
01086  * @param psz_name The name string. Will be strdup'd
01087  * @param i_id The id in the database
01088  * @note This function is NOT thread safe. Please lock any associated media
01089  */
01090 static inline int ml_CreateAppendPersonAdv( ml_person_t **pp_person,
01091         const char* psz_role, const char* psz_name, int i_id )
01092 {
01093     if( i_id == 0 || !( psz_name && *psz_name && psz_role && *psz_role ) )
01094         return VLC_SUCCESS;
01095     if( !pp_person )
01096         return VLC_EGENERIC;
01097     if( *pp_person != NULL )
01098         return ml_CreateAppendPersonAdv( &((**pp_person).p_next),
01099                                          psz_role, psz_name, i_id);
01100     *pp_person = ( ml_person_t * ) calloc( 1, sizeof( ml_person_t ) );
01101     (*pp_person)->psz_name = (psz_name && *psz_name) ? strdup( psz_name ): NULL;
01102     (*pp_person)->psz_role = (psz_role && *psz_role) ? strdup( psz_role ): NULL;
01103     (*pp_person)->i_id = i_id;
01104     (*pp_person)->p_next = NULL;
01105     return VLC_SUCCESS;
01106 }
01107 
01108 /**
01109  * @brief Create and append a person object to the given list
01110  * @param pp_person pointer to person list.
01111  * Set the address to NULL to create a new list
01112  * @param personfrom Person object to copy from
01113  * @note Ignores the next variable and copies only the variables.
01114  * Uses ml_CreateAppendPersonAdv
01115  * @note This function is NOT threadsafe
01116  */
01117 static inline int ml_CreateAppendPerson( ml_person_t **pp_person,
01118                                          ml_person_t *p_personfrom )
01119 {
01120     return ml_CreateAppendPersonAdv( pp_person,
01121                                      p_personfrom->psz_role,
01122                                      p_personfrom->psz_name,
01123                                      p_personfrom->i_id );
01124 }
01125 
01126 /**
01127  * @brief Copy one person list into another
01128  * @param a To list
01129  * @param b From list
01130  * @note On errors, you have to free any allocated persons yourself
01131  * @note This function is NOT threadsafe. Please ensure your medias are locked
01132  */
01133 static inline int ml_CopyPersons( ml_person_t** a, ml_person_t* b )
01134 {
01135     int i_ret;
01136     while( b )
01137     {
01138         i_ret = ml_CreateAppendPerson( a, b );
01139         if( i_ret != VLC_SUCCESS )
01140             return i_ret;
01141         b = b->p_next;
01142     }
01143     return VLC_SUCCESS;
01144 }
01145 
01146 
01147 /**
01148  * @brief Returns a person list of given type
01149  * @param p_ml The ML object
01150  * @param p_media The Media object
01151  * @param i_type The person type
01152  * @note This function is thread safe
01153  */
01154 VLC_API ml_person_t *ml_GetPersonsFromMedia( media_library_t* p_ml,
01155                                                     ml_media_t* p_media,
01156                                                     const char *psz_role );
01157 
01158 
01159 #define ml_GetAlbumArtistsFromMedia( a, b ) ml_GetPersonsFromMedia( a, b, ML_PERSON_ALBUM_ARTIST );
01160 #define ml_GetArtistsFromMedia( a, b )      ml_GetPersonsFromMedia( a, b, ML_PERSON_ARTIST );
01161 #define ml_GetEncodersFromMedia( a, b )     ml_GetPersonsFromMedia( a, b, ML_PERSON_ENCODER );
01162 #define ml_GetPublishersFromMedia( a, b )   ml_GetPersonsFromMedia( a, b, ML_PERSON_PUBLISHER );
01163 
01164 /**
01165  * @brief Delete a certain type of people from a media
01166  * @param p_media Media to delete from
01167  * @param i_type Type of person to delete
01168  * @note This function is threadsafe
01169  */
01170 VLC_API void ml_DeletePersonTypeFromMedia( ml_media_t* p_media,
01171                                                  const char *psz_role );
01172 
01173 
01174 /**
01175  * @brief Creates and adds the playlist based on a given find tree
01176  * @param p_ml Media library object
01177  * @param p_tree Find tree to create SELECT
01178  */
01179 
01180 VLC_API void ml_PlaySmartPlaylistBasedOn( media_library_t* p_ml,
01181                                                 ml_ftree_t* p_tree );
01182 
01183 
01184 /**
01185  * Convenience Macros
01186  */
01187 
01188 /**
01189  * Get information using the *media* ID. This returns only 1 information.
01190  * @note You have to free the string returned (if that's a string!).
01191  */
01192 #define ml_GetAlbumById( a, id )            ml_GetPsz( a, ML_ALBUM, ML_ID, id )
01193 #define ml_GetArtistById( a, id )           ml_GetPsz( a, ML_PEOPLE, ML_PERSON_ARTIST, ML_ID, id )
01194 #define ml_GetCoverUriById( a, id )         ml_GetPsz( a, ML_COVER, ML_ID, id )
01195 #define ml_GetEncoderById( a, id )          ml_GetPsz( a, ML_PEOPLE, ML_PERSON_ENCODER, ML_ID, id )
01196 #define ml_GetExtraById( a, id )            ml_GetPsz( a, ML_EXTRA, ML_ID, id )
01197 #define ml_GetGenreById( a, id )            ml_GetPsz( a, ML_GENRE, ML_ID, id )
01198 #define ml_GetOriginalTitleById( a, id )    ml_GetPsz( a, ML_ORIGINAL_TITLE, ML_ID, id )
01199 #define ml_GetPublisherById( a, id )        ml_GetPsz( a, ML_PEOPLE, ML_PERSON_PUBLISHER, ML_ID, id )
01200 #define ml_GetTitleById( a, id )            ml_GetPsz( a, ML_TITLE, ML_ID, id )
01201 #define ml_GetUriById( a, id )              ml_GetPsz( a, ML_URI, ML_ID, id )
01202 
01203 #define ml_GetAlbumIdById( a, id )          ml_GetInt( a, ML_ALBUM_ID, ML_ID, id )
01204 #define ml_GetArtistIdById( a, id )         ml_GetInt( a, ML_PEOPLE_ID, ML_PERSON_ARTIST, ML_ID, id )
01205 #define ml_GetDurationById( a, id )         ml_GetInt( a, ML_DURATION, ML_ID, id )
01206 #define ml_GetEncoderIdById( a, id )        ml_GetInt( a, ML_PEOPLE_ID, ML_PERSON_ENCODER, ML_ID, id )
01207 #define ml_GetLastPlayedById( a, id )       ml_GetInt( a, ML_LAST_PLAYED, ML_ID, id )
01208 #define ml_GetPlayedCountById( a, id )      ml_GetInt( a, ML_PLAYED_COUNT, ML_ID, id )
01209 #define ml_GetPublisherIdById( a, id )      ml_GetInt( a, ML_PEOPLE_ID, ML_PERSON_PUBLISHER, ML_ID, id )
01210 #define ml_GetScoreById( a, id )            ml_GetInt( a, ML_SCORE, ML_ID, id )
01211 #define ml_GetTrackNumberById( a, id )      ml_GetInt( a, ML_TRACK_NUMBER, ML_ID, id )
01212 #define ml_GetTypeById( a, id )             ml_GetInt( a, ML_TYPE, ML_ID, id )
01213 #define ml_GetYearById( a, id )             ml_GetInt( a, ML_YEAR, ML_ID, id )
01214 #define ml_GetVoteById( a, id )             ml_GetInt( a, ML_VOTE, ML_ID, id )
01215 
01216 /** Albums handling */
01217 #define ml_GetAlbumId( a, b )               ml_GetInt( a, ML_ALBUM_ID, ML_ALBUM, b )
01218 
01219 /** People handling */
01220 #define ml_GetArtistId( a, b )              ml_GetInt( a, ML_PERSON_ID, ML_PERSON_ARTIST, ML_PERSON, ML_PERSON_ARTIST, b )
01221 #define ml_GetEncoderId( a, b )             ml_GetInt( a, ML_PERSON_ID, ML_PERSON_ENCODER, ML_PERSON, ML_PERSON_ENCODER, b )
01222 #define ml_GetPublisherId( a, b )           ml_GetInt( a, ML_PERSON_ID, ML_PERSON_PUBLISHER, ML_PERSON, ML_PERSON_PUBLISHER, b )
01223 
01224 /** Counts handling */
01225 #define ml_GetMediaCount( a, ... )          __ml_GetInt( a, ML_COUNT_MEDIA,      __VA_ARGS__, ML_END )
01226 #define ml_GetAlbumCount( a, ... )          __ml_GetInt( a, ML_COUNT_ALBUM,      __VA_ARGS__, ML_END )
01227 #define ml_GetPeopleCount( a, ... )         __ml_GetInt( a, ML_COUNT_PEOPLE,     __VA_ARGS__, ML_END )
01228 
01229 #define ml_Find( a, b, ... )                __ml_Find( a, b, __VA_ARGS__, ML_END )
01230 
01231 #define ml_FindAlbum( a, b, ... )           __ml_Find( a, b, ML_ALBUM,           __VA_ARGS__, ML_END )
01232 #define ml_FindArtist( a, b, ... )          __ml_Find( a, b, ML_PERSON, ML_PERSON_ARTIST, __VA_ARGS__, ML_END )
01233 #define ml_FindEncoder( a, b, ... )         __ml_Find( a, b, ML_PERSON, ML_PERSON_ENCODER, __VA_ARGS__, ML_END )
01234 #define ml_FindGenre( a, b, ... )           __ml_Find( a, b, ML_GENRE,           __VA_ARGS__, ML_END )
01235 #define ml_FindMedia( a, b, ... )           __ml_Find( a, b, ML_MEDIA,           __VA_ARGS__, ML_END )
01236 #define ml_FindOriginalTitle( a, b, ... )   __ml_Find( a, b, ML_ORIGINAL_TITLE,  __VA_ARGS__, ML_END )
01237 #define ml_FindPublisher( a, b, ... )       __ml_Find( a, b, ML_PERSON, ML_PERSON_PUBLISHER, __VA_ARGS__, ML_END )
01238 #define ml_FindTitle( a, b, ... )           __ml_Find( a, b, ML_TITLE,           __VA_ARGS__, ML_END )
01239 #define ml_FindType( a, b, ... )            __ml_Find( a, b, ML_TYPE,            __VA_ARGS__, ML_END )
01240 #define ml_FindUri( a, b, ... )             __ml_Find( a, b, ML_URI,             __VA_ARGS__, ML_END )
01241 #define ml_FindYear( a, b, ... )            __ml_Find( a, b, ML_YEAR,            __VA_ARGS__, ML_END )
01242 
01243 #define ml_FindAllAlbums( a, b )            ml_FindAlbum( a, b,         ML_DISTINCT )
01244 #define ml_FindAllArtists( a, b )           ml_FindArtist( a, b,        ML_DISTINCT )
01245 #define ml_FindAllGenres( a, b )            ml_FindGenre( a, b,         ML_DISTINCT )
01246 #define ml_FindAllMedias( a, b )            ml_FindMedia( a, b,         ML_DISTINCT )
01247 #define ml_FindAllOriginalTitles( a, b )    ml_FindOriginalTitle( a, b, ML_DISTINCT )
01248 #define ml_FindAllPublishers( a, b, ... )   ml_FindPublisher( a, b,     ML_DISTINCT )
01249 #define ml_FindAllTitles( a, b )            ml_FindTitle( a, b,         ML_DISTINCT )
01250 #define ml_FindAllTypes( a, b )             ml_FindType( a, b,          ML_DISTINCT )
01251 #define ml_FindAllUris( a, b )              ml_FindUri( a, b,           ML_DISTINCT )
01252 #define ml_FindAllYears( a, b )             ml_FindYear( a, b,          ML_DISTINCT )
01253 
01254 #define ml_FindAlbumAdv( a, b, c )          ml_FindAdv( a, b, ML_ALBUM,         NULL, c )
01255 #define ml_FindArtistAdv( a, b, c )         ml_FindAdv( a, b, ML_PERSON,        ML_PERSON_ARTIST, c )
01256 #define ml_FindEncoderAdv( a, b, c )        ml_FindAdv( a, b, ML_PERSON,        ML_PERSON_ENCODER, c )
01257 #define ml_FindGenreAdv( a, b, c )          ml_FindAdv( a, b, ML_GENRE,         NULL, c )
01258 #define ml_FindMediaAdv( a, b, c )          ml_FindAdv( a, b, ML_MEDIA,         NULL, c )
01259 #define ml_FindOriginalTitleAdv( a, b, c )  ml_FindAdv( a, b, ML_ORIGINAL_TITLE,NULL, c )
01260 #define ml_FindPublisherAdv( a, b, c )      ml_FindAdv( a, b, ML_PUBLISHER,     ML_PERSON_PUBLISHER, c )
01261 #define ml_FindTitleAdv( a, b, c )          ml_FindAdv( a, b, ML_TITLE,         NULL, c )
01262 #define ml_FindTypeAdv( a, b, c )           ml_FindAdv( a, b, ML_TYPE,          NULL, c )
01263 #define ml_FindUriAdv( a, b, c )            ml_FindAdv( a, b, ML_URI,           NULL, c )
01264 #define ml_FindYearAdv( a, b, c )           ml_FindAdv( a, b, ML_YEAR,          NULL, c )
01265 
01266 
01267 
01268 #ifdef __cplusplus
01269 }
01270 #endif /* C++ */
01271 
01272 #endif /* VLC_MEDIA_LIBRARY_H */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines