|
|
|
@ -86,6 +86,10 @@ struct media_player_cache_packet { |
|
|
|
struct media_player_media_file { |
|
|
|
struct obj obj; // must be first |
|
|
|
str blob; |
|
|
|
union { |
|
|
|
str_list *str_link; |
|
|
|
}; |
|
|
|
time_t ts; |
|
|
|
}; |
|
|
|
|
|
|
|
static mutex_t media_player_cache_lock = MUTEX_STATIC_INIT; |
|
|
|
@ -95,6 +99,9 @@ TYPED_GHASHTABLE(media_player_media_files_ht, str, struct media_player_media_fil |
|
|
|
NULL, __obj_put); |
|
|
|
static mutex_t media_player_media_files_lock = MUTEX_STATIC_INIT; |
|
|
|
static media_player_media_files_ht media_player_media_files; |
|
|
|
static rwlock_t media_player_media_files_names_lock = RWLOCK_STATIC_INIT; |
|
|
|
static str_q media_player_media_files_names = TYPED_GQUEUE_INIT; |
|
|
|
// lock order: media_player_media_files_names_lock first, media_player_media_files_lock second |
|
|
|
|
|
|
|
static bool media_player_read_packet(struct media_player *mp); |
|
|
|
static mp_cached_code __media_player_add_blob_id(struct media_player *mp, |
|
|
|
@ -1194,6 +1201,7 @@ static struct media_player_media_file *media_player_media_file_new(str blob) { |
|
|
|
media_player_media_file_free); |
|
|
|
fo->blob = blob; |
|
|
|
fo->blob.dup = call_ref; // string is allocated by reference on `fo` |
|
|
|
fo->ts = time(NULL); |
|
|
|
return fo; |
|
|
|
} |
|
|
|
|
|
|
|
@ -1227,12 +1235,14 @@ static struct media_player_media_file *media_player_media_files_get(const str *f |
|
|
|
return fo; |
|
|
|
} |
|
|
|
|
|
|
|
// lock must be held, reference will be taken over |
|
|
|
// locks must be held, reference will be taken over |
|
|
|
static void media_player_media_files_insert(const str *fn, struct media_player_media_file *fo) { |
|
|
|
if (!t_hash_table_is_set(media_player_media_files)) |
|
|
|
media_player_media_files = media_player_media_files_ht_new(); |
|
|
|
str *dup = str_dup(fn); |
|
|
|
t_hash_table_insert(media_player_media_files, dup, fo); |
|
|
|
t_queue_push_tail(&media_player_media_files_names, dup); |
|
|
|
fo->str_link = media_player_media_files_names.tail; |
|
|
|
} |
|
|
|
|
|
|
|
static mp_cached_code media_player_set_media_file(struct media_player *mp, |
|
|
|
@ -1878,6 +1888,7 @@ void media_player_free(void) { |
|
|
|
|
|
|
|
if (t_hash_table_is_set(media_player_media_files)) |
|
|
|
t_hash_table_destroy(media_player_media_files); |
|
|
|
t_queue_clear_full(&media_player_media_files_names, str_free); |
|
|
|
#endif |
|
|
|
timerthread_free(&send_timer_thread); |
|
|
|
} |
|
|
|
@ -1920,3 +1931,60 @@ bool media_player_preload_files(char **files) { |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
bool media_player_reload_file(str *name) { |
|
|
|
bool ret = false; |
|
|
|
|
|
|
|
#ifdef WITH_TRANSCODING |
|
|
|
__auto_type fo = media_player_media_files_get(name); |
|
|
|
assert(fo != NULL); |
|
|
|
|
|
|
|
// get file mtime |
|
|
|
char file_s[PATH_MAX]; |
|
|
|
snprintf(file_s, sizeof(file_s), STR_FORMAT, STR_FMT(name)); |
|
|
|
|
|
|
|
struct stat sb; |
|
|
|
int fail = stat(file_s, &sb); |
|
|
|
if (fail) |
|
|
|
ilog(LOG_WARN, "Failed to stat() media file '" STR_FORMAT "': %s", |
|
|
|
STR_FMT(name), strerror(errno)); |
|
|
|
else if (sb.st_mtim.tv_sec > fo->ts) { |
|
|
|
__auto_type fonew = media_player_media_file_read_c(file_s); |
|
|
|
if (fonew) { |
|
|
|
// got a new entry. swap it out against the old one |
|
|
|
LOCK(&media_player_media_files_lock); |
|
|
|
if (t_hash_table_is_set(media_player_media_files) |
|
|
|
&& t_hash_table_lookup(media_player_media_files, name) == fo) |
|
|
|
{ |
|
|
|
t_hash_table_insert(media_player_media_files, name, fonew); // releases `fo` reference |
|
|
|
ilog(LOG_DEBUG, "Reloaded cached media file '" STR_FORMAT "'", |
|
|
|
STR_FMT(name)); |
|
|
|
ret = true; |
|
|
|
} |
|
|
|
else // somebody beat us to it |
|
|
|
obj_put(fonew); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
obj_put(fo); |
|
|
|
#endif |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
unsigned int media_player_reload_files(void) { |
|
|
|
unsigned int ret = 0; |
|
|
|
|
|
|
|
#ifdef WITH_TRANSCODING |
|
|
|
RWLOCK_R(&media_player_media_files_names_lock); |
|
|
|
|
|
|
|
for (__auto_type l = media_player_media_files_names.head; l; l = l->next) { |
|
|
|
str *name = l->data; |
|
|
|
if (media_player_reload_file(name)) |
|
|
|
ret++; |
|
|
|
} |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |