1 /* Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
3 /** \file afs.c Paraslash's audio file selector. */
5 #include <netinet/in.h>
6 #include <sys/socket.h>
12 #include <arpa/inet.h>
17 #include "server.lsg.h"
18 #include "server_cmd.lsg.h"
37 * The array of tables of the audio file selector.
39 * We organize them in an array to be able to loop over all tables.
41 static const struct afs_table
{
42 /** The name is no table operation, so define it here. */
43 const char * const name
;
44 /** The only way to invoke the ops is via this pointer. */
45 const struct afs_table_operations
*ops
;
47 {.name
= "audio_files", .ops
= &aft_ops
},
48 {.name
= "attributes", .ops
= &attr_ops
},
49 {.name
= "scores", .ops
= &score_ops
},
50 {.name
= "moods", .ops
= &moods_ops
},
51 {.name
= "lyrics", .ops
= &lyrics_ops
},
52 {.name
= "images", .ops
= &images_ops
},
53 {.name
= "playlists", .ops
= &playlists_ops
},
55 /** Used to loop over the afs tables. */
56 #define NUM_AFS_TABLES ARRAY_SIZE(afs_tables)
59 /** The file descriptor for the local socket. */
61 /** The associated task structure. */
66 extern struct misc_meta_data
*mmd
;
68 static int server_socket
;
69 static struct command_task command_task_struct
;
70 static struct signal_task
*signal_task
;
72 static enum play_mode current_play_mode
;
73 static char *current_mop
; /* mode or playlist specifier. NULL means dummy mood */
75 extern uint32_t afs_socket_cookie
;
78 * Passed from command handlers to afs.
80 * Command handlers cannot change the afs database directly because they run in
81 * a separate process. The callback query structure circumvents this
82 * restriction as follows. To instruct the afs process to execute a particular
83 * function, the command hander writes an instance of this structure to a
84 * shared memory area, along with the arguments to the callback function. The
85 * identifier of the shared memory area is transferred to the afs process via
88 * The afs process reads the shared memory id from the command socket, attaches
89 * the corresponding area, and calls the callback function whose address is
92 * The command output, if any, is transferred back to the command handler in
93 * the same way: The afs process writes the output to a second shared memory
94 * area together with a fixed size metadata header whose format corresponds to
95 * the \ref callback_result structure. The identifier of this area is sent back
96 * to the command handler which attaches the area and forwards the output to
99 * \sa \ref struct callback_result.
101 struct callback_query
{
102 /** The function to be called. */
104 /** The number of bytes of the query */
109 * Structure embedded in the result of a callback.
111 * If the callback produced a result, an instance of that structure is embedded
112 * into the shared memory area holding the result, mainly to let the command
113 * handler know the size of the result.
115 * \sa \ref struct callback_query.
117 struct callback_result
{
118 /** The number of bytes of the result. */
120 /** The band designator (loglevel for the result). */
124 static int dispatch_result(int result_shmid
, callback_result_handler
*handler
,
125 void *private_result_data
)
127 struct osl_object result
;
129 /* must attach r/w as result.data might get encrypted in-place. */
130 int ret2
, ret
= shm_attach(result_shmid
, ATTACH_RW
, &result_shm
);
131 struct callback_result
*cr
= result_shm
;
134 PARA_ERROR_LOG("attach failed: %s\n", para_strerror(-ret
));
137 result
.size
= cr
->result_size
;
138 result
.data
= result_shm
+ sizeof(*cr
);
140 ret
= handler(&result
, cr
->band
, private_result_data
);
141 ret2
= shm_detach(result_shm
);
143 PARA_ERROR_LOG("detach failed: %s\n", para_strerror(-ret2
));
151 * Ask the afs process to call a given function.
153 * \param f The function to be called.
154 * \param query Pointer to arbitrary data for the callback.
155 * \param result_handler Called for each shm area sent by the callback.
156 * \param private_result_data Passed verbatim to \a result_handler.
158 * This function creates a socket for communication with the afs process and a
159 * shared memory area (sma) to which the buffer pointed to by \a query is
160 * copied. It then notifies the afs process that the callback function \a f
161 * should be executed by sending the shared memory identifier (shmid) to the
164 * If the callback produces a result, it sends any number of shared memory
165 * identifiers back via the socket. For each such identifier received, \a
166 * result_handler is called. The contents of the sma identified by the received
167 * shmid are passed to that function as an osl object. The private_result_data
168 * pointer is passed as the second argument to \a result_handler.
170 * \return Number of shared memory areas dispatched on success, negative on
173 int send_callback_request(afs_callback
*f
, struct osl_object
*query
,
174 callback_result_handler
*result_handler
,
175 void *private_result_data
)
177 struct callback_query
*cq
;
178 int ret
, fd
= -1, query_shmid
, result_shmid
;
180 char buf
[sizeof(afs_socket_cookie
) + sizeof(int)];
181 size_t query_shm_size
= sizeof(*cq
);
182 int dispatch_error
= 0, num_dispatched
= 0;
185 query_shm_size
+= query
->size
;
186 ret
= shm_new(query_shm_size
);
190 ret
= shm_attach(query_shmid
, ATTACH_RW
, &query_shm
);
195 cq
->query_size
= query_shm_size
- sizeof(*cq
);
198 memcpy(query_shm
+ sizeof(*cq
), query
->data
, query
->size
);
199 ret
= shm_detach(query_shm
);
203 *(uint32_t *)buf
= afs_socket_cookie
;
204 *(int *)(buf
+ sizeof(afs_socket_cookie
)) = query_shmid
;
206 ret
= connect_local_socket(OPT_STRING_VAL(AFS_SOCKET
));
210 ret
= write_all(fd
, buf
, sizeof(buf
));
214 * Read all shmids from afs.
216 * Even if the dispatcher returns an error we _must_ continue to read
217 * shmids from fd so that we can destroy all shared memory areas that
218 * have been created for us by the afs process.
221 ret
= recv_bin_buffer(fd
, buf
, sizeof(int));
224 assert(ret
== sizeof(int));
228 ret
= dispatch_result(result_shmid
, result_handler
,
229 private_result_data
);
230 if (ret
< 0 && dispatch_error
>= 0)
231 dispatch_error
= ret
;
232 ret
= shm_destroy(result_shmid
);
234 PARA_CRIT_LOG("destroy result failed: %s\n",
235 para_strerror(-ret
));
239 if (shm_destroy(query_shmid
) < 0)
240 PARA_CRIT_LOG("shm destroy error\n");
243 if (dispatch_error
< 0)
244 return dispatch_error
;
247 return num_dispatched
;
251 * Wrapper for send_callback_request() which passes a lopsub parse result.
253 * \param f The callback function.
254 * \param cmd Needed for (de-)serialization.
255 * \param lpr Must match cmd.
256 * \param private_result_data Passed to send_callback_request().
258 * This function serializes the parse result given by the lpr pointer into a
259 * buffer. The buffer is sent as the query to the afs process with the callback
262 * \return The return value of the underlying call to send_callback_request().
264 int send_lls_callback_request(afs_callback
*f
,
265 const struct lls_command
* const cmd
,
266 struct lls_parse_result
*lpr
, void *private_result_data
)
268 struct osl_object query
;
270 int ret
= lls_serialize_parse_result(lpr
, cmd
, &buf
, &query
.size
);
274 ret
= send_callback_request(f
, &query
, afs_cb_result_handler
,
275 private_result_data
);
280 static int action_if_pattern_matches(struct osl_row
*row
, void *data
)
282 struct pattern_match_data
*pmd
= data
;
283 struct osl_object name_obj
;
284 const char *p
, *name
;
287 ret
= osl(osl_get_object(pmd
->table
, row
, pmd
->match_col_num
,
291 name
= (char *)name_obj
.data
;
292 if ((!name
|| !*name
) && (pmd
->pm_flags
& PM_SKIP_EMPTY_NAME
))
294 if (lls_num_inputs(pmd
->lpr
) == 0) {
295 if (pmd
->pm_flags
& PM_NO_PATTERN_MATCHES_EVERYTHING
) {
297 return pmd
->action(pmd
->table
, row
, name
, pmd
->data
);
302 if (i
>= lls_num_inputs(pmd
->lpr
))
304 p
= lls_input(i
, pmd
->lpr
);
305 ret
= fnmatch(p
, name
, pmd
->fnmatch_flags
);
306 if (ret
!= FNM_NOMATCH
) {
309 ret
= pmd
->action(pmd
->table
, row
, name
, pmd
->data
);
321 * Execute the given function for each matching row.
323 * \param pmd Describes what to match and how.
327 int for_each_matching_row(struct pattern_match_data
*pmd
)
329 if (pmd
->pm_flags
& PM_REVERSE_LOOP
)
330 return osl(osl_rbtree_loop_reverse(pmd
->table
, pmd
->loop_col_num
, pmd
,
331 action_if_pattern_matches
));
332 return osl(osl_rbtree_loop(pmd
->table
, pmd
->loop_col_num
, pmd
,
333 action_if_pattern_matches
));
337 * Compare two osl objects of string type.
339 * \param obj1 Pointer to the first object.
340 * \param obj2 Pointer to the second object.
342 * In any case, only \p MIN(obj1->size, obj2->size) characters of each string
343 * are taken into account.
345 * \return It returns an integer less than, equal to, or greater than zero if
346 * \a obj1 is found, respectively, to be less than, to match, or be greater than
349 * \sa strcmp(3), strncmp(3).
351 int string_compare(const struct osl_object
*obj1
, const struct osl_object
*obj2
)
353 const char *str1
= obj1
->data
;
354 const char *str2
= obj2
->data
;
355 return strncmp(str1
, str2
, PARA_MIN(obj1
->size
, obj2
->size
));
358 static int pass_afd(int fd
, char *buf
, size_t size
)
360 struct msghdr msg
= {.msg_iov
= NULL
};
361 struct cmsghdr
*cmsg
;
362 char control
[255] __a_aligned(8);
372 msg
.msg_control
= control
;
373 msg
.msg_controllen
= sizeof(control
);
375 cmsg
= CMSG_FIRSTHDR(&msg
);
376 cmsg
->cmsg_level
= SOL_SOCKET
;
377 cmsg
->cmsg_type
= SCM_RIGHTS
;
378 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int));
379 *(int *)CMSG_DATA(cmsg
) = fd
;
381 /* Sum of the length of all control messages in the buffer */
382 msg
.msg_controllen
= cmsg
->cmsg_len
;
383 PARA_DEBUG_LOG("passing %zu bytes and fd %d\n", size
, fd
);
384 ret
= sendmsg(server_socket
, &msg
, 0);
386 ret
= -ERRNO_TO_PARA_ERROR(errno
);
393 * Pass the fd of the next audio file to the server process.
395 * This stores all information for streaming the "best" audio file in a shared
396 * memory area. The id of that area and an open file descriptor for the next
397 * audio file are passed to the server process.
401 * \sa \ref open_and_update_audio_file().
403 static int open_next_audio_file(void)
408 ret
= open_and_update_audio_file(&fd
);
410 if (ret
!= -OSL_ERRNO_TO_PARA_ERROR(E_OSL_RB_KEY_NOT_FOUND
))
411 PARA_ERROR_LOG("%s\n", para_strerror(-ret
));
412 goto no_admissible_files
;
415 if (!write_ok(server_socket
)) {
419 *(uint32_t *)buf
= NEXT_AUDIO_FILE
;
420 *(uint32_t *)(buf
+ 4) = (uint32_t)shmid
;
421 ret
= pass_afd(fd
, buf
, 8);
429 *(uint32_t *)buf
= NO_ADMISSIBLE_FILES
;
430 *(uint32_t *)(buf
+ 4) = (uint32_t)0;
431 return write_all(server_socket
, buf
, 8);
434 static int activate_mood_or_playlist(const char *arg
, struct para_buffer
*pb
)
441 ret
= mood_load(NULL
, &msg
);
442 mode
= PLAY_MODE_MOOD
;
443 } else if (!strncmp(arg
, "p/", 2)) {
444 ret
= playlist_load(arg
+ 2, &msg
);
445 mode
= PLAY_MODE_PLAYLIST
;
446 } else if (!strncmp(arg
, "m/", 2)) {
447 ret
= mood_load(arg
+ 2, &msg
);
448 mode
= PLAY_MODE_MOOD
;
450 ret
= -ERRNO_TO_PARA_ERROR(EINVAL
);
451 msg
= make_message("%s: parse error", arg
);
454 para_printf(pb
, "%s", msg
);
458 current_play_mode
= mode
;
460 * We get called with arg == current_mop from the signal dispatcher
461 * after SIGHUP and from the error path of the select command to
462 * re-select the current mood or playlist. In this case the assignment
463 * to current_mop below would result in a use-after-free condition.
465 if (arg
!= current_mop
) {
467 current_mop
= arg
? para_strdup(arg
) : NULL
;
469 /* Notify the server about the mood/playlist change. */
470 mutex_lock(mmd_mutex
);
471 strncpy(mmd
->afs_mode_string
, arg
? arg
: "dummy",
472 sizeof(mmd
->afs_mode_string
));
473 mmd
->afs_mode_string
[sizeof(mmd
->afs_mode_string
) - 1] = '\0';
475 mutex_unlock(mmd_mutex
);
480 * Result handler for sending data to the para_client process.
482 * \param result The data to be sent.
483 * \param band The band designator.
484 * \param private Pointer to the command context.
486 * \return The return value of the underlying call to \ref command.c::send_sb.
488 * \sa \ref callback_result_handler, \ref command.c::send_sb.
490 int afs_cb_result_handler(struct osl_object
*result
, uint8_t band
,
493 struct command_context
*cc
= private;
501 case SBD_WARNING_LOG
:
505 assert(result
->size
> 0);
506 return send_sb(&cc
->scc
, result
->data
, result
->size
, band
, true);
507 case SBD_AFS_CB_FAILURE
:
508 return *(int *)(result
->data
);
514 static void flush_and_free_pb(struct para_buffer
*pb
)
517 struct afs_max_size_handler_data
*amshd
= pb
->private_data
;
519 if (pb
->buf
&& pb
->size
> 0) {
520 ret
= pass_buffer_as_shm(amshd
->fd
, amshd
->band
, pb
->buf
,
523 PARA_ERROR_LOG("%s\n", para_strerror(-ret
));
528 static void init_admissible_files(const char *arg
)
530 int ret
= activate_mood_or_playlist(arg
, NULL
);
532 PARA_WARNING_LOG("could not activate %s: %s\n", arg
,
533 para_strerror(-ret
));
535 activate_mood_or_playlist(NULL
, NULL
);
539 static int setup_command_socket_or_die(void)
542 const char *socket_name
= OPT_STRING_VAL(AFS_SOCKET
);
545 ret
= create_local_socket(socket_name
);
547 PARA_EMERG_LOG("%s: %s\n", para_strerror(-ret
), socket_name
);
551 PARA_INFO_LOG("listening on socket %s (fd %d)\n", socket_name
,
556 static char *database_dir
;
558 static void close_afs_tables(void)
561 PARA_NOTICE_LOG("closing afs tables\n");
562 for (i
= 0; i
< NUM_AFS_TABLES
; i
++)
563 afs_tables
[i
].ops
->close();
568 static void get_database_dir(void)
571 if (OPT_GIVEN(AFS_DATABASE_DIR
))
572 database_dir
= para_strdup(OPT_STRING_VAL(AFS_DATABASE_DIR
));
574 char *home
= para_homedir();
575 database_dir
= make_message(
576 "%s/.paraslash/afs_database-0.7", home
);
580 PARA_INFO_LOG("afs_database dir %s\n", database_dir
);
583 static int make_database_dir(void)
588 ret
= para_mkdir(database_dir
, 0777);
589 if (ret
>= 0 || ret
== -ERRNO_TO_PARA_ERROR(EEXIST
))
594 static int open_afs_tables(void)
599 PARA_NOTICE_LOG("opening %zu osl tables in %s\n", NUM_AFS_TABLES
,
601 for (i
= 0; i
< NUM_AFS_TABLES
; i
++) {
602 ret
= afs_tables
[i
].ops
->open(database_dir
);
605 PARA_ERROR_LOG("could not open %s\n", afs_tables
[i
].name
);
611 afs_tables
[--i
].ops
->close();
615 static int afs_signal_post_monitor(struct sched
*s
, __a_unused
void *context
)
619 if (getppid() == 1) {
620 PARA_EMERG_LOG("para_server died\n");
623 signum
= para_next_signal();
626 if (signum
== SIGHUP
) {
628 parse_config_or_die(1);
629 ret
= open_afs_tables();
632 init_admissible_files(current_mop
);
635 PARA_EMERG_LOG("terminating on signal %d\n", signum
);
637 task_notify_all(s
, E_AFS_SIGNAL
);
638 return -E_AFS_SIGNAL
;
641 static void register_signal_task(struct sched
*s
)
643 para_sigaction(SIGPIPE
, SIG_IGN
);
644 signal_task
= signal_init_or_die();
645 para_install_sighandler(SIGINT
);
646 para_install_sighandler(SIGTERM
);
647 para_install_sighandler(SIGHUP
);
649 signal_task
->task
= task_register(&(struct task_info
) {
651 .pre_monitor
= signal_pre_monitor
,
652 .post_monitor
= afs_signal_post_monitor
,
653 .context
= signal_task
,
658 static struct list_head afs_client_list
;
660 /** Describes one connected afs client. */
662 /** Position in the afs client list. */
663 struct list_head node
;
664 /** The socket file descriptor for this client. */
666 /** The time the client connected. */
667 struct timeval connect_time
;
670 static void command_pre_monitor(struct sched
*s
, void *context
)
672 struct command_task
*ct
= context
;
673 struct afs_client
*client
;
675 sched_monitor_readfd(server_socket
, s
);
676 sched_monitor_readfd(ct
->fd
, s
);
677 list_for_each_entry(client
, &afs_client_list
, node
)
678 sched_monitor_readfd(client
->fd
, s
);
682 * Send data as shared memory to a file descriptor.
684 * \param fd File descriptor to send the shmid to.
685 * \param band The band designator for this data.
686 * \param buf The buffer holding the data to be sent.
687 * \param size The size of \a buf.
689 * This function creates a shared memory area large enough to hold
690 * the content given by \a buf and \a size and sends the identifier
691 * of this area to the file descriptor \a fd.
693 * It is called by the AFS max_size handler as well as directly by the AFS
694 * command callbacks to send command output to the command handlers.
696 * \return Zero if \a buf is \p NULL or \a size is zero. Negative on errors,
697 * and positive on success.
699 int pass_buffer_as_shm(int fd
, uint8_t band
, const char *buf
, size_t size
)
703 struct callback_result
*cr
;
706 assert(band
!= SBD_OUTPUT
);
707 ret
= shm_new(size
+ sizeof(*cr
));
711 ret
= shm_attach(shmid
, ATTACH_RW
, &shm
);
715 cr
->result_size
= size
;
718 memcpy(shm
+ sizeof(*cr
), buf
, size
);
719 ret
= shm_detach(shm
);
722 ret
= write_all(fd
, (char *)&shmid
, sizeof(int));
726 if (shm_destroy(shmid
) < 0)
727 PARA_ERROR_LOG("destroy result failed\n");
732 * Format and send an error message to the command handler.
734 * To pass an error message from the callback of an afs command to the client,
735 * this function should be called. It formats the message into a buffer which
736 * is passed as a shared memory area to the command handler from where it
737 * propagates to the client.
739 * The message will be tagged with the ERROR_LOG sideband designator so that
740 * the client writes it to its stderr stream rather than to stdout as with
741 * aca->pbout. In analogy to the default Unix semantics of stderr, the message
742 * is sent without buffering.
744 * If sending the error message fails, an error is logged on the server side,
745 * but no other action is taken.
747 * \param aca Used to obtain the fd to send the shmid to.
748 * \param fmt Usual format string.
750 __printf_2_3
void afs_error(const struct afs_callback_arg
*aca
,
759 n
= xvasprintf(&msg
, fmt
, argp
);
761 ret
= pass_buffer_as_shm(aca
->fd
, SBD_ERROR_LOG
, msg
, n
+ 1);
763 PARA_ERROR_LOG("Could not send %s: %s\n", msg
,
764 para_strerror(-ret
));
768 static int call_callback(int fd
, int query_shmid
)
771 struct callback_query
*cq
;
773 struct afs_callback_arg aca
= {.fd
= fd
};
775 ret
= shm_attach(query_shmid
, ATTACH_RW
, &query_shm
);
779 aca
.query
.data
= (char *)query_shm
+ sizeof(*cq
);
780 aca
.query
.size
= cq
->query_size
;
781 aca
.pbout
.max_size
= shm_get_shmmax();
782 aca
.pbout
.max_size_handler
= afs_max_size_handler
;
783 aca
.pbout
.private_data
= &(struct afs_max_size_handler_data
) {
788 ret2
= shm_detach(query_shm
);
790 if (ret
< 0) /* ignore (but log) detach error */
791 PARA_ERROR_LOG("could not detach sma: %s\n",
792 para_strerror(-ret2
));
796 flush_and_free_pb(&aca
.pbout
);
798 ret2
= pass_buffer_as_shm(fd
, SBD_AFS_CB_FAILURE
,
799 (const char *)&ret
, sizeof(ret
));
801 PARA_ERROR_LOG("could not pass cb failure packet: %s\n",
802 para_strerror(-ret
));
807 static int execute_server_command(void)
811 int ret
= read_nonblock(server_socket
, buf
, sizeof(buf
) - 1, &n
);
813 if (ret
< 0 || n
== 0)
816 if (strcmp(buf
, "new"))
817 return -ERRNO_TO_PARA_ERROR(EINVAL
);
818 return open_next_audio_file();
821 /* returns 0 if no data available, 1 else */
822 static int execute_afs_command(int fd
)
826 char buf
[sizeof(cookie
) + sizeof(query_shmid
)];
828 int ret
= read_nonblock(fd
, buf
, sizeof(buf
), &n
);
834 if (n
!= sizeof(buf
)) {
835 PARA_NOTICE_LOG("short read (%d bytes, expected %lu)\n",
836 ret
, (long unsigned) sizeof(buf
));
839 cookie
= *(uint32_t *)buf
;
840 if (cookie
!= afs_socket_cookie
) {
841 PARA_NOTICE_LOG("received invalid cookie (got %u, expected %u)\n",
842 (unsigned)cookie
, (unsigned)afs_socket_cookie
);
845 query_shmid
= *(int *)(buf
+ sizeof(cookie
));
846 if (query_shmid
< 0) {
847 PARA_WARNING_LOG("received invalid query shmid %d)\n",
851 ret
= call_callback(fd
, query_shmid
);
855 PARA_NOTICE_LOG("%s\n", para_strerror(-ret
));
859 /** Shutdown connection if query has not arrived until this many seconds. */
860 #define AFS_CLIENT_TIMEOUT 3
862 static int command_post_monitor(struct sched
*s
, void *context
)
864 struct command_task
*ct
= context
;
865 struct sockaddr_un unix_addr
;
866 struct afs_client
*client
, *tmp
;
869 ret
= task_get_notification(ct
->task
);
872 ret
= execute_server_command();
874 PARA_EMERG_LOG("%s\n", para_strerror(-ret
));
875 task_notify_all(s
, -ret
);
878 /* Check the list of connected clients. */
879 list_for_each_entry_safe(client
, tmp
, &afs_client_list
, node
) {
880 ret
= execute_afs_command(client
->fd
);
881 if (ret
== 0) { /* prevent bogus connection flooding */
883 tv_diff(now
, &client
->connect_time
, &diff
);
884 if (diff
.tv_sec
< AFS_CLIENT_TIMEOUT
)
886 PARA_WARNING_LOG("connection timeout\n");
889 list_del(&client
->node
);
892 /* Accept connections on the local socket. */
893 ret
= para_accept(ct
->fd
, &unix_addr
, sizeof(unix_addr
), &fd
);
895 PARA_NOTICE_LOG("%s\n", para_strerror(-ret
));
898 ret
= mark_fd_nonblocking(fd
);
900 PARA_NOTICE_LOG("%s\n", para_strerror(-ret
));
904 client
= alloc(sizeof(*client
));
906 client
->connect_time
= *now
;
907 para_list_add(&client
->node
, &afs_client_list
);
911 static void register_command_task(struct sched
*s
)
913 struct command_task
*ct
= &command_task_struct
;
914 ct
->fd
= setup_command_socket_or_die();
916 ct
->task
= task_register(&(struct task_info
) {
917 .name
= "afs command",
918 .pre_monitor
= command_pre_monitor
,
919 .post_monitor
= command_post_monitor
,
924 static int afs_poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
)
926 mutex_lock(mmd_mutex
);
927 daemon_set_loglevel(mmd
->loglevel
);
928 mutex_unlock(mmd_mutex
);
929 return xpoll(fds
, nfds
, timeout
);
933 * Initialize the audio file selector process.
935 * \param socket_fd File descriptor used for communication with the server.
937 __noreturn
void afs_init(int socket_fd
)
939 static struct sched s
;
942 register_signal_task(&s
);
943 init_list_head(&afs_client_list
);
944 ret
= open_afs_tables();
947 server_socket
= socket_fd
;
948 ret
= mark_fd_nonblocking(server_socket
);
951 PARA_INFO_LOG("server_socket: %d\n", server_socket
);
952 init_admissible_files(OPT_STRING_VAL(AFS_INITIAL_MODE
));
953 register_command_task(&s
);
954 s
.default_timeout
= 1000;
955 s
.poll_function
= afs_poll
;
956 ret
= write(socket_fd
, "\0", 1);
960 ret
= -ERRNO_TO_PARA_ERROR(errno
);
969 signal_shutdown(signal_task
);
974 PARA_EMERG_LOG("%s\n", para_strerror(-ret
));
978 static int com_select_callback(struct afs_callback_arg
*aca
)
980 const struct lls_command
*cmd
= SERVER_CMD_CMD_PTR(SELECT
);
984 ret
= lls_deserialize_parse_result(aca
->query
.data
, cmd
, &aca
->lpr
);
986 arg
= lls_input(0, aca
->lpr
);
988 if (current_play_mode
== PLAY_MODE_MOOD
)
992 ret
= activate_mood_or_playlist(arg
, &aca
->pbout
);
995 /* ignore subsequent errors (but log them) */
996 if (current_mop
&& strcmp(current_mop
, arg
) != 0) {
998 afs_error(aca
, "switching back to %s\n", current_mop
);
999 ret2
= activate_mood_or_playlist(current_mop
, &aca
->pbout
);
1002 afs_error(aca
, "could not reactivate %s: %s\n", current_mop
,
1003 para_strerror(-ret2
));
1005 activate_mood_or_playlist(NULL
, &aca
->pbout
);
1007 lls_free_parse_result(aca
->lpr
, cmd
);
1011 static int com_select(struct command_context
*cc
, struct lls_parse_result
*lpr
)
1013 const struct lls_command
*cmd
= SERVER_CMD_CMD_PTR(SELECT
);
1015 int ret
= lls(lls_check_arg_count(lpr
, 1, 1, &errctx
));
1018 send_errctx(cc
, errctx
);
1021 return send_lls_callback_request(com_select_callback
, cmd
, lpr
, cc
);
1023 EXPORT_SERVER_CMD_HANDLER(select
);
1025 static int com_init_callback(struct afs_callback_arg
*aca
)
1027 uint32_t table_mask
= *(uint32_t *)aca
->query
.data
;
1032 for (i
= 0; i
< NUM_AFS_TABLES
; i
++) {
1033 const struct afs_table
*t
= afs_tables
+ i
;
1035 if (!(table_mask
& (1 << i
)))
1037 if (!t
->ops
->create
)
1039 ret
= t
->ops
->create(database_dir
);
1041 afs_error(aca
, "cannot create table %s\n", t
->name
);
1044 para_printf(&aca
->pbout
, "successfully created %s table\n",
1047 ret
= open_afs_tables();
1049 afs_error(aca
, "cannot open afs tables: %s\n",
1050 para_strerror(-ret
));
1055 static int com_init(struct command_context
*cc
, struct lls_parse_result
*lpr
)
1058 uint32_t table_mask
= (1 << (NUM_AFS_TABLES
+ 1)) - 1;
1059 struct osl_object query
= {.data
= &table_mask
,
1060 .size
= sizeof(table_mask
)};
1061 unsigned num_inputs
= lls_num_inputs(lpr
);
1063 ret
= make_database_dir();
1066 if (num_inputs
> 0) {
1068 for (i
= 0; i
< num_inputs
; i
++) {
1069 for (j
= 0; j
< NUM_AFS_TABLES
; j
++) {
1070 const struct afs_table
*t
= afs_tables
+ j
;
1072 if (strcmp(lls_input(i
, lpr
), t
->name
))
1074 table_mask
|= (1 << j
);
1077 if (j
== NUM_AFS_TABLES
)
1078 return -E_BAD_TABLE_NAME
;
1081 return send_callback_request(com_init_callback
, &query
,
1082 afs_cb_result_handler
, cc
);
1084 EXPORT_SERVER_CMD_HANDLER(init
);
1086 static int com_check(struct command_context
*cc
, struct lls_parse_result
*lpr
)
1088 const struct lls_opt_result
*r_a
= SERVER_CMD_OPT_RESULT(CHECK
, AFT
, lpr
);
1089 const struct lls_opt_result
*r_A
= SERVER_CMD_OPT_RESULT(CHECK
, ATTRIBUTE
, lpr
);
1090 const struct lls_opt_result
*r_m
= SERVER_CMD_OPT_RESULT(CHECK
, MOOD
, lpr
);
1091 const struct lls_opt_result
*r_p
= SERVER_CMD_OPT_RESULT(CHECK
, PLAYLIST
, lpr
);
1092 bool noopt
= !lls_opt_given(r_a
) && !lls_opt_given(r_A
)
1093 && !lls_opt_given(r_m
) && !lls_opt_given(r_p
);
1096 if (noopt
|| lls_opt_given(r_a
)) {
1097 ret
= send_callback_request(aft_check_callback
, NULL
,
1098 afs_cb_result_handler
, cc
);
1102 if (noopt
|| lls_opt_given(r_A
)) {
1103 ret
= send_callback_request(attribute_check_callback
, NULL
,
1104 afs_cb_result_handler
, cc
);
1108 if (noopt
|| lls_opt_given(r_p
)) {
1109 ret
= send_callback_request(playlist_check_callback
,
1110 NULL
, afs_cb_result_handler
, cc
);
1114 if (noopt
|| lls_opt_given(r_m
)) {
1115 ret
= send_callback_request(mood_check_callback
, NULL
,
1116 afs_cb_result_handler
, cc
);
1122 EXPORT_SERVER_CMD_HANDLER(check
);
1125 * The afs event dispatcher.
1127 * \param event Type of the event.
1128 * \param pb May be \p NULL.
1129 * \param data Type depends on \a event.
1131 * This function calls each table event handler, passing \a pb and \a data
1132 * verbatim. It's up to the handlers to interpret the \a data pointer. If a
1133 * handler returns negative, the loop is aborted.
1135 * \return The (negative) error code of the first handler that failed, or non-negative
1136 * if all handlers succeeded.
1138 __must_check
int afs_event(enum afs_events event
, struct para_buffer
*pb
,
1143 for (i
= 0; i
< NUM_AFS_TABLES
; i
++) {
1144 const struct afs_table
*t
= afs_tables
+ i
;
1145 if (!t
->ops
->event_handler
)
1147 ret
= t
->ops
->event_handler(event
, pb
, data
);
1149 PARA_CRIT_LOG("table %s, event %u: %s\n", t
->name
,
1150 event
, para_strerror(-ret
));
1158 * Dummy event handler for the images table.
1160 * \param event Unused.
1162 * \param data Unused.
1164 * \return The images table does not honor events, so this handler always
1167 __a_const
int images_event_handler(__a_unused
enum afs_events event
,
1168 __a_unused
struct para_buffer
*pb
, __a_unused
void *data
)
1174 * Dummy event handler for the lyrics table.
1176 * \param event Unused.
1178 * \param data Unused.
1180 * \return The lyrics table does not honor events, so this handler always
1183 __a_const
int lyrics_event_handler(__a_unused
enum afs_events event
,
1184 __a_unused
struct para_buffer
*pb
, __a_unused
void *data
)