1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2010-2014 - Hans-Kristian Arntzen
3  *  Copyright (C) 2011-2017 - Daniel De Matteis
4  *  Copyright (C) 2016-2019 - Brad Parker
5  *
6  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
7  *  of the GNU General Public License as published by the Free Software Found-
8  *  ation, either version 3 of the License, or (at your option) any later version.
9  *
10  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  *  PURPOSE.  See the GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along with RetroArch.
15  *  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef _PLAYLIST_H__
19 #define _PLAYLIST_H__
20 
21 #include <stddef.h>
22 
23 #include <retro_common_api.h>
24 #include <boolean.h>
25 #include <lists/string_list.h>
26 
27 #include "core_info.h"
28 
29 RETRO_BEGIN_DECLS
30 
31 /* Default maximum playlist size */
32 #define COLLECTION_SIZE 0x7FFFFFFF
33 
34 typedef struct content_playlist playlist_t;
35 
36 enum playlist_runtime_status
37 {
38    PLAYLIST_RUNTIME_UNKNOWN = 0,
39    PLAYLIST_RUNTIME_MISSING,
40    PLAYLIST_RUNTIME_VALID
41 };
42 
43 enum playlist_file_mode
44 {
45    PLAYLIST_LOAD = 0,
46    PLAYLIST_SAVE
47 };
48 
49 enum playlist_label_display_mode
50 {
51    LABEL_DISPLAY_MODE_DEFAULT = 0,
52    LABEL_DISPLAY_MODE_REMOVE_PARENTHESES,
53    LABEL_DISPLAY_MODE_REMOVE_BRACKETS,
54    LABEL_DISPLAY_MODE_REMOVE_PARENTHESES_AND_BRACKETS,
55    LABEL_DISPLAY_MODE_KEEP_REGION,
56    LABEL_DISPLAY_MODE_KEEP_DISC_INDEX,
57    LABEL_DISPLAY_MODE_KEEP_REGION_AND_DISC_INDEX
58 };
59 
60 enum playlist_thumbnail_mode
61 {
62    PLAYLIST_THUMBNAIL_MODE_DEFAULT = 0,
63    PLAYLIST_THUMBNAIL_MODE_OFF,
64    PLAYLIST_THUMBNAIL_MODE_SCREENSHOTS,
65    PLAYLIST_THUMBNAIL_MODE_TITLE_SCREENS,
66    PLAYLIST_THUMBNAIL_MODE_BOXARTS
67 };
68 
69 enum playlist_sort_mode
70 {
71    PLAYLIST_SORT_MODE_DEFAULT = 0,
72    PLAYLIST_SORT_MODE_ALPHABETICAL,
73    PLAYLIST_SORT_MODE_OFF
74 };
75 
76 /* TODO/FIXME - since gfx_thumbnail_path.h has now
77  * been divorced from the menu code, perhaps jdgleaver
78  * can refactor this? */
79 
80 /* Note: We already have a left/right enum defined
81  * in gfx_thumbnail_path.h - but we can't include
82  * menu code here, so have to make a 'duplicate'... */
83 enum playlist_thumbnail_id
84 {
85    PLAYLIST_THUMBNAIL_RIGHT = 0,
86    PLAYLIST_THUMBNAIL_LEFT
87 };
88 
89 /* Holds all parameters required to uniquely
90  * identify a playlist content path */
91 typedef struct
92 {
93    char *real_path;
94    char *archive_path;
95    uint32_t real_path_hash;
96    uint32_t archive_path_hash;
97    bool is_archive;
98    bool is_in_archive;
99 } playlist_path_id_t;
100 
101 struct playlist_entry
102 {
103    char *path;
104    char *label;
105    char *core_path;
106    char *core_name;
107    char *db_name;
108    char *crc32;
109    char *subsystem_ident;
110    char *subsystem_name;
111    char *runtime_str;
112    char *last_played_str;
113    struct string_list *subsystem_roms;
114    playlist_path_id_t *path_id;
115    unsigned runtime_hours;
116    unsigned runtime_minutes;
117    unsigned runtime_seconds;
118    /* Note: due to platform dependence, have to record
119     * timestamp as either a string or independent integer
120     * values. The latter is more verbose, but more efficient. */
121    unsigned last_played_year;
122    unsigned last_played_month;
123    unsigned last_played_day;
124    unsigned last_played_hour;
125    unsigned last_played_minute;
126    unsigned last_played_second;
127    enum playlist_runtime_status runtime_status;
128 };
129 
130 /* Holds all configuration parameters required
131  * when initialising/saving playlists */
132 typedef struct
133 {
134    size_t capacity;
135    bool old_format;
136    bool compress;
137    bool fuzzy_archive_match;
138    bool autofix_paths;
139    char path[PATH_MAX_LENGTH];
140    char base_content_directory[PATH_MAX_LENGTH];
141 } playlist_config_t;
142 
143 /* Convenience function: copies specified playlist
144  * path to specified playlist configuration object */
145 void playlist_config_set_path(playlist_config_t *config, const char *path);
146 
147 /* Convenience function: copies base content directory
148  * path to specified playlist configuration object */
149 void playlist_config_set_base_content_directory(playlist_config_t* config, const char* path);
150 
151 /* Creates a copy of the specified playlist configuration.
152  * Returns false in the event of an error */
153 bool playlist_config_copy(const playlist_config_t *src, playlist_config_t *dst);
154 
155 /* Returns internal playlist configuration object
156  * of specified playlist.
157  * Returns NULL it the event of an error. */
158 playlist_config_t *playlist_get_config(playlist_t *playlist);
159 
160 /**
161  * playlist_init:
162  * @config            	: Playlist configuration object.
163  *
164  * Creates and initializes a playlist.
165  *
166  * Returns: handle to new playlist if successful, otherwise NULL
167  **/
168 playlist_t *playlist_init(const playlist_config_t *config);
169 
170 /**
171  * playlist_free:
172  * @playlist        	   : Playlist handle.
173  *
174  * Frees playlist handle.
175  */
176 void playlist_free(playlist_t *playlist);
177 
178 /**
179  * playlist_clear:
180  * @playlist        	   : Playlist handle.
181  *
182  * Clears all playlist entries in playlist.
183  **/
184 void playlist_clear(playlist_t *playlist);
185 
186 /**
187  * playlist_size:
188  * @playlist        	   : Playlist handle.
189  *
190  * Gets size of playlist.
191  * Returns: size of playlist.
192  **/
193 size_t playlist_size(playlist_t *playlist);
194 
195 /**
196  * playlist_capacity:
197  * @playlist        	   : Playlist handle.
198  *
199  * Gets maximum capacity of playlist.
200  * Returns: maximum capacity of playlist.
201  **/
202 size_t playlist_capacity(playlist_t *playlist);
203 
204 /**
205  * playlist_get_index:
206  * @playlist               : Playlist handle.
207  * @idx                 : Index of playlist entry.
208  *
209  * Gets values of playlist index:
210  **/
211 void playlist_get_index(playlist_t *playlist,
212       size_t idx,
213       const struct playlist_entry **entry);
214 
215 /**
216  * playlist_delete_index:
217  * @playlist               : Playlist handle.
218  * @idx                 : Index of playlist entry.
219  *
220  * Deletes the entry at index:
221  **/
222 void playlist_delete_index(playlist_t *playlist,
223       size_t idx);
224 
225 /**
226  * playlist_delete_by_path:
227  * @playlist            : Playlist handle.
228  * @search_path         : Content path.
229  *
230  * Deletes all entries with content path
231  * matching 'search_path'
232  **/
233 void playlist_delete_by_path(playlist_t *playlist,
234       const char *search_path);
235 
236 /**
237  * playlist_resolve_path:
238  * @mode      : PLAYLIST_LOAD or PLAYLIST_SAVE
239  * @is_core   : Set true if path to be resolved is a core file
240  * @path      : The path to be modified
241  *
242  * Resolves the path of an item, such as the content path or path to the core, to a format
243  * appropriate for saving or loading depending on the @mode parameter
244  *
245  * Can be platform specific. File paths for saving can be abbreviated to avoid saving absolute
246  * paths, as the base directory (home or application dir) may change after each subsequent
247  * install (iOS)
248  **/
249 void playlist_resolve_path(enum playlist_file_mode mode,
250       bool is_core, char *path, size_t len);
251 
252 /**
253  * playlist_push:
254  * @playlist        	   : Playlist handle.
255  *
256  * Push entry to top of playlist.
257  **/
258 bool playlist_push(playlist_t *playlist,
259       const struct playlist_entry *entry);
260 
261 bool playlist_push_runtime(playlist_t *playlist,
262       const struct playlist_entry *entry);
263 
264 void playlist_update(playlist_t *playlist, size_t idx,
265       const struct playlist_entry *update_entry);
266 
267 /* Note: register_update determines whether the internal
268  * 'playlist->modified' flag is set when updating runtime
269  * values. Since these are normally set temporarily (for
270  * display purposes), we do not always want this function
271  * to trigger a re-write of the playlist file. */
272 void playlist_update_runtime(playlist_t *playlist, size_t idx,
273       const struct playlist_entry *update_entry,
274       bool register_update);
275 
276 void playlist_get_index_by_path(playlist_t *playlist,
277       const char *search_path,
278       const struct playlist_entry **entry);
279 
280 bool playlist_entry_exists(playlist_t *playlist,
281       const char *path);
282 
283 char *playlist_get_conf_path(playlist_t *playlist);
284 
285 uint32_t playlist_get_size(playlist_t *playlist);
286 
287 void playlist_write_file(playlist_t *playlist);
288 
289 void playlist_write_runtime_file(playlist_t *playlist);
290 
291 void playlist_qsort(playlist_t *playlist);
292 
293 void playlist_free_cached(void);
294 
295 playlist_t *playlist_get_cached(void);
296 
297 /* If current on-disk playlist file referenced
298  * by 'config->path' does not match requested
299  * 'old format' or 'compression' state, file will
300  * be updated automatically
301  * > Since this function is called whenever a
302  *   playlist is browsed via the menu, this is
303  *   a simple method for ensuring that files
304  *   are always kept synced with user settings */
305 bool playlist_init_cached(const playlist_config_t *config);
306 
307 void command_playlist_push_write(
308       playlist_t *playlist,
309       const struct playlist_entry *entry);
310 
311 void command_playlist_update_write(
312       playlist_t *playlist,
313       size_t idx,
314       const struct playlist_entry *entry);
315 
316 /* Returns true if specified playlist index matches
317  * specified content/core paths */
318 bool playlist_index_is_valid(playlist_t *playlist, size_t idx,
319       const char *path, const char *core_path);
320 
321 /* Returns true if specified playlist entries have
322  * identical content and core paths */
323 bool playlist_entries_are_equal(
324       const struct playlist_entry *entry_a,
325       const struct playlist_entry *entry_b,
326       const playlist_config_t *config);
327 
328 /* Returns true if entries at specified indices
329  * of specified playlist have identical content
330  * and core paths */
331 bool playlist_index_entries_are_equal(
332       playlist_t *playlist, size_t idx_a, size_t idx_b);
333 
334 void playlist_get_crc32(playlist_t *playlist, size_t idx,
335       const char **crc32);
336 
337 /* If db_name is empty, 'returns' playlist file basename */
338 void playlist_get_db_name(playlist_t *playlist, size_t idx,
339       const char **db_name);
340 
341 char *playlist_get_default_core_path(playlist_t *playlist);
342 char *playlist_get_default_core_name(playlist_t *playlist);
343 enum playlist_label_display_mode playlist_get_label_display_mode(playlist_t *playlist);
344 enum playlist_thumbnail_mode playlist_get_thumbnail_mode(
345       playlist_t *playlist, enum playlist_thumbnail_id thumbnail_id);
346 enum playlist_sort_mode playlist_get_sort_mode(playlist_t *playlist);
347 
348 void playlist_set_default_core_path(playlist_t *playlist, const char *core_path);
349 void playlist_set_default_core_name(playlist_t *playlist, const char *core_name);
350 void playlist_set_label_display_mode(playlist_t *playlist, enum playlist_label_display_mode label_display_mode);
351 void playlist_set_thumbnail_mode(
352       playlist_t *playlist, enum playlist_thumbnail_id thumbnail_id, enum playlist_thumbnail_mode thumbnail_mode);
353 void playlist_set_sort_mode(playlist_t *playlist, enum playlist_sort_mode sort_mode);
354 
355 /* Returns true if specified entry has a valid
356  * core association (i.e. a non-empty string
357  * other than DETECT) */
358 bool playlist_entry_has_core(const struct playlist_entry *entry);
359 
360 /* Fetches core info object corresponding to the
361  * currently associated core of the specified
362  * playlist entry.
363  * Returns NULL if entry does not have a valid
364  * core association */
365 core_info_t *playlist_entry_get_core_info(const struct playlist_entry* entry);
366 
367 /* Fetches core info object corresponding to the
368  * currently associated default core of the
369  * specified playlist.
370  * Returns NULL if playlist does not have a valid
371  * default core association */
372 core_info_t *playlist_get_default_core_info(playlist_t* playlist);
373 
374 void playlist_set_cached_external(playlist_t* pl);
375 
376 RETRO_END_DECLS
377 
378 #endif
379