2 * GeeXboX Valhalla: tiny media scanner API.
3 * Copyright (C) 2009-2010 Mathieu Schroeter <mathieu.schroeter@gamesover.ch>
5 * This file is part of libvalhalla.
7 * libvalhalla is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * libvalhalla is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with libvalhalla; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <libavcodec/avcodec.h>
29 #include <libavformat/avformat.h>
32 #include "valhalla_internals.h"
35 #include "dbmanager.h"
36 #include "dispatcher.h"
38 #include "event_handler.h"
47 #include "downloader.h"
48 #include "url_utils.h"
49 #endif /* USE_GRABBER */
52 static pthread_mutex_t g_preinit_mutex = PTHREAD_MUTEX_INITIALIZER;
56 libvalhalla_version (void)
58 return LIBVALHALLA_VERSION_INT;
61 /******************************************************************************/
63 /* Valhalla Handling */
65 /******************************************************************************/
68 queue_cleanup (fifo_queue_t *queue)
73 vh_fifo_queue_push (queue,
74 FIFO_QUEUE_PRIORITY_NORMAL, ACTION_CLEANUP_END, NULL);
78 e = ACTION_NO_OPERATION;
80 vh_fifo_queue_pop (queue, &e, &data);
87 case ACTION_DB_INSERT_P:
88 case ACTION_DB_INSERT_G:
89 case ACTION_DB_UPDATE_P:
90 case ACTION_DB_UPDATE_G:
92 case ACTION_DB_NEWFILE:
94 vh_file_data_free (data);
97 case ACTION_DB_EXT_INSERT:
98 case ACTION_DB_EXT_UPDATE:
99 case ACTION_DB_EXT_DELETE:
101 vh_dbmanager_extmd_free (data);
104 case ACTION_OD_ENGAGE:
105 case ACTION_EH_EVENTGL:
110 case ACTION_EH_EVENTOD:
112 vh_event_handler_od_free (data);
115 case ACTION_EH_EVENTMD:
117 vh_event_handler_md_free (data);
121 while (e != ACTION_CLEANUP_END);
125 valhalla_mrproper (valhalla_t *handle)
128 fifo_queue_t *fifo_o;
130 fifo_queue_t *fifo_i[] = {
131 vh_scanner_fifo_get (handle->scanner),
132 vh_dbmanager_fifo_get (handle->dbmanager),
133 vh_dispatcher_fifo_get (handle->dispatcher),
134 vh_parser_fifo_get (handle->parser),
136 vh_grabber_fifo_get (handle->grabber),
137 vh_downloader_fifo_get (handle->downloader),
138 #endif /* USE_GRABBER */
139 vh_event_handler_fifo_get (handle->event_handler),
142 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
147 fifo_o = vh_fifo_queue_new ();
152 vh_dbmanager_db_begin_transaction (handle->dbmanager);
154 /* remove all previous contexts */
155 vh_dbmanager_db_dlcontext_delete (handle->dbmanager);
156 #endif /* USE_GRABBER */
159 * The same data pointer can exist in several queues at the same time.
160 * The goal is to identify all unique entries from all queues and to save
161 * these entries in the fifo_o queue.
162 * Then, all data pointers can be safety freed (prevents double free).
164 for (i = 0; i < ARRAY_NB_ELEMENTS (fifo_i); i++)
172 vh_fifo_queue_push (fifo_i[i],
173 FIFO_QUEUE_PRIORITY_NORMAL, ACTION_CLEANUP_END, NULL);
177 e = ACTION_NO_OPERATION;
179 vh_fifo_queue_pop (fifo_i[i], &e, &data);
183 case ACTION_DB_INSERT_P:
184 case ACTION_DB_INSERT_G:
185 case ACTION_DB_UPDATE_P:
186 case ACTION_DB_UPDATE_G:
188 case ACTION_DB_NEWFILE:
190 file_data_t *file = data;
191 if (!file || file->clean_f)
195 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
198 /* save downloader context */
199 if (file->step < STEP_ENDING && file->list_downloader)
200 vh_dbmanager_db_dlcontext_save (handle->dbmanager, file);
201 #endif /* USE_GRABBER */
205 case ACTION_DB_EXT_INSERT:
206 case ACTION_DB_EXT_UPDATE:
207 case ACTION_DB_EXT_DELETE:
208 case ACTION_EH_EVENTOD:
209 case ACTION_EH_EVENTMD:
210 case ACTION_EH_EVENTGL:
211 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
218 while (e != ACTION_CLEANUP_END);
222 vh_dbmanager_db_end_transaction (handle->dbmanager);
223 #endif /* USE_GRABBER */
225 queue_cleanup (fifo_o);
226 vh_fifo_queue_free (fifo_o);
228 /* On-demand queue must be handled separately. */
229 fifo_o = vh_ondemand_fifo_get (handle->ondemand);
232 queue_cleanup (fifo_o);
236 valhalla_config_set_orig (valhalla_t *handle, valhalla_cfg_t conf, ...)
239 const void *p1 = NULL, *p2 = NULL;
242 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
247 if (conf >= (1 << VH_CFG_RANGE))
253 if (conf & VH_VOIDP_T)
254 p1 = va_arg (ap, void *);
256 i = va_arg (ap, int);
257 if (conf & VH_VOIDP_2_T)
258 p2 = va_arg (ap, void *);
260 if (va_arg (ap, int) != ~0) /* check for safeguard */
262 vh_log (VALHALLA_MSG_CRITICAL,
263 "unrecoverable error with valhalla_config_set(), conf = %#x, "
264 "it is probably a bad use of this function", conf);
277 case VALHALLA_CFG_DOWNLOADER_DEST:
278 vh_downloader_destination_set (handle->downloader, (valhalla_dl_t) i, p1);
281 case VALHALLA_CFG_GRABBER_PRIORITY:
282 vh_grabber_priority_set (handle->grabber,
283 p1, (valhalla_metadata_pl_t) i, p2);
286 case VALHALLA_CFG_GRABBER_STATE:
288 vh_grabber_state_set (handle->grabber, p1, i);
290 #endif /* USE_GRABBER */
292 case VALHALLA_CFG_PARSER_KEYWORD:
294 vh_parser_bl_keyword_add (handle->parser, p1);
297 case VALHALLA_CFG_SCANNER_PATH:
299 vh_scanner_path_add (handle->scanner, p1, i);
302 case VALHALLA_CFG_SCANNER_SUFFIX:
304 vh_scanner_suffix_add (handle->scanner, p1);
308 vh_log (VALHALLA_MSG_WARNING,
309 "%s: unsupported option %#x", __FUNCTION__, conf);
318 valhalla_wait (valhalla_t *handle)
320 const int f = STOP_FLAG_REQUEST | STOP_FLAG_WAIT;
322 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
324 if (!handle || handle->noscan)
327 vh_scanner_wait (handle->scanner);
329 vh_ondemand_stop (handle->ondemand, f);
330 vh_dbmanager_wait (handle->dbmanager);
331 vh_dispatcher_stop (handle->dispatcher, f);
332 vh_parser_stop (handle->parser, f);
334 vh_grabber_stop (handle->grabber, f);
335 vh_downloader_stop (handle->downloader, f);
336 #endif /* USE_GRABBER */
337 vh_event_handler_stop (handle->event_handler, f);
343 valhalla_force_stop (valhalla_t *handle)
347 vh_log (VALHALLA_MSG_WARNING,
348 "%s: This can take a time, please be patient", __FUNCTION__);
350 for (i = 0; i < 2; i++)
352 int f = !i ? STOP_FLAG_REQUEST : STOP_FLAG_WAIT;
354 vh_ondemand_stop (handle->ondemand, f);
356 vh_scanner_stop (handle->scanner, f);
357 vh_dbmanager_stop (handle->dbmanager, f);
358 vh_dispatcher_stop (handle->dispatcher, f);
359 vh_parser_stop (handle->parser, f);
361 vh_grabber_stop (handle->grabber, f);
362 vh_downloader_stop (handle->downloader, f);
363 #endif /* USE_GRABBER */
364 vh_event_handler_stop (handle->event_handler, f);
367 valhalla_mrproper (handle);
373 valhalla_uninit (valhalla_t *handle)
377 vh_log (VALHALLA_MSG_VERBOSE, "%s: begin", __FUNCTION__);
382 pthread_mutex_lock (&g_preinit_mutex);
383 preinit = --g_preinit;
384 pthread_mutex_unlock (&g_preinit_mutex);
387 valhalla_force_stop (handle);
389 /* dump all statistics */
390 vh_stats_dump (handle->stats, NULL);
391 vh_stats_debug_dump (handle->stats);
393 vh_ondemand_uninit (handle->ondemand);
394 vh_scanner_uninit (handle->scanner);
395 vh_dbmanager_uninit (handle->dbmanager);
396 vh_dispatcher_uninit (handle->dispatcher);
397 vh_parser_uninit (handle->parser);
399 vh_grabber_uninit (handle->grabber);
400 vh_downloader_uninit (handle->downloader);
401 #endif /* USE_GRABBER */
402 vh_event_handler_uninit (handle->event_handler);
405 vh_url_global_uninit ();
406 #endif /* USE_GRABBER */
410 av_lockmgr_register (NULL);
411 #endif /* USE_LAVC */
413 vh_stats_free (handle->stats);
415 vh_log (VALHALLA_MSG_VERBOSE, "%s: end", __FUNCTION__);
421 valhalla_run (valhalla_t *handle, int loop, uint16_t timeout, int priority)
425 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
428 return VALHALLA_ERROR_HANDLER;
431 return VALHALLA_ERROR_DEAD;
435 if (handle->event_handler)
437 res = vh_event_handler_run (handle->event_handler, priority);
439 return VALHALLA_ERROR_THREAD;
442 res = vh_scanner_run (handle->scanner, loop, timeout, priority);
445 if (res == SCANNER_ERROR_PATH)
448 vh_log (VALHALLA_MSG_INFO , "no path defined, scanner disabled");
451 return VALHALLA_ERROR_THREAD;
454 res = vh_dbmanager_run (handle->dbmanager, priority);
456 return VALHALLA_ERROR_THREAD;
458 res = vh_dispatcher_run (handle->dispatcher, priority);
460 return VALHALLA_ERROR_THREAD;
462 res = vh_parser_run (handle->parser, priority);
464 return VALHALLA_ERROR_THREAD;
467 res = vh_grabber_run (handle->grabber, priority);
469 return VALHALLA_ERROR_THREAD;
471 res = vh_downloader_run (handle->downloader, priority);
473 return VALHALLA_ERROR_THREAD;
474 #endif /* USE_GRABBER */
476 res = vh_ondemand_run (handle->ondemand, priority);
478 return VALHALLA_ERROR_THREAD;
480 return VALHALLA_SUCCESS;
484 valhalla_metadata_group_str (valhalla_meta_grp_t group)
486 return vh_metadata_group_str (group);
490 valhalla_grabber_next (valhalla_t *handle, const char *id)
492 vh_log (VALHALLA_MSG_VERBOSE, "%s : %s", __FUNCTION__, id ? id : "");
498 return vh_grabber_next (handle->grabber, id);
500 vh_log (VALHALLA_MSG_WARNING,
501 "This function is usable only with grabbing support!");
503 #endif /* USE_GRABBER */
506 valhalla_metadata_pl_t
507 valhalla_grabber_priority_read (valhalla_t *handle,
508 const char *id, const char **meta)
510 vh_log (VALHALLA_MSG_VERBOSE,
511 "%s : %s/%s", __FUNCTION__, id ? id : "", meta && *meta ? *meta : "");
517 return vh_grabber_priority_read (handle->grabber, id, meta);
519 vh_log (VALHALLA_MSG_WARNING,
520 "This function is usable only with grabbing support!");
522 #endif /* USE_GRABBER */
526 valhalla_stats_group_next (valhalla_t *handle, const char *id)
528 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
533 return vh_stats_group_next (handle->stats, id);
537 valhalla_stats_read_next (valhalla_t *handle, const char *id,
538 valhalla_stats_type_t type, const char **item)
540 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
545 return vh_stats_read_next (handle->stats, id, type, item);
549 valhalla_verbosity (valhalla_verb_t level)
556 valhalla_avlock (void **mutex, enum AVLockOp op)
561 *mutex = malloc (sizeof (pthread_mutex_t));
564 return !!pthread_mutex_init (*mutex, NULL);
567 return !!pthread_mutex_lock (*mutex);
569 case AV_LOCK_RELEASE:
570 return !!pthread_mutex_unlock (*mutex);
572 case AV_LOCK_DESTROY:
573 pthread_mutex_destroy (*mutex);
581 #endif /* USE_LAVC */
584 valhalla_init (const char *db, valhalla_init_param_t *param)
588 valhalla_init_param_t p;
589 const valhalla_init_param_t *pp = &p;
591 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
593 pthread_mutex_lock (&g_preinit_mutex);
595 pthread_mutex_unlock (&g_preinit_mutex);
597 if (!preinit && vh_osdep_init ())
606 memset (&p, 0, sizeof (p));
608 handle = calloc (1, sizeof (valhalla_t));
613 vh_url_global_init ();
614 #endif /* USE_GRABBER */
616 handle->stats = vh_stats_new ();
620 if (pp->od_cb || pp->gl_cb || pp->md_cb)
622 event_handler_cb_t cb;
624 cb.od_cb = pp->od_cb;
625 cb.gl_cb = pp->gl_cb;
626 cb.md_cb = pp->md_cb;
627 cb.od_data = pp->od_data;
628 cb.gl_data = pp->gl_data;
629 cb.md_data = pp->md_data;
631 handle->event_handler = vh_event_handler_init (handle, &cb);
632 if (!handle->event_handler)
636 handle->dispatcher = vh_dispatcher_init (handle);
637 if (!handle->dispatcher)
640 handle->parser = vh_parser_init (handle, pp->parser_nb, pp->decrapifier);
645 handle->grabber = vh_grabber_init (handle, pp->grabber_nb);
646 if (!handle->grabber)
649 handle->downloader = vh_downloader_init (handle);
650 if (!handle->downloader)
652 #endif /* USE_GRABBER */
654 handle->scanner = vh_scanner_init (handle);
655 if (!handle->scanner)
658 handle->dbmanager = vh_dbmanager_init (handle, db, pp->commit_int);
659 if (!handle->dbmanager)
662 handle->ondemand = vh_ondemand_init (handle);
663 if (!handle->ondemand)
669 if (av_lockmgr_register (valhalla_avlock))
671 #endif /* USE_LAVC */
672 av_log_set_level (AV_LOG_FATAL);
676 pthread_mutex_lock (&g_preinit_mutex);
678 pthread_mutex_unlock (&g_preinit_mutex);
683 valhalla_uninit (handle);
688 valhalla_scanner_wakeup (valhalla_t *handle)
690 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
695 vh_scanner_wakeup (handle->scanner);
699 valhalla_ondemand (valhalla_t *handle, const char *file)
703 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
705 if (!handle || !file)
708 odfile = strdup (file);
712 vh_ondemand_action_send (handle->ondemand, FIFO_QUEUE_PRIORITY_HIGH,
713 ACTION_OD_ENGAGE, odfile);
716 /******************************************************************************/
718 /* Public Database Selections */
720 /******************************************************************************/
723 valhalla_db_metalist_get (valhalla_t *handle, valhalla_db_item_t *search,
724 valhalla_file_type_t filetype,
725 valhalla_db_restrict_t *restriction)
727 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
729 if (!handle || !search)
732 return vh_dbmanager_db_metalist_get (handle->dbmanager,
733 search, filetype, restriction);
736 const valhalla_db_metares_t *
737 valhalla_db_metalist_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
739 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
741 if (!handle || !vhstmt)
744 return vh_dbmanager_db_metalist_read (handle->dbmanager, vhstmt);
748 valhalla_db_filelist_get (valhalla_t *handle, valhalla_file_type_t filetype,
749 valhalla_db_restrict_t *restriction)
751 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
757 vh_dbmanager_db_filelist_get (handle->dbmanager, filetype, restriction);
760 const valhalla_db_fileres_t *
761 valhalla_db_filelist_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
763 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
765 if (!handle || !vhstmt)
768 return vh_dbmanager_db_filelist_read (handle->dbmanager, vhstmt);
772 valhalla_db_file_get (valhalla_t *handle, int64_t id, const char *path,
773 valhalla_db_restrict_t *restriction)
775 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
780 return vh_dbmanager_db_file_get (handle->dbmanager, id, path, restriction);
783 const valhalla_db_metares_t *
784 valhalla_db_file_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
786 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
788 if (!handle || !vhstmt)
791 return vh_dbmanager_db_file_read (handle->dbmanager, vhstmt);
794 /******************************************************************************/
796 /* For Public Insertions/Updates/Deletions */
798 /******************************************************************************/
801 valhalla_db_metadata_insert (valhalla_t *handle, const char *path,
802 const char *meta, const char *data,
803 valhalla_meta_grp_t group)
805 dbmanager_extmd_t *extmd;
807 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
809 if (!handle || !path || !meta || !data)
812 extmd = calloc (1, sizeof (dbmanager_extmd_t));
816 extmd->path = strdup (path);
817 extmd->meta = strdup (meta);
818 extmd->data = strdup (data);
819 extmd->group = group;
821 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
822 ACTION_DB_EXT_INSERT, extmd);
827 valhalla_db_metadata_update (valhalla_t *handle, const char *path,
828 const char *meta, const char *data,
831 dbmanager_extmd_t *extmd;
833 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
835 if (!handle || !path || !meta || !data || !ndata)
838 extmd = calloc (1, sizeof (dbmanager_extmd_t));
842 extmd->path = strdup (path);
843 extmd->meta = strdup (meta);
844 extmd->data = strdup (data);
845 extmd->ndata = strdup (ndata);
847 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
848 ACTION_DB_EXT_UPDATE, extmd);
853 valhalla_db_metadata_delete (valhalla_t *handle, const char *path,
854 const char *meta, const char *data)
856 dbmanager_extmd_t *extmd;
858 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
860 if (!handle || !path || !meta || !data)
863 extmd = calloc (1, sizeof (dbmanager_extmd_t));
867 extmd->path = strdup (path);
868 extmd->meta = strdup (meta);
869 extmd->data = strdup (data);
871 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
872 ACTION_DB_EXT_DELETE, extmd);