*/
struct callback_query {
/** The function to be called. */
- callback_function *handler;
+ afs_callback *handler;
/** The number of bytes of the query */
size_t query_size;
};
*
* \sa send_option_arg_callback_request(), send_standard_callback_request().
*/
-int send_callback_request(callback_function *f, struct osl_object *query,
+int send_callback_request(afs_callback *f, struct osl_object *query,
callback_result_handler *result_handler,
void *private_result_data)
{
* \sa send_standard_callback_request(), send_callback_request().
*/
int send_option_arg_callback_request(struct osl_object *options,
- int argc, char * const * const argv, callback_function *f,
+ int argc, char * const * const argv, afs_callback *f,
callback_result_handler *result_handler,
void *private_result_data)
{
* send_option_arg_callback_request().
*/
int send_standard_callback_request(int argc, char * const * const argv,
- callback_function *f, callback_result_handler *result_handler,
+ afs_callback *f, callback_result_handler *result_handler,
void *private_result_data)
{
return send_option_arg_callback_request(NULL, argc, argv, f, result_handler,
enum play_mode mode;
int ret;
+ PARA_INFO_LOG("new playlist: %s\n", arg);
if (!arg) {
ret = change_current_mood(NULL); /* always successful */
mode = PLAY_MODE_MOOD;
ret = clear_score_table();
if (ret < 0) {
- para_printf(&pb, "%s\n", para_strerror(-ret));
- goto out;
+ para_printf(&pb, "could not clear score table: %s\n",
+ para_strerror(-ret));
+ return ret;
}
if (current_play_mode == PLAY_MODE_MOOD)
close_current_mood();
else
playlist_close();
ret = activate_mood_or_playlist(arg, &num_admissible);
- if (ret < 0) {
- para_printf(&pb, "%s\nswitching back to %s\n",
- para_strerror(-ret), current_mop?
- current_mop : "dummy");
- ret = activate_mood_or_playlist(current_mop, &num_admissible);
- if (ret < 0) {
- para_printf(&pb, "failed (%s), switching to dummy\n",
- para_strerror(-ret));
- activate_mood_or_playlist(NULL, &num_admissible);
- }
- } else
- para_printf(&pb, "activated %s (%d admissible files)\n",
- current_mop? current_mop : "dummy mood",
- num_admissible);
+ if (ret >= 0)
+ goto out;
+ para_printf(&pb, "could not activate %s: %s\n"
+ "switching back to %s\n",
+ arg, para_strerror(-ret), current_mop? current_mop : "dummy");
+ /* ignore subsequent errors (but log them) */
+ ret = activate_mood_or_playlist(current_mop, &num_admissible);
+ if (ret >= 0)
+ goto out;
+ para_printf(&pb, "could not activate %s: %s\nswitching to dummy\n",
+ current_mop, para_strerror(-ret));
+ activate_mood_or_playlist(NULL, &num_admissible);
out:
+ para_printf(&pb, "activated %s (%d admissible files)\n",
+ current_mop? current_mop : "dummy mood", num_admissible);
flush_and_free_pb(&pb);
- return 0;
+ return ret;
}
int com_select(struct command_context *cc)
exit(EXIT_FAILURE);
}
-static int create_tables_callback(int fd, const struct osl_object *query)
+static int com_init_callback(int fd, const struct osl_object *query)
{
uint32_t table_mask = *(uint32_t *)query->data;
int i, ret;
if (!t->create)
continue;
ret = t->create(database_dir);
- if (ret < 0)
+ if (ret < 0) {
+ para_printf(&pb, "cannot create table %s\n", t->name);
goto out;
+ }
para_printf(&pb, "successfully created %s table\n", t->name);
}
ret = open_afs_tables();
-out:
if (ret < 0)
- para_printf(&pb, "%s\n", para_strerror(-ret));
+ para_printf(&pb, "cannot open afs tables\n");
+out:
flush_and_free_pb(&pb);
- return 0;
+ return ret;
}
int com_init(struct command_context *cc)
return -E_BAD_TABLE_NAME;
}
}
- return send_callback_request(create_tables_callback, &query,
+ return send_callback_request(com_init_callback, &query,
afs_cb_result_handler, cc);
}
/** Check the mood table. */
CHECK_MOODS = 2,
/** Check the playlist table. */
- CHECK_PLAYLISTS = 4
+ CHECK_PLAYLISTS = 4,
+ /** Check the attribute table against the audio file table. */
+ CHECK_ATTS = 8
};
int com_check(struct command_context *cc)
flags |= CHECK_AFT;
continue;
}
+ if (!strcmp(arg, "-A")) {
+ flags |= CHECK_ATTS;
+ continue;
+ }
if (!strcmp(arg, "-p")) {
flags |= CHECK_PLAYLISTS;
continue;
if (ret < 0)
return ret;
}
+ if (flags & CHECK_ATTS) {
+ ret = send_callback_request(attribute_check_callback, NULL,
+ afs_cb_result_handler, cc);
+ if (ret < 0)
+ return ret;
+ }
if (flags & CHECK_PLAYLISTS) {
ret = send_callback_request(playlist_check_callback,
NULL, afs_cb_result_handler, cc);
* \param pb May be \p NULL.
* \param data Type depends on \a event.
*
- * This function calls the table handlers of all tables and passes \a pb and \a
- * data verbatim. It's up to the handlers to interpret the \a data pointer.
+ * This function calls each table event handler, passing \a pb and \a data
+ * verbatim. It's up to the handlers to interpret the \a data pointer. If a
+ * handler returns negative, the loop is aborted.
+ *
+ * \return The (negative) error code of the first handler that failed, or non-negative
+ * if all handlers succeeded.
*/
-void afs_event(enum afs_events event, struct para_buffer *pb,
+__must_check int afs_event(enum afs_events event, struct para_buffer *pb,
void *data)
{
int i, ret;
if (!t->event_handler)
continue;
ret = t->event_handler(event, pb, data);
- if (ret < 0)
+ if (ret < 0) {
PARA_CRIT_LOG("table %s, event %d: %s\n", t->name,
event, para_strerror(-ret));
+ return ret;
+ }
}
+ return 1;
}
/**