2 * GeeXboX Valhalla: tiny media scanner API.
3 * Copyright (C) 2009 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"
46 #include "downloader.h"
47 #include "url_utils.h"
48 #endif /* USE_GRABBER */
52 libvalhalla_version (void)
54 return LIBVALHALLA_VERSION_INT;
57 /******************************************************************************/
59 /* Valhalla Handling */
61 /******************************************************************************/
64 queue_cleanup (fifo_queue_t *queue)
69 vh_fifo_queue_push (queue,
70 FIFO_QUEUE_PRIORITY_NORMAL, ACTION_CLEANUP_END, NULL);
74 e = ACTION_NO_OPERATION;
76 vh_fifo_queue_pop (queue, &e, &data);
83 case ACTION_DB_INSERT_P:
84 case ACTION_DB_INSERT_G:
85 case ACTION_DB_UPDATE_P:
86 case ACTION_DB_UPDATE_G:
88 case ACTION_DB_NEWFILE:
90 vh_file_data_free (data);
93 case ACTION_DB_EXT_INSERT:
94 case ACTION_DB_EXT_UPDATE:
95 case ACTION_DB_EXT_DELETE:
97 vh_dbmanager_extmd_free (data);
100 case ACTION_OD_ENGAGE:
101 case ACTION_EH_EVENTGL:
106 case ACTION_EH_EVENTOD:
108 vh_event_handler_od_free (data);
111 case ACTION_EH_EVENTMD:
113 vh_event_handler_md_free (data);
117 while (e != ACTION_CLEANUP_END);
121 valhalla_mrproper (valhalla_t *handle)
124 fifo_queue_t *fifo_o;
126 fifo_queue_t *fifo_i[] = {
127 vh_scanner_fifo_get (handle->scanner),
128 vh_dbmanager_fifo_get (handle->dbmanager),
129 vh_dispatcher_fifo_get (handle->dispatcher),
130 vh_parser_fifo_get (handle->parser),
132 vh_grabber_fifo_get (handle->grabber),
133 vh_downloader_fifo_get (handle->downloader),
134 #endif /* USE_GRABBER */
135 vh_event_handler_fifo_get (handle->event_handler),
138 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
143 fifo_o = vh_fifo_queue_new ();
148 vh_dbmanager_db_begin_transaction (handle->dbmanager);
150 /* remove all previous contexts */
151 vh_dbmanager_db_dlcontext_delete (handle->dbmanager);
152 #endif /* USE_GRABBER */
155 * The same data pointer can exist in several queues at the same time.
156 * The goal is to identify all unique entries from all queues and to save
157 * these entries in the fifo_o queue.
158 * Then, all data pointers can be safety freed (prevents double free).
160 for (i = 0; i < ARRAY_NB_ELEMENTS (fifo_i); i++)
168 vh_fifo_queue_push (fifo_i[i],
169 FIFO_QUEUE_PRIORITY_NORMAL, ACTION_CLEANUP_END, NULL);
173 e = ACTION_NO_OPERATION;
175 vh_fifo_queue_pop (fifo_i[i], &e, &data);
179 case ACTION_DB_INSERT_P:
180 case ACTION_DB_INSERT_G:
181 case ACTION_DB_UPDATE_P:
182 case ACTION_DB_UPDATE_G:
184 case ACTION_DB_NEWFILE:
186 file_data_t *file = data;
187 if (!file || file->clean_f)
191 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
194 /* save downloader context */
195 if (file->step < STEP_ENDING && file->list_downloader)
196 vh_dbmanager_db_dlcontext_save (handle->dbmanager, file);
197 #endif /* USE_GRABBER */
201 case ACTION_DB_EXT_INSERT:
202 case ACTION_DB_EXT_UPDATE:
203 case ACTION_DB_EXT_DELETE:
204 case ACTION_EH_EVENTOD:
205 case ACTION_EH_EVENTMD:
206 case ACTION_EH_EVENTGL:
207 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
214 while (e != ACTION_CLEANUP_END);
218 vh_dbmanager_db_end_transaction (handle->dbmanager);
219 #endif /* USE_GRABBER */
221 queue_cleanup (fifo_o);
222 vh_fifo_queue_free (fifo_o);
224 /* On-demand queue must be handled separately. */
225 fifo_o = vh_ondemand_fifo_get (handle->ondemand);
228 queue_cleanup (fifo_o);
232 valhalla_config_set_orig (valhalla_t *handle, valhalla_cfg_t conf, ...)
235 const void *p1 = NULL, *p2 = NULL;
238 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
243 if (conf >= (1 << VH_CFG_RANGE))
249 if (conf & VH_VOIDP_T)
250 p1 = va_arg (ap, void *);
252 i = va_arg (ap, int);
253 if (conf & VH_VOIDP_2_T)
254 p2 = va_arg (ap, void *);
256 if (va_arg (ap, int) != ~0) /* check for safeguard */
258 vh_log (VALHALLA_MSG_CRITICAL,
259 "unrecoverable error with valhalla_config_set(), conf = %#x, "
260 "it is probably a bad use of this function", conf);
273 case VALHALLA_CFG_DOWNLOADER_DEST:
274 vh_downloader_destination_set (handle->downloader, (valhalla_dl_t) i, p1);
277 case VALHALLA_CFG_GRABBER_PRIORITY:
278 vh_grabber_priority_set (handle->grabber,
279 p1, (valhalla_metadata_pl_t) i, p2);
282 case VALHALLA_CFG_GRABBER_STATE:
284 vh_grabber_state_set (handle->grabber, p1, i);
286 #endif /* USE_GRABBER */
288 case VALHALLA_CFG_PARSER_KEYWORD:
290 vh_parser_bl_keyword_add (handle->parser, p1);
293 case VALHALLA_CFG_SCANNER_PATH:
295 vh_scanner_path_add (handle->scanner, p1, i);
298 case VALHALLA_CFG_SCANNER_SUFFIX:
300 vh_scanner_suffix_add (handle->scanner, p1);
304 vh_log (VALHALLA_MSG_WARNING,
305 "%s: unsupported option %#x", __FUNCTION__, conf);
314 valhalla_wait (valhalla_t *handle)
316 const int f = STOP_FLAG_REQUEST | STOP_FLAG_WAIT;
318 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
320 if (!handle || handle->noscan)
323 vh_scanner_wait (handle->scanner);
325 vh_ondemand_stop (handle->ondemand, f);
326 vh_dbmanager_wait (handle->dbmanager);
327 vh_dispatcher_stop (handle->dispatcher, f);
328 vh_parser_stop (handle->parser, f);
330 vh_grabber_stop (handle->grabber, f);
331 vh_downloader_stop (handle->downloader, f);
332 #endif /* USE_GRABBER */
333 vh_event_handler_stop (handle->event_handler, f);
339 valhalla_force_stop (valhalla_t *handle)
343 vh_log (VALHALLA_MSG_WARNING,
344 "%s: This can take a time, please be patient", __FUNCTION__);
346 for (i = 0; i < 2; i++)
348 int f = !i ? STOP_FLAG_REQUEST : STOP_FLAG_WAIT;
350 vh_ondemand_stop (handle->ondemand, f);
352 vh_scanner_stop (handle->scanner, f);
353 vh_dbmanager_stop (handle->dbmanager, f);
354 vh_dispatcher_stop (handle->dispatcher, f);
355 vh_parser_stop (handle->parser, f);
357 vh_grabber_stop (handle->grabber, f);
358 vh_downloader_stop (handle->downloader, f);
359 #endif /* USE_GRABBER */
360 vh_event_handler_stop (handle->event_handler, f);
363 valhalla_mrproper (handle);
369 valhalla_uninit (valhalla_t *handle)
371 vh_log (VALHALLA_MSG_VERBOSE, "%s: begin", __FUNCTION__);
377 valhalla_force_stop (handle);
379 /* dump all statistics */
380 vh_stats_dump (handle->stats, NULL);
381 vh_stats_debug_dump (handle->stats);
383 vh_ondemand_uninit (handle->ondemand);
384 vh_scanner_uninit (handle->scanner);
385 vh_dbmanager_uninit (handle->dbmanager);
386 vh_dispatcher_uninit (handle->dispatcher);
387 vh_parser_uninit (handle->parser);
389 vh_grabber_uninit (handle->grabber);
390 vh_downloader_uninit (handle->downloader);
391 #endif /* USE_GRABBER */
392 vh_event_handler_uninit (handle->event_handler);
395 vh_url_global_uninit ();
396 #endif /* USE_GRABBER */
399 av_lockmgr_register (NULL);
400 #endif /* USE_LAVC */
402 vh_stats_free (handle->stats);
404 vh_log (VALHALLA_MSG_VERBOSE, "%s: end", __FUNCTION__);
410 valhalla_run (valhalla_t *handle, int loop, uint16_t timeout, int priority)
414 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
417 return VALHALLA_ERROR_HANDLER;
420 return VALHALLA_ERROR_DEAD;
424 if (handle->event_handler)
426 res = vh_event_handler_run (handle->event_handler, priority);
428 return VALHALLA_ERROR_THREAD;
431 res = vh_scanner_run (handle->scanner, loop, timeout, priority);
434 if (res == SCANNER_ERROR_PATH)
437 vh_log (VALHALLA_MSG_INFO , "no path defined, scanner disabled");
440 return VALHALLA_ERROR_THREAD;
443 res = vh_dbmanager_run (handle->dbmanager, priority);
445 return VALHALLA_ERROR_THREAD;
447 res = vh_dispatcher_run (handle->dispatcher, priority);
449 return VALHALLA_ERROR_THREAD;
451 res = vh_parser_run (handle->parser, priority);
453 return VALHALLA_ERROR_THREAD;
456 res = vh_grabber_run (handle->grabber, priority);
458 return VALHALLA_ERROR_THREAD;
460 res = vh_downloader_run (handle->downloader, priority);
462 return VALHALLA_ERROR_THREAD;
463 #endif /* USE_GRABBER */
465 res = vh_ondemand_run (handle->ondemand, priority);
467 return VALHALLA_ERROR_THREAD;
469 return VALHALLA_SUCCESS;
473 valhalla_metadata_group_str (valhalla_meta_grp_t group)
475 return vh_metadata_group_str (group);
479 valhalla_grabber_next (valhalla_t *handle, const char *id)
481 vh_log (VALHALLA_MSG_VERBOSE, "%s : %s", __FUNCTION__, id ? id : "");
487 return vh_grabber_next (handle->grabber, id);
489 vh_log (VALHALLA_MSG_WARNING,
490 "This function is usable only with grabbing support!");
492 #endif /* USE_GRABBER */
495 valhalla_metadata_pl_t
496 valhalla_grabber_priority_read (valhalla_t *handle,
497 const char *id, const char **meta)
499 vh_log (VALHALLA_MSG_VERBOSE,
500 "%s : %s/%s", __FUNCTION__, id ? id : "", meta && *meta ? *meta : "");
506 return vh_grabber_priority_read (handle->grabber, id, meta);
508 vh_log (VALHALLA_MSG_WARNING,
509 "This function is usable only with grabbing support!");
511 #endif /* USE_GRABBER */
515 valhalla_stats_group_next (valhalla_t *handle, const char *id)
517 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
522 return vh_stats_group_next (handle->stats, id);
526 valhalla_stats_read_next (valhalla_t *handle, const char *id,
527 valhalla_stats_type_t type, const char **item)
529 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
534 return vh_stats_read_next (handle->stats, id, type, item);
538 valhalla_verbosity (valhalla_verb_t level)
545 valhalla_avlock (void **mutex, enum AVLockOp op)
550 *mutex = malloc (sizeof (pthread_mutex_t));
553 return !!pthread_mutex_init (*mutex, NULL);
556 return !!pthread_mutex_lock (*mutex);
558 case AV_LOCK_RELEASE:
559 return !!pthread_mutex_unlock (*mutex);
561 case AV_LOCK_DESTROY:
562 pthread_mutex_destroy (*mutex);
570 #endif /* USE_LAVC */
573 valhalla_init (const char *db, valhalla_init_param_t *param)
575 static int preinit = 0;
577 valhalla_init_param_t p;
578 const valhalla_init_param_t *pp = &p;
580 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
588 memset (&p, 0, sizeof (p));
590 handle = calloc (1, sizeof (valhalla_t));
595 vh_url_global_init ();
596 #endif /* USE_GRABBER */
598 handle->stats = vh_stats_new ();
602 if (pp->od_cb || pp->gl_cb || pp->md_cb)
604 event_handler_cb_t cb;
606 cb.od_cb = pp->od_cb;
607 cb.gl_cb = pp->gl_cb;
608 cb.md_cb = pp->md_cb;
609 cb.od_data = pp->od_data;
610 cb.gl_data = pp->gl_data;
611 cb.md_data = pp->md_data;
613 handle->event_handler = vh_event_handler_init (handle, &cb);
614 if (!handle->event_handler)
618 handle->dispatcher = vh_dispatcher_init (handle);
619 if (!handle->dispatcher)
622 handle->parser = vh_parser_init (handle, pp->parser_nb, pp->decrapifier);
627 handle->grabber = vh_grabber_init (handle, pp->grabber_nb);
628 if (!handle->grabber)
631 handle->downloader = vh_downloader_init (handle);
632 if (!handle->downloader)
634 #endif /* USE_GRABBER */
636 handle->scanner = vh_scanner_init (handle);
637 if (!handle->scanner)
640 handle->dbmanager = vh_dbmanager_init (handle, db, pp->commit_int);
641 if (!handle->dbmanager)
644 handle->ondemand = vh_ondemand_init (handle);
645 if (!handle->ondemand)
651 if (av_lockmgr_register (valhalla_avlock))
653 #endif /* USE_LAVC */
654 av_log_set_level (AV_LOG_FATAL);
662 valhalla_uninit (handle);
667 valhalla_scanner_wakeup (valhalla_t *handle)
669 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
674 vh_scanner_wakeup (handle->scanner);
678 valhalla_ondemand (valhalla_t *handle, const char *file)
682 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
684 if (!handle || !file)
687 odfile = strdup (file);
691 vh_ondemand_action_send (handle->ondemand, FIFO_QUEUE_PRIORITY_HIGH,
692 ACTION_OD_ENGAGE, odfile);
695 /******************************************************************************/
697 /* Public Database Selections */
699 /******************************************************************************/
701 int valhalla_db_metalist_get (valhalla_t *handle,
702 valhalla_db_item_t *search,
703 valhalla_file_type_t filetype,
704 valhalla_db_restrict_t *restriction,
705 int (*result_cb) (void *data,
706 valhalla_db_metares_t *res),
709 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
711 if (!handle || !search || !result_cb)
714 return vh_dbmanager_db_metalist_get (handle->dbmanager, search,
715 filetype, restriction, result_cb, data);
718 int valhalla_db_filelist_get (valhalla_t *handle,
719 valhalla_file_type_t filetype,
720 valhalla_db_restrict_t *restriction,
721 int (*result_cb) (void *data,
722 valhalla_db_fileres_t *res),
725 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
727 if (!handle || !result_cb)
730 return vh_dbmanager_db_filelist_get (handle->dbmanager,
731 filetype, restriction, result_cb, data);
735 valhalla_db_file_get (valhalla_t *handle,
736 int64_t id, const char *path,
737 valhalla_db_restrict_t *restriction,
738 valhalla_db_filemeta_t **res)
740 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
746 vh_dbmanager_db_file_get (handle->dbmanager, id, path, restriction, res);
749 /******************************************************************************/
751 /* For Public Insertions/Updates/Deletions */
753 /******************************************************************************/
756 valhalla_db_metadata_insert (valhalla_t *handle, const char *path,
757 const char *meta, const char *data,
758 valhalla_meta_grp_t group)
760 dbmanager_extmd_t *extmd;
762 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
764 if (!handle || !path || !meta || !data)
767 extmd = calloc (1, sizeof (dbmanager_extmd_t));
771 extmd->path = strdup (path);
772 extmd->meta = strdup (meta);
773 extmd->data = strdup (data);
774 extmd->group = group;
776 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
777 ACTION_DB_EXT_INSERT, extmd);
782 valhalla_db_metadata_update (valhalla_t *handle, const char *path,
783 const char *meta, const char *data,
786 dbmanager_extmd_t *extmd;
788 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
790 if (!handle || !path || !meta || !data || !ndata)
793 extmd = calloc (1, sizeof (dbmanager_extmd_t));
797 extmd->path = strdup (path);
798 extmd->meta = strdup (meta);
799 extmd->data = strdup (data);
800 extmd->ndata = strdup (ndata);
802 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
803 ACTION_DB_EXT_UPDATE, extmd);
808 valhalla_db_metadata_delete (valhalla_t *handle, const char *path,
809 const char *meta, const char *data)
811 dbmanager_extmd_t *extmd;
813 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
815 if (!handle || !path || !meta || !data)
818 extmd = calloc (1, sizeof (dbmanager_extmd_t));
822 extmd->path = strdup (path);
823 extmd->meta = strdup (meta);
824 extmd->data = strdup (data);
826 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
827 ACTION_DB_EXT_DELETE, extmd);