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:
100 case ACTION_DB_EXT_PRIORITY:
102 vh_dbmanager_extmd_free (data);
105 case ACTION_OD_ENGAGE:
106 case ACTION_EH_EVENTGL:
111 case ACTION_EH_EVENTOD:
113 vh_event_handler_od_free (data);
116 case ACTION_EH_EVENTMD:
118 vh_event_handler_md_free (data);
122 while (e != ACTION_CLEANUP_END);
126 valhalla_mrproper (valhalla_t *handle)
129 fifo_queue_t *fifo_o;
131 fifo_queue_t *fifo_i[] = {
132 vh_scanner_fifo_get (handle->scanner),
133 vh_dbmanager_fifo_get (handle->dbmanager),
134 vh_dispatcher_fifo_get (handle->dispatcher),
135 vh_parser_fifo_get (handle->parser),
137 vh_grabber_fifo_get (handle->grabber),
138 vh_downloader_fifo_get (handle->downloader),
139 #endif /* USE_GRABBER */
140 vh_event_handler_fifo_get (handle->event_handler),
143 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
148 fifo_o = vh_fifo_queue_new ();
153 vh_dbmanager_db_begin_transaction (handle->dbmanager);
155 /* remove all previous contexts */
156 vh_dbmanager_db_dlcontext_delete (handle->dbmanager);
157 #endif /* USE_GRABBER */
160 * The same data pointer can exist in several queues at the same time.
161 * The goal is to identify all unique entries from all queues and to save
162 * these entries in the fifo_o queue.
163 * Then, all data pointers can be safety freed (prevents double free).
165 for (i = 0; i < ARRAY_NB_ELEMENTS (fifo_i); i++)
173 vh_fifo_queue_push (fifo_i[i],
174 FIFO_QUEUE_PRIORITY_NORMAL, ACTION_CLEANUP_END, NULL);
178 e = ACTION_NO_OPERATION;
180 vh_fifo_queue_pop (fifo_i[i], &e, &data);
184 case ACTION_DB_INSERT_P:
185 case ACTION_DB_INSERT_G:
186 case ACTION_DB_UPDATE_P:
187 case ACTION_DB_UPDATE_G:
189 case ACTION_DB_NEWFILE:
191 file_data_t *file = data;
192 if (!file || file->clean_f)
196 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
199 /* save downloader context */
200 if (file->step < STEP_ENDING && file->list_downloader)
201 vh_dbmanager_db_dlcontext_save (handle->dbmanager, file);
202 #endif /* USE_GRABBER */
206 case ACTION_DB_EXT_INSERT:
207 case ACTION_DB_EXT_UPDATE:
208 case ACTION_DB_EXT_DELETE:
209 case ACTION_EH_EVENTOD:
210 case ACTION_EH_EVENTMD:
211 case ACTION_EH_EVENTGL:
212 vh_fifo_queue_push (fifo_o, FIFO_QUEUE_PRIORITY_NORMAL, e, data);
219 while (e != ACTION_CLEANUP_END);
223 vh_dbmanager_db_end_transaction (handle->dbmanager);
224 #endif /* USE_GRABBER */
226 queue_cleanup (fifo_o);
227 vh_fifo_queue_free (fifo_o);
229 /* On-demand queue must be handled separately. */
230 fifo_o = vh_ondemand_fifo_get (handle->ondemand);
233 queue_cleanup (fifo_o);
237 valhalla_config_set_orig (valhalla_t *handle, valhalla_cfg_t conf, ...)
240 const void *p1 = NULL, *p2 = NULL;
243 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
248 if (conf >= (1 << VH_CFG_RANGE))
254 if (conf & VH_VOIDP_T)
255 p1 = va_arg (ap, void *);
257 i = va_arg (ap, int);
258 if (conf & VH_VOIDP_2_T)
259 p2 = va_arg (ap, void *);
261 if (va_arg (ap, int) != ~0) /* check for safeguard */
263 vh_log (VALHALLA_MSG_CRITICAL,
264 "unrecoverable error with valhalla_config_set(), conf = %#x, "
265 "it is probably a bad use of this function", conf);
278 case VALHALLA_CFG_DOWNLOADER_DEST:
279 vh_downloader_destination_set (handle->downloader, (valhalla_dl_t) i, p1);
282 case VALHALLA_CFG_GRABBER_PRIORITY:
283 vh_grabber_priority_set (handle->grabber,
284 p1, (valhalla_metadata_pl_t) i, p2);
287 case VALHALLA_CFG_GRABBER_STATE:
289 vh_grabber_state_set (handle->grabber, p1, i);
291 #endif /* USE_GRABBER */
293 case VALHALLA_CFG_PARSER_KEYWORD:
295 vh_parser_bl_keyword_add (handle->parser, p1);
298 case VALHALLA_CFG_SCANNER_PATH:
300 vh_scanner_path_add (handle->scanner, p1, i);
303 case VALHALLA_CFG_SCANNER_SUFFIX:
305 vh_scanner_suffix_add (handle->scanner, p1);
309 vh_log (VALHALLA_MSG_WARNING,
310 "%s: unsupported option %#x", __FUNCTION__, conf);
319 valhalla_wait (valhalla_t *handle)
321 const int f = STOP_FLAG_REQUEST | STOP_FLAG_WAIT;
323 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
325 if (!handle || handle->noscan)
328 vh_scanner_wait (handle->scanner);
330 vh_ondemand_stop (handle->ondemand, f);
331 vh_dbmanager_wait (handle->dbmanager);
332 vh_dispatcher_stop (handle->dispatcher, f);
333 vh_parser_stop (handle->parser, f);
335 vh_grabber_stop (handle->grabber, f);
336 vh_downloader_stop (handle->downloader, f);
337 #endif /* USE_GRABBER */
338 vh_event_handler_stop (handle->event_handler, f);
344 valhalla_force_stop (valhalla_t *handle)
348 vh_log (VALHALLA_MSG_WARNING,
349 "%s: This can take a time, please be patient", __FUNCTION__);
351 for (i = 0; i < 2; i++)
353 int f = !i ? STOP_FLAG_REQUEST : STOP_FLAG_WAIT;
355 vh_ondemand_stop (handle->ondemand, f);
357 vh_scanner_stop (handle->scanner, f);
358 vh_dbmanager_stop (handle->dbmanager, f);
359 vh_dispatcher_stop (handle->dispatcher, f);
360 vh_parser_stop (handle->parser, f);
362 vh_grabber_stop (handle->grabber, f);
363 vh_downloader_stop (handle->downloader, f);
364 #endif /* USE_GRABBER */
365 vh_event_handler_stop (handle->event_handler, f);
368 /* abort all cURL transfers as fast as possible */
369 if (f == STOP_FLAG_REQUEST)
370 vh_url_ctl_abort (handle->url_ctl);
371 #endif /* USE_GRABBER */
374 valhalla_mrproper (handle);
380 valhalla_uninit (valhalla_t *handle)
384 vh_log (VALHALLA_MSG_VERBOSE, "%s: begin", __FUNCTION__);
389 pthread_mutex_lock (&g_preinit_mutex);
390 preinit = --g_preinit;
391 pthread_mutex_unlock (&g_preinit_mutex);
394 valhalla_force_stop (handle);
396 /* dump all statistics */
397 vh_stats_dump (handle->stats, NULL);
398 vh_stats_debug_dump (handle->stats);
400 vh_ondemand_uninit (handle->ondemand);
401 vh_scanner_uninit (handle->scanner);
402 vh_dbmanager_uninit (handle->dbmanager);
403 vh_dispatcher_uninit (handle->dispatcher);
404 vh_parser_uninit (handle->parser);
406 vh_grabber_uninit (handle->grabber);
407 vh_downloader_uninit (handle->downloader);
408 #endif /* USE_GRABBER */
409 vh_event_handler_uninit (handle->event_handler);
412 vh_url_global_uninit ();
413 vh_url_ctl_free (handle->url_ctl);
414 #endif /* USE_GRABBER */
418 av_lockmgr_register (NULL);
419 #endif /* USE_LAVC */
421 vh_stats_free (handle->stats);
423 vh_log (VALHALLA_MSG_VERBOSE, "%s: end", __FUNCTION__);
429 valhalla_run (valhalla_t *handle,
430 int loop, uint16_t timeout, uint16_t delay, int priority)
434 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
437 return VALHALLA_ERROR_HANDLER;
440 return VALHALLA_ERROR_DEAD;
444 if (handle->event_handler)
446 res = vh_event_handler_run (handle->event_handler, priority);
448 return VALHALLA_ERROR_THREAD;
451 res = vh_scanner_run (handle->scanner, loop, timeout, delay, priority);
454 if (res == SCANNER_ERROR_PATH)
457 vh_log (VALHALLA_MSG_INFO , "no path defined, scanner disabled");
460 return VALHALLA_ERROR_THREAD;
463 res = vh_dbmanager_run (handle->dbmanager, priority);
465 return VALHALLA_ERROR_THREAD;
467 res = vh_dispatcher_run (handle->dispatcher, priority);
469 return VALHALLA_ERROR_THREAD;
471 res = vh_parser_run (handle->parser, priority);
473 return VALHALLA_ERROR_THREAD;
476 res = vh_grabber_run (handle->grabber, priority);
478 return VALHALLA_ERROR_THREAD;
480 res = vh_downloader_run (handle->downloader, priority);
482 return VALHALLA_ERROR_THREAD;
483 #endif /* USE_GRABBER */
485 res = vh_ondemand_run (handle->ondemand, priority);
487 return VALHALLA_ERROR_THREAD;
489 return VALHALLA_SUCCESS;
493 valhalla_metadata_group_str (valhalla_meta_grp_t group)
495 return vh_metadata_group_str (group);
499 valhalla_grabber_next (valhalla_t *handle, const char *id)
501 vh_log (VALHALLA_MSG_VERBOSE, "%s : %s", __FUNCTION__, id ? id : "");
507 return vh_grabber_next (handle->grabber, id);
509 vh_log (VALHALLA_MSG_WARNING,
510 "This function is usable only with grabbing support!");
512 #endif /* USE_GRABBER */
515 valhalla_metadata_pl_t
516 valhalla_grabber_priority_read (valhalla_t *handle,
517 const char *id, const char **meta)
519 vh_log (VALHALLA_MSG_VERBOSE,
520 "%s : %s/%s", __FUNCTION__, id ? id : "", meta && *meta ? *meta : "");
526 return vh_grabber_priority_read (handle->grabber, id, meta);
528 vh_log (VALHALLA_MSG_WARNING,
529 "This function is usable only with grabbing support!");
531 #endif /* USE_GRABBER */
535 valhalla_stats_group_next (valhalla_t *handle, const char *id)
537 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
542 return vh_stats_group_next (handle->stats, id);
546 valhalla_stats_read_next (valhalla_t *handle, const char *id,
547 valhalla_stats_type_t type, const char **item)
549 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
554 return vh_stats_read_next (handle->stats, id, type, item);
558 valhalla_verbosity (valhalla_verb_t level)
565 valhalla_avlock (void **mutex, enum AVLockOp op)
570 *mutex = malloc (sizeof (pthread_mutex_t));
573 return !!pthread_mutex_init (*mutex, NULL);
576 return !!pthread_mutex_lock (*mutex);
578 case AV_LOCK_RELEASE:
579 return !!pthread_mutex_unlock (*mutex);
581 case AV_LOCK_DESTROY:
582 pthread_mutex_destroy (*mutex);
590 #endif /* USE_LAVC */
593 valhalla_init (const char *db, valhalla_init_param_t *param)
597 valhalla_init_param_t p;
598 const valhalla_init_param_t *pp = &p;
600 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
602 pthread_mutex_lock (&g_preinit_mutex);
604 pthread_mutex_unlock (&g_preinit_mutex);
606 if (!preinit && vh_osdep_init ())
615 memset (&p, 0, sizeof (p));
617 handle = calloc (1, sizeof (valhalla_t));
622 handle->url_ctl = vh_url_ctl_new ();
623 if (!handle->url_ctl)
626 vh_url_global_init ();
627 #endif /* USE_GRABBER */
629 handle->stats = vh_stats_new ();
633 if (pp->od_cb || pp->gl_cb || pp->md_cb)
635 event_handler_cb_t cb;
637 cb.od_cb = pp->od_cb;
638 cb.gl_cb = pp->gl_cb;
639 cb.md_cb = pp->md_cb;
640 cb.od_data = pp->od_data;
641 cb.gl_data = pp->gl_data;
642 cb.md_data = pp->md_data;
644 handle->event_handler = vh_event_handler_init (handle, &cb);
645 if (!handle->event_handler)
649 handle->dispatcher = vh_dispatcher_init (handle);
650 if (!handle->dispatcher)
653 handle->parser = vh_parser_init (handle, pp->parser_nb, pp->decrapifier);
658 handle->grabber = vh_grabber_init (handle, pp->grabber_nb);
659 if (!handle->grabber)
662 handle->downloader = vh_downloader_init (handle);
663 if (!handle->downloader)
665 #endif /* USE_GRABBER */
667 handle->scanner = vh_scanner_init (handle);
668 if (!handle->scanner)
671 handle->dbmanager = vh_dbmanager_init (handle, db, pp->commit_int);
672 if (!handle->dbmanager)
675 handle->ondemand = vh_ondemand_init (handle);
676 if (!handle->ondemand)
682 if (av_lockmgr_register (valhalla_avlock))
684 #endif /* USE_LAVC */
685 av_log_set_level (AV_LOG_FATAL);
689 pthread_mutex_lock (&g_preinit_mutex);
691 pthread_mutex_unlock (&g_preinit_mutex);
696 valhalla_uninit (handle);
701 valhalla_scanner_wakeup (valhalla_t *handle)
703 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
708 vh_scanner_wakeup (handle->scanner);
712 valhalla_ondemand (valhalla_t *handle, const char *file)
716 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
718 if (!handle || !file)
721 odfile = strdup (file);
725 vh_ondemand_action_send (handle->ondemand, FIFO_QUEUE_PRIORITY_HIGH,
726 ACTION_OD_ENGAGE, odfile);
729 /******************************************************************************/
731 /* Public Database Selections */
733 /******************************************************************************/
736 valhalla_db_metalist_get (valhalla_t *handle, valhalla_db_item_t *search,
737 valhalla_file_type_t filetype,
738 valhalla_db_restrict_t *restriction)
740 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
742 if (!handle || !search)
745 return vh_dbmanager_db_metalist_get (handle->dbmanager,
746 search, filetype, restriction);
749 const valhalla_db_metares_t *
750 valhalla_db_metalist_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
752 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
754 if (!handle || !vhstmt)
757 return vh_dbmanager_db_metalist_read (handle->dbmanager, vhstmt);
761 valhalla_db_filelist_get (valhalla_t *handle, valhalla_file_type_t filetype,
762 valhalla_db_restrict_t *restriction)
764 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
770 vh_dbmanager_db_filelist_get (handle->dbmanager, filetype, restriction);
773 const valhalla_db_fileres_t *
774 valhalla_db_filelist_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
776 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
778 if (!handle || !vhstmt)
781 return vh_dbmanager_db_filelist_read (handle->dbmanager, vhstmt);
785 valhalla_db_file_get (valhalla_t *handle, int64_t id, const char *path,
786 valhalla_db_restrict_t *restriction)
788 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
793 return vh_dbmanager_db_file_get (handle->dbmanager, id, path, restriction);
796 const valhalla_db_metares_t *
797 valhalla_db_file_read (valhalla_t *handle, valhalla_db_stmt_t *vhstmt)
799 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
801 if (!handle || !vhstmt)
804 return vh_dbmanager_db_file_read (handle->dbmanager, vhstmt);
807 /******************************************************************************/
809 /* For Public Insertions/Updates/Deletions */
811 /******************************************************************************/
814 valhalla_db_metadata_insert (valhalla_t *handle, const char *path,
815 const char *meta, const char *data,
816 valhalla_lang_t lang, valhalla_meta_grp_t group)
818 dbmanager_extmd_t *extmd;
820 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
822 if (!handle || !path || !meta || !data)
825 extmd = calloc (1, sizeof (dbmanager_extmd_t));
829 extmd->path = strdup (path);
830 extmd->meta = strdup (meta);
831 extmd->data = strdup (data);
832 extmd->group = group;
835 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
836 ACTION_DB_EXT_INSERT, extmd);
841 valhalla_db_metadata_update (valhalla_t *handle, const char *path,
842 const char *meta, const char *data,
843 const char *ndata, valhalla_lang_t lang)
845 dbmanager_extmd_t *extmd;
847 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
849 if (!handle || !path || !meta || !data || !ndata)
852 extmd = calloc (1, sizeof (dbmanager_extmd_t));
856 extmd->path = strdup (path);
857 extmd->meta = strdup (meta);
858 extmd->data = strdup (data);
859 extmd->ndata = strdup (ndata);
862 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
863 ACTION_DB_EXT_UPDATE, extmd);
868 valhalla_db_metadata_delete (valhalla_t *handle, const char *path,
869 const char *meta, const char *data)
871 dbmanager_extmd_t *extmd;
873 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
875 if (!handle || !path || !meta || !data)
878 extmd = calloc (1, sizeof (dbmanager_extmd_t));
882 extmd->path = strdup (path);
883 extmd->meta = strdup (meta);
884 extmd->data = strdup (data);
886 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
887 ACTION_DB_EXT_DELETE, extmd);
892 valhalla_db_metadata_priority (valhalla_t *handle, const char *path,
893 const char *meta, const char *data,
894 valhalla_metadata_pl_t p)
896 dbmanager_extmd_t *extmd;
898 vh_log (VALHALLA_MSG_VERBOSE, __FUNCTION__);
900 if (!handle || !path)
906 extmd = calloc (1, sizeof (dbmanager_extmd_t));
910 extmd->path = strdup (path);
912 extmd->meta = strdup (meta);
914 extmd->data = strdup (data);
917 vh_dbmanager_action_send (handle->dbmanager, FIFO_QUEUE_PRIORITY_HIGH,
918 ACTION_DB_EXT_PRIORITY, extmd);