*/
static struct osl_table *audio_file_table; /* NULL if table not open */
static struct osl_row *current_aft_row; /* NULL if no audio file open */
+static unsigned char current_hash[HASH_SIZE]; /* only used on sighup */
static char *status_items;
static char *parser_friendly_status_items;
/** The different sorting methods of the ls command. */
enum ls_sorting_method {
- /** -sp (default) */
- LS_SORT_BY_PATH,
- /** -ss */
- LS_SORT_BY_SCORE,
- /** -sl */
- LS_SORT_BY_LAST_PLAYED,
- /** -sn */
- LS_SORT_BY_NUM_PLAYED,
- /** -sf */
- LS_SORT_BY_FREQUENCY,
- /** -sc */
- LS_SORT_BY_CHANNELS,
- /** -si */
- LS_SORT_BY_IMAGE_ID,
- /** -sy */
- LS_SORT_BY_LYRICS_ID,
- /** -sb */
- LS_SORT_BY_BITRATE,
- /** -sd */
- LS_SORT_BY_DURATION,
- /** -sa */
- LS_SORT_BY_AUDIO_FORMAT,
- /** -sh */
- LS_SORT_BY_HASH,
+ LS_SORT_BY_PATH, /**< -s=p (default) */
+ LS_SORT_BY_SCORE, /**< -s=s */
+ LS_SORT_BY_LAST_PLAYED, /**< -s=l */
+ LS_SORT_BY_NUM_PLAYED, /**< -s=n */
+ LS_SORT_BY_FREQUENCY, /**< -s=f */
+ LS_SORT_BY_CHANNELS, /**< -s=c */
+ LS_SORT_BY_IMAGE_ID, /**< -s=i */
+ LS_SORT_BY_LYRICS_ID, /**< -s=y */
+ LS_SORT_BY_BITRATE, /**< -s=b */
+ LS_SORT_BY_DURATION, /**< -s=d */
+ LS_SORT_BY_AUDIO_FORMAT, /**< -s=a */
+ LS_SORT_BY_HASH, /**< -s=h */
};
/** The different listing modes of the ls command. */
enum ls_listing_mode {
- /** Default listing mode. */
- LS_MODE_SHORT,
- /** -l or -ll */
- LS_MODE_LONG,
- /** -lv */
- LS_MODE_VERBOSE,
- /** -lm */
- LS_MODE_MBOX,
- /** -lc */
- LS_MODE_CHUNKS,
- /** -lp */
- LS_MODE_PARSER,
+ LS_MODE_SHORT, /**< Default listing mode. */
+ LS_MODE_LONG, /**< -l or -l=l */
+ LS_MODE_VERBOSE, /** -l=v */
+ LS_MODE_MBOX, /** -l=m */
+ LS_MODE_CHUNKS, /** -l=c */
+ LS_MODE_PARSER, /** -l=p */
};
/**
{
uint32_t n;
- if (!afhi->chunk_table)
+ if (!afhi->chunk_table || afhi->chunks_total == 0)
return;
for (n = 0; n <= afhi->chunks_total; n++)
write_u32(buf + 4 * n, afhi->chunk_table[n]);
WRITE_STATUS_ITEM(pb, SI_file_size, "%ld\n", statbuf.st_size / 1024);
}
+/**
+ * Deallocate and invalidate the status item strings.
+ *
+ * This needs to be a public function so that afs.c can call it on shutdown.
+ */
void free_status_items(void)
{
freep(&status_items);
freep(&parser_friendly_status_items);
}
-static int make_status_items(void)
+static void make_status_items(void)
{
const struct lls_command *cmd = SERVER_CMD_CMD_PTR(LS);
char *argv[] = {"ls", "--admissible", "--listing-mode=verbose"};
free_status_items();
if (!status_item_ls_data.path) /* no audio file open */
- return 0;
+ return;
ret = lls_parse(ARRAY_SIZE(argv), argv, cmd, &opts.lpr, NULL);
assert(ret >= 0);
time(¤t_time);
parser_friendly_status_items = pb.buf;
ret = 1;
out:
- if (ret < 0)
+ if (ret < 0) {
+ PARA_WARNING_LOG("could not create status items: %s\n",
+ para_strerror(-ret));
free_status_items();
+ }
lls_free_parse_result(opts.lpr, cmd);
- return ret;
}
/**
return audio_file_loop(&acad, check_atts_of_audio_file);
}
-/**
- * Close the audio file table.
- *
- * \param flags Usual flags that are passed to osl_close_table().
- *
- * \sa \ref osl_close_table().
+/*
+ * This sets audio_file_table to NULL, but leaves current_aft_row unmodified,
+ * though stale (pointing to unmapped memory). If the table is being closed
+ * because we received SIGHUP, the table will be reopened after the config file
+ * has been reloaded. We remember the hash of the current audio file here so
+ * that aft_open() can initialize current_aft_row by looking up the saved hash.
*/
static void aft_close(void)
{
+ int ret;
+ unsigned char *p;
+
+ if (current_aft_row) {
+ ret = get_hash_of_row(current_aft_row, &p);
+ if (ret < 0) {
+ PARA_WARNING_LOG("hash lookup failure\n");
+ current_aft_row = NULL;
+ } else
+ memcpy(current_hash, p, HASH_SIZE);
+ }
osl_close_table(audio_file_table, OSL_MARK_CLEAN);
audio_file_table = NULL;
}
-/**
- * Open the audio file table.
- *
- * \param dir The database directory.
- *
- * \return Standard.
- *
- * \sa \ref osl_open_table().
- */
static int aft_open(const char *dir)
{
int ret;
unsigned num;
osl_get_num_rows(audio_file_table, &num);
PARA_INFO_LOG("audio file table contains %u files\n", num);
- return ret;
+ if (!current_aft_row) {
+ PARA_DEBUG_LOG("no current aft row\n");
+ return 1;
+ }
+ /* SIGHUP case, update current_aft_row */
+ ret = aft_get_row_of_hash(current_hash, ¤t_aft_row);
+ if (ret < 0) { /* not fatal */
+ PARA_WARNING_LOG("current hash lookup failure: %s\n",
+ para_strerror(-ret));
+ current_aft_row = NULL;
+ return 1;
+ }
+ PARA_NOTICE_LOG("current audio file hash lookup: success\n");
+ return 1;
}
PARA_NOTICE_LOG("failed to open audio file table\n");
audio_file_table = NULL;
status_item_ls_data.afsi.last_played = old_last_played;
make_status_items();
return 1;
+ } case AUDIO_FILE_RENAME: {
+ char *path;
+ if (data != current_aft_row)
+ return 0;
+ ret = get_audio_file_path_of_row(current_aft_row, &path);
+ if (ret < 0)
+ return ret;
+ status_item_ls_data.path = path;
+ make_status_items();
+ return 1;
} case AFHI_CHANGE: {
if (data != current_aft_row)
return 0;
return ret;
make_status_items();
return 1;
+ } case AUDIO_FILE_REMOVE: {
+ if (data == current_aft_row)
+ current_aft_row = NULL;
+ return 0;
}
case BLOB_RENAME:
case BLOB_REMOVE: