mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 05:43:01 +00:00 
			
		
		
		
	Feat: mympd_api handler for non mpd api requests
This commit is contained in:
		| @@ -42,6 +42,7 @@ set(SOURCES | |||||||
|     src/global.c |     src/global.c | ||||||
|     src/mpd_client.c |     src/mpd_client.c | ||||||
|     src/web_server.c |     src/web_server.c | ||||||
|  |     src/mympd_api.c | ||||||
|     src/list.c |     src/list.c | ||||||
|     src/tiny_queue.c |     src/tiny_queue.c | ||||||
|     dist/src/mongoose/mongoose.c |     dist/src/mongoose/mongoose.c | ||||||
|   | |||||||
| @@ -2232,7 +2232,7 @@ function parseSongDetails(obj) { | |||||||
| } | } | ||||||
|  |  | ||||||
| function execSyscmd(cmd) { | function execSyscmd(cmd) { | ||||||
|     sendAPI({"cmd": "MPD_API_SYSCMD", "data": {"cmd": cmd}}); |     sendAPI({"cmd": "MYMPD_API_SYSCMD", "data": {"cmd": cmd}}); | ||||||
| } | } | ||||||
|  |  | ||||||
| function playlistDetails(uri) { | function playlistDetails(uri) { | ||||||
|   | |||||||
							
								
								
									
										26
									
								
								src/global.c
									
									
									
									
									
								
							
							
						
						
									
										26
									
								
								src/global.c
									
									
									
									
									
								
							| @@ -25,6 +25,10 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | #include "tiny_queue.h" | ||||||
| #include "global.h" | #include "global.h" | ||||||
|  |  | ||||||
| int randrange(int n) { | int randrange(int n) { | ||||||
| @@ -41,6 +45,18 @@ void sanitize_string(const char *data) { | |||||||
|         *cp = '_'; |         *cp = '_'; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | bool validate_string(const char *data) { | ||||||
|  |     static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz" | ||||||
|  |                              "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | ||||||
|  |                              "1234567890_-. "; | ||||||
|  |     const char *cp = data; | ||||||
|  |     const char *end = data + strlen(data); | ||||||
|  |     for (cp += strspn(cp, ok_chars); cp != end; cp += strspn(cp, ok_chars)) | ||||||
|  |         return false; | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len) { | int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len) { | ||||||
|     if (dst_len == 0 || src_len == 0) |     if (dst_len == 0 || src_len == 0) | ||||||
|         return 0; |         return 0; | ||||||
| @@ -49,3 +65,13 @@ int copy_string(char * const dest, char const * const src, size_t const dst_len, | |||||||
|     dest[max] = '\0'; |     dest[max] = '\0'; | ||||||
|     return max; |     return max; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | enum mypd_cmd_ids get_cmd_id(const char *cmd) { | ||||||
|  |     const char * mympd_cmd_strs[] = { MYMPD_CMDS(GEN_STR) }; | ||||||
|  |  | ||||||
|  |     for (unsigned i = 0; i < sizeof(mympd_cmd_strs) / sizeof(mympd_cmd_strs[0]); i++) | ||||||
|  |         if (!strncmp(cmd, mympd_cmd_strs[i], strlen(mympd_cmd_strs[i]))) | ||||||
|  |             return i; | ||||||
|  |  | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -25,8 +25,6 @@ | |||||||
| #ifndef __GLOBAL_H__ | #ifndef __GLOBAL_H__ | ||||||
| #define __GLOBAL_H__ | #define __GLOBAL_H__ | ||||||
|  |  | ||||||
| #include <stdbool.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <signal.h> | #include <signal.h> | ||||||
|  |  | ||||||
| //architecture | //architecture | ||||||
| @@ -62,6 +60,91 @@ | |||||||
|     return len; \ |     return len; \ | ||||||
| } while (0) | } while (0) | ||||||
|  |  | ||||||
|  | //API cmds | ||||||
|  | #define MYMPD_CMDS(X) \ | ||||||
|  |     X(MPD_API_UNKNOWN) \ | ||||||
|  |     X(MPD_API_QUEUE_CLEAR) \ | ||||||
|  |     X(MPD_API_QUEUE_CROP) \ | ||||||
|  |     X(MPD_API_QUEUE_SAVE) \ | ||||||
|  |     X(MPD_API_QUEUE_LIST) \ | ||||||
|  |     X(MPD_API_QUEUE_SEARCH) \ | ||||||
|  |     X(MPD_API_QUEUE_RM_TRACK) \ | ||||||
|  |     X(MPD_API_QUEUE_RM_RANGE) \ | ||||||
|  |     X(MPD_API_QUEUE_MOVE_TRACK) \ | ||||||
|  |     X(MPD_API_QUEUE_ADD_TRACK_AFTER) \ | ||||||
|  |     X(MPD_API_QUEUE_ADD_TRACK) \ | ||||||
|  |     X(MPD_API_QUEUE_ADD_PLAY_TRACK) \ | ||||||
|  |     X(MPD_API_QUEUE_REPLACE_TRACK) \ | ||||||
|  |     X(MPD_API_QUEUE_ADD_PLAYLIST) \ | ||||||
|  |     X(MPD_API_QUEUE_REPLACE_PLAYLIST) \ | ||||||
|  |     X(MPD_API_QUEUE_SHUFFLE) \ | ||||||
|  |     X(MPD_API_QUEUE_LAST_PLAYED) \ | ||||||
|  |     X(MPD_API_PLAYLIST_CLEAR) \ | ||||||
|  |     X(MPD_API_PLAYLIST_RENAME) \ | ||||||
|  |     X(MPD_API_PLAYLIST_MOVE_TRACK) \ | ||||||
|  |     X(MPD_API_PLAYLIST_ADD_TRACK) \ | ||||||
|  |     X(MPD_API_PLAYLIST_RM_TRACK) \ | ||||||
|  |     X(MPD_API_PLAYLIST_RM) \ | ||||||
|  |     X(MPD_API_PLAYLIST_LIST) \ | ||||||
|  |     X(MPD_API_PLAYLIST_CONTENT_LIST) \ | ||||||
|  |     X(MPD_API_SMARTPLS_UPDATE_ALL) \ | ||||||
|  |     X(MPD_API_SMARTPLS_SAVE) \ | ||||||
|  |     X(MPD_API_SMARTPLS_GET) \ | ||||||
|  |     X(MPD_API_DATABASE_SEARCH_ADV) \ | ||||||
|  |     X(MPD_API_DATABASE_SEARCH) \ | ||||||
|  |     X(MPD_API_DATABASE_UPDATE) \ | ||||||
|  |     X(MPD_API_DATABASE_RESCAN) \ | ||||||
|  |     X(MPD_API_DATABASE_FILESYSTEM_LIST) \ | ||||||
|  |     X(MPD_API_DATABASE_TAG_LIST) \ | ||||||
|  |     X(MPD_API_DATABASE_TAG_ALBUM_LIST) \ | ||||||
|  |     X(MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST) \ | ||||||
|  |     X(MPD_API_DATABASE_STATS) \ | ||||||
|  |     X(MPD_API_DATABASE_SONGDETAILS) \ | ||||||
|  |     X(MPD_API_PLAYER_PLAY_TRACK) \ | ||||||
|  |     X(MPD_API_PLAYER_VOLUME_SET) \ | ||||||
|  |     X(MPD_API_PLAYER_VOLUME_GET) \ | ||||||
|  |     X(MPD_API_PLAYER_PAUSE) \ | ||||||
|  |     X(MPD_API_PLAYER_PLAY) \ | ||||||
|  |     X(MPD_API_PLAYER_STOP) \ | ||||||
|  |     X(MPD_API_PLAYER_SEEK) \ | ||||||
|  |     X(MPD_API_PLAYER_NEXT) \ | ||||||
|  |     X(MPD_API_PLAYER_PREV) \ | ||||||
|  |     X(MPD_API_PLAYER_OUTPUT_LIST) \ | ||||||
|  |     X(MPD_API_PLAYER_TOGGLE_OUTPUT) \ | ||||||
|  |     X(MPD_API_PLAYER_CURRENT_SONG) \ | ||||||
|  |     X(MPD_API_PLAYER_STATE) \ | ||||||
|  |     X(MPD_API_SETTINGS_GET) \ | ||||||
|  |     X(MPD_API_SETTINGS_SET) \ | ||||||
|  |     X(MPD_API_LIKE) \ | ||||||
|  |     X(MPD_API_COLS_SAVE) \ | ||||||
|  |     X(MYMPD_API_SYSCMD) | ||||||
|  |  | ||||||
|  | #define GEN_ENUM(X) X, | ||||||
|  | #define GEN_STR(X) #X, | ||||||
|  |  | ||||||
|  | enum mypd_cmd_ids { | ||||||
|  |     MYMPD_CMDS(GEN_ENUM) | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //message queue | ||||||
|  | tiny_queue_t *web_server_queue; | ||||||
|  | tiny_queue_t *mpd_client_queue; | ||||||
|  | tiny_queue_t *mympd_api_queue; | ||||||
|  |  | ||||||
|  | struct work_request_t { | ||||||
|  |     long conn_id;  // needed to identify the connection where to send the reply | ||||||
|  |     char data[1000]; | ||||||
|  |     int length; | ||||||
|  |     enum mypd_cmd_ids cmd_id; | ||||||
|  | } work_request_t; | ||||||
|  |  | ||||||
|  | struct work_result_t { | ||||||
|  |     long conn_id;  // needed to identify the connection where to send the reply | ||||||
|  |     char data[MAX_SIZE]; | ||||||
|  |     int length; | ||||||
|  | } work_result_t; | ||||||
|  |  | ||||||
|  |  | ||||||
| //signal handler | //signal handler | ||||||
| sig_atomic_t s_signal_received; | sig_atomic_t s_signal_received; | ||||||
|  |  | ||||||
| @@ -94,6 +177,7 @@ typedef struct { | |||||||
|     const char *streamurl; |     const char *streamurl; | ||||||
|     unsigned long last_played_count; |     unsigned long last_played_count; | ||||||
|     long loglevel; |     long loglevel; | ||||||
|  |     void *syscmd_list; | ||||||
| } t_config; | } t_config; | ||||||
|  |  | ||||||
| t_config config; | t_config config; | ||||||
| @@ -101,5 +185,7 @@ t_config config; | |||||||
| //global functions | //global functions | ||||||
| int randrange(int n); | int randrange(int n); | ||||||
| void sanitize_string(const char *data); | void sanitize_string(const char *data); | ||||||
|  | bool validate_string(const char *data); | ||||||
| int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len); | int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len); | ||||||
|  | enum mypd_cmd_ids get_cmd_id(const char *cmd); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /* myMPD | /* myMPD | ||||||
|    (c) 2018 Juergen Mang <mail@jcgames.de> |    (c) 2018-2019 Juergen Mang <mail@jcgames.de> | ||||||
|    This project's homepage is: https://github.com/jcorporation/mympd |    This project's homepage is: https://github.com/jcorporation/mympd | ||||||
|     |     | ||||||
|    This linked list implementation is based on: https://github.com/joshkunz/ashuffle |    This linked list implementation is based on: https://github.com/joshkunz/ashuffle | ||||||
| @@ -27,13 +27,11 @@ struct node { | |||||||
|     struct node *next; |     struct node *next; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| struct list { | struct list { | ||||||
|     unsigned length; |     unsigned length; | ||||||
|     struct node *list; |     struct node *list; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  |  | ||||||
| int list_init(struct list *l); | int list_init(struct list *l); | ||||||
| int list_push(struct list *l, const char *data, int value); | int list_push(struct list *l, const char *data, int value); | ||||||
| int list_insert(struct list *l, const char *data, int value); | int list_insert(struct list *l, const char *data, int value); | ||||||
|   | |||||||
							
								
								
									
										38
									
								
								src/main.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								src/main.c
									
									
									
									
									
								
							| @@ -33,11 +33,15 @@ | |||||||
| #include <pthread.h> | #include <pthread.h> | ||||||
| #include <dirent.h> | #include <dirent.h> | ||||||
| #include <mpd/client.h> | #include <mpd/client.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
| #include "../dist/src/inih/ini.h" | #include "list.h" | ||||||
|  | #include "tiny_queue.h" | ||||||
| #include "global.h" | #include "global.h" | ||||||
| #include "mpd_client.h" | #include "mpd_client.h" | ||||||
| #include "web_server.h" | #include "web_server.h" | ||||||
|  | #include "mympd_api.h" | ||||||
|  | #include "../dist/src/inih/ini.h" | ||||||
| #include "../dist/src/mongoose/mongoose.h" | #include "../dist/src/mongoose/mongoose.h" | ||||||
|  |  | ||||||
| static void signal_handler(int sig_num) { | static void signal_handler(int sig_num) { | ||||||
| @@ -137,28 +141,31 @@ static int inihandler(void* user, const char* section, const char* name, const c | |||||||
|     return 1; |     return 1; | ||||||
| } | } | ||||||
|  |  | ||||||
| void read_syscmds() { | void read_syscmds(void *arg_config) { | ||||||
|     DIR *dir; |     DIR *dir; | ||||||
|     struct dirent *ent; |     struct dirent *ent; | ||||||
|     char dirname[400]; |     char dirname[400]; | ||||||
|     char *cmd; |     char *cmd; | ||||||
|     long order; |     long order; | ||||||
|     if (config.syscmds == true) {     |     t_config *config = (t_config *) arg_config; | ||||||
|         snprintf(dirname, 400, "%s/syscmds", config.etcdir); |      | ||||||
|         LOG_INFO() printf("Reading syscmds: %s\n", dirname); |     if (config->syscmds == true) {     | ||||||
|  |         snprintf(dirname, 400, "%s/syscmds", config->etcdir); | ||||||
|  |         LOG_INFO2() printf("Reading syscmds: %s\n", dirname); | ||||||
|         if ((dir = opendir (dirname)) != NULL) { |         if ((dir = opendir (dirname)) != NULL) { | ||||||
|             while ((ent = readdir(dir)) != NULL) { |             while ((ent = readdir(dir)) != NULL) { | ||||||
|                 if (strncmp(ent->d_name, ".", 1) == 0) |                 if (strncmp(ent->d_name, ".", 1) == 0) | ||||||
|                     continue; |                     continue; | ||||||
|                 order = strtol(ent->d_name, &cmd, 10); |                 order = strtol(ent->d_name, &cmd, 10); | ||||||
|                 if (strcmp(cmd, "") != 0) |                 if (strcmp(cmd, "") != 0) | ||||||
|                     list_push(&syscmds, strdup(cmd), order); |                     list_push(config->syscmd_list, strdup(cmd), order); | ||||||
|             } |             } | ||||||
|             closedir(dir); |             closedir(dir); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else |     else { | ||||||
|         LOG_INFO() printf("Syscmds are disabled\n"); |         LOG_INFO2() printf("Syscmds are disabled\n"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void read_statefiles() { | void read_statefiles() { | ||||||
| @@ -310,6 +317,7 @@ int main(int argc, char **argv) { | |||||||
|     s_signal_received = 0; |     s_signal_received = 0; | ||||||
|     char testdirname[400]; |     char testdirname[400]; | ||||||
|     mpd_client_queue = tiny_queue_create(); |     mpd_client_queue = tiny_queue_create(); | ||||||
|  |     mympd_api_queue = tiny_queue_create(); | ||||||
|     web_server_queue = tiny_queue_create(); |     web_server_queue = tiny_queue_create(); | ||||||
|  |  | ||||||
|     srand((unsigned int)time(NULL)); |     srand((unsigned int)time(NULL)); | ||||||
| @@ -387,6 +395,7 @@ int main(int argc, char **argv) { | |||||||
|     if (!web_server_init(&mgr, &config)) { |     if (!web_server_init(&mgr, &config)) { | ||||||
|         return EXIT_FAILURE; |         return EXIT_FAILURE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     //drop privileges |     //drop privileges | ||||||
|     if (config.user != NULL) { |     if (config.user != NULL) { | ||||||
|         LOG_INFO() printf("Droping privileges to %s\n", config.user); |         LOG_INFO() printf("Droping privileges to %s\n", config.user); | ||||||
| @@ -446,9 +455,10 @@ int main(int argc, char **argv) { | |||||||
|     read_statefiles(); |     read_statefiles(); | ||||||
|  |  | ||||||
|     //read system command files |     //read system command files | ||||||
|     list_init(&syscmds);     |     config.syscmd_list = malloc(sizeof(struct list)); | ||||||
|     read_syscmds(); |     list_init(config.syscmd_list); | ||||||
|     list_sort_by_value(&syscmds, true); |     read_syscmds(&config); | ||||||
|  |     list_sort_by_value(config.syscmd_list, true); | ||||||
|  |  | ||||||
|     //init lists for tag handling |     //init lists for tag handling | ||||||
|     list_init(&mpd_tags); |     list_init(&mpd_tags); | ||||||
| @@ -459,11 +469,13 @@ int main(int argc, char **argv) { | |||||||
|     LOG_INFO() printf("Reading last played songs: %d\n", read_last_played()); |     LOG_INFO() printf("Reading last played songs: %d\n", read_last_played()); | ||||||
|      |      | ||||||
|     //Create working threads |     //Create working threads | ||||||
|     pthread_t mpd_client_thread, web_server_thread; |     pthread_t mpd_client_thread, web_server_thread, mympd_api_thread; | ||||||
|     //mpd connection |     //mpd connection | ||||||
|     pthread_create(&mpd_client_thread, NULL, mpd_client_loop, NULL); |     pthread_create(&mpd_client_thread, NULL, mpd_client_loop, NULL); | ||||||
|     //webserver |     //webserver | ||||||
|     pthread_create(&web_server_thread, NULL, web_server_loop, &mgr); |     pthread_create(&web_server_thread, NULL, web_server_loop, &mgr); | ||||||
|  |     //mympd api | ||||||
|  |     pthread_create(&mympd_api_thread, NULL, mympd_api_loop, &config); | ||||||
|  |  | ||||||
|     //Do nothing... |     //Do nothing... | ||||||
|  |  | ||||||
| @@ -473,7 +485,9 @@ int main(int argc, char **argv) { | |||||||
|     pthread_join(web_server_thread, NULL); |     pthread_join(web_server_thread, NULL); | ||||||
|     list_free(&mpd_tags); |     list_free(&mpd_tags); | ||||||
|     list_free(&mympd_tags); |     list_free(&mympd_tags); | ||||||
|  |     list_free(config.syscmd_list); | ||||||
|     tiny_queue_free(web_server_queue); |     tiny_queue_free(web_server_queue); | ||||||
|     tiny_queue_free(mpd_client_queue); |     tiny_queue_free(mpd_client_queue); | ||||||
|  |     tiny_queue_free(mympd_api_queue); | ||||||
|     return EXIT_SUCCESS; |     return EXIT_SUCCESS; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										427
									
								
								src/mpd_client.c
									
									
									
									
									
								
							
							
						
						
									
										427
									
								
								src/mpd_client.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -25,11 +25,6 @@ | |||||||
| #ifndef __MPD_CLIENT_H__ | #ifndef __MPD_CLIENT_H__ | ||||||
| #define __MPD_CLIENT_H__ | #define __MPD_CLIENT_H__ | ||||||
|  |  | ||||||
| #include "global.h" |  | ||||||
| #include "web_server.h" |  | ||||||
| #include "list.h" |  | ||||||
| #include "tiny_queue.h" |  | ||||||
|  |  | ||||||
| #define RETURN_ERROR_AND_RECOVER(X) do { \ | #define RETURN_ERROR_AND_RECOVER(X) do { \ | ||||||
|     printf("MPD %s: %s\n", X, mpd_connection_get_error_message(mpd.conn)); \ |     printf("MPD %s: %s\n", X, mpd_connection_get_error_message(mpd.conn)); \ | ||||||
|     len = json_printf(&out, "{type: error, data: %Q}", mpd_connection_get_error_message(mpd.conn)); \ |     len = json_printf(&out, "{type: error, data: %Q}", mpd_connection_get_error_message(mpd.conn)); \ | ||||||
| @@ -61,71 +56,6 @@ | |||||||
| } while (0) | } while (0) | ||||||
|  |  | ||||||
|  |  | ||||||
| #define MPD_CMDS(X) \ |  | ||||||
|     X(MPD_API_UNKNOWN) \ |  | ||||||
|     X(MPD_API_QUEUE_CLEAR) \ |  | ||||||
|     X(MPD_API_QUEUE_CROP) \ |  | ||||||
|     X(MPD_API_QUEUE_SAVE) \ |  | ||||||
|     X(MPD_API_QUEUE_LIST) \ |  | ||||||
|     X(MPD_API_QUEUE_SEARCH) \ |  | ||||||
|     X(MPD_API_QUEUE_RM_TRACK) \ |  | ||||||
|     X(MPD_API_QUEUE_RM_RANGE) \ |  | ||||||
|     X(MPD_API_QUEUE_MOVE_TRACK) \ |  | ||||||
|     X(MPD_API_QUEUE_ADD_TRACK_AFTER) \ |  | ||||||
|     X(MPD_API_QUEUE_ADD_TRACK) \ |  | ||||||
|     X(MPD_API_QUEUE_ADD_PLAY_TRACK) \ |  | ||||||
|     X(MPD_API_QUEUE_REPLACE_TRACK) \ |  | ||||||
|     X(MPD_API_QUEUE_ADD_PLAYLIST) \ |  | ||||||
|     X(MPD_API_QUEUE_REPLACE_PLAYLIST) \ |  | ||||||
|     X(MPD_API_QUEUE_SHUFFLE) \ |  | ||||||
|     X(MPD_API_QUEUE_LAST_PLAYED) \ |  | ||||||
|     X(MPD_API_PLAYLIST_CLEAR) \ |  | ||||||
|     X(MPD_API_PLAYLIST_RENAME) \ |  | ||||||
|     X(MPD_API_PLAYLIST_MOVE_TRACK) \ |  | ||||||
|     X(MPD_API_PLAYLIST_ADD_TRACK) \ |  | ||||||
|     X(MPD_API_PLAYLIST_RM_TRACK) \ |  | ||||||
|     X(MPD_API_PLAYLIST_RM) \ |  | ||||||
|     X(MPD_API_PLAYLIST_LIST) \ |  | ||||||
|     X(MPD_API_PLAYLIST_CONTENT_LIST) \ |  | ||||||
|     X(MPD_API_SMARTPLS_UPDATE_ALL) \ |  | ||||||
|     X(MPD_API_SMARTPLS_SAVE) \ |  | ||||||
|     X(MPD_API_SMARTPLS_GET) \ |  | ||||||
|     X(MPD_API_DATABASE_SEARCH_ADV) \ |  | ||||||
|     X(MPD_API_DATABASE_SEARCH) \ |  | ||||||
|     X(MPD_API_DATABASE_UPDATE) \ |  | ||||||
|     X(MPD_API_DATABASE_RESCAN) \ |  | ||||||
|     X(MPD_API_DATABASE_FILESYSTEM_LIST) \ |  | ||||||
|     X(MPD_API_DATABASE_TAG_LIST) \ |  | ||||||
|     X(MPD_API_DATABASE_TAG_ALBUM_LIST) \ |  | ||||||
|     X(MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST) \ |  | ||||||
|     X(MPD_API_DATABASE_STATS) \ |  | ||||||
|     X(MPD_API_DATABASE_SONGDETAILS) \ |  | ||||||
|     X(MPD_API_PLAYER_PLAY_TRACK) \ |  | ||||||
|     X(MPD_API_PLAYER_VOLUME_SET) \ |  | ||||||
|     X(MPD_API_PLAYER_VOLUME_GET) \ |  | ||||||
|     X(MPD_API_PLAYER_PAUSE) \ |  | ||||||
|     X(MPD_API_PLAYER_PLAY) \ |  | ||||||
|     X(MPD_API_PLAYER_STOP) \ |  | ||||||
|     X(MPD_API_PLAYER_SEEK) \ |  | ||||||
|     X(MPD_API_PLAYER_NEXT) \ |  | ||||||
|     X(MPD_API_PLAYER_PREV) \ |  | ||||||
|     X(MPD_API_PLAYER_OUTPUT_LIST) \ |  | ||||||
|     X(MPD_API_PLAYER_TOGGLE_OUTPUT) \ |  | ||||||
|     X(MPD_API_PLAYER_CURRENT_SONG) \ |  | ||||||
|     X(MPD_API_PLAYER_STATE) \ |  | ||||||
|     X(MPD_API_SETTINGS_GET) \ |  | ||||||
|     X(MPD_API_SETTINGS_SET) \ |  | ||||||
|     X(MPD_API_LIKE) \ |  | ||||||
|     X(MPD_API_COLS_SAVE) \ |  | ||||||
|     X(MPD_API_SYSCMD) |  | ||||||
|  |  | ||||||
| #define GEN_ENUM(X) X, |  | ||||||
| #define GEN_STR(X) #X, |  | ||||||
|  |  | ||||||
| enum mpd_cmd_ids { |  | ||||||
|     MPD_CMDS(GEN_ENUM) |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| enum mpd_conn_states { | enum mpd_conn_states { | ||||||
|     MPD_DISCONNECTED, |     MPD_DISCONNECTED, | ||||||
|     MPD_FAILURE, |     MPD_FAILURE, | ||||||
| @@ -167,7 +97,6 @@ struct list mympd_tags; | |||||||
| struct list mympd_searchtags; | struct list mympd_searchtags; | ||||||
| struct list mympd_browsetags; | struct list mympd_browsetags; | ||||||
| struct list last_played; | struct list last_played; | ||||||
| struct list syscmds; |  | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     long playCount; |     long playCount; | ||||||
| @@ -192,11 +121,10 @@ typedef struct { | |||||||
| } t_mympd_state; | } t_mympd_state; | ||||||
|  |  | ||||||
| t_mympd_state mympd_state; | t_mympd_state mympd_state; | ||||||
| tiny_queue_t *mpd_client_queue; |  | ||||||
|  |  | ||||||
| void mpd_client_idle(int timeout); | void mpd_client_idle(int timeout); | ||||||
| void mpd_client_parse_idle(int idle_bitmask); | void mpd_client_parse_idle(int idle_bitmask); | ||||||
| void mpd_client_api(struct work_request_t *request); | void mpd_client_api(void *arg_request); | ||||||
| void mpd_client_notify(size_t n); | void mpd_client_notify(size_t n); | ||||||
| bool mpd_client_count_song_id(int song_id, char *name, int value); | bool mpd_client_count_song_id(int song_id, char *name, int value); | ||||||
| bool mpd_client_count_song_uri(const char *uri, char *name, int value); | bool mpd_client_count_song_uri(const char *uri, char *name, int value); | ||||||
| @@ -208,7 +136,6 @@ bool mpd_client_last_played_list(int song_id); | |||||||
| bool mpd_client_jukebox(); | bool mpd_client_jukebox(); | ||||||
| bool mpd_client_state_get(char *name, char *value); | bool mpd_client_state_get(char *name, char *value); | ||||||
| bool mpd_client_state_set(const char *name, const char *value); | bool mpd_client_state_set(const char *name, const char *value); | ||||||
| int mpd_client_syscmd(char *buffer, char *cmd, int order); |  | ||||||
| int mpd_client_smartpls_save(char *smartpltype, char *playlist, char *tag, char *searchstr, int maxentries, int timerange); | int mpd_client_smartpls_save(char *smartpltype, char *playlist, char *tag, char *searchstr, int maxentries, int timerange); | ||||||
| int mpd_client_smartpls_put(char *buffer, char *playlist); | int mpd_client_smartpls_put(char *buffer, char *playlist); | ||||||
| int mpd_client_smartpls_update_all(); | int mpd_client_smartpls_update_all(); | ||||||
| @@ -228,7 +155,7 @@ int mpd_client_search_queue(char *buffer, char *mpdtagtype, unsigned int offset, | |||||||
| int mpd_client_put_welcome(char *buffer); | int mpd_client_put_welcome(char *buffer); | ||||||
| int mpd_client_put_volume(char *buffer); | int mpd_client_put_volume(char *buffer); | ||||||
| int mpd_client_put_stats(char *buffer); | int mpd_client_put_stats(char *buffer); | ||||||
| int mpd_client_put_settings(char *buffer); | int mpd_client_put_settings(char *buffer, void *arg_config); | ||||||
| int mpd_client_put_db_tag(char *buffer, unsigned int offset, char *mpdtagtype, char *mpdsearchtagtype, char *searchstr, char *filter); | int mpd_client_put_db_tag(char *buffer, unsigned int offset, char *mpdtagtype, char *mpdsearchtagtype, char *searchstr, char *filter); | ||||||
| int mpd_client_put_songs_in_album(char *buffer, char *album, char *search, char *tag); | int mpd_client_put_songs_in_album(char *buffer, char *album, char *search, char *tag); | ||||||
| int mpd_client_put_playlists(char *buffer, unsigned int offset, char *filter); | int mpd_client_put_playlists(char *buffer, unsigned int offset, char *filter); | ||||||
|   | |||||||
							
								
								
									
										135
									
								
								src/mympd_api.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								src/mympd_api.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | |||||||
|  | /* myMPD | ||||||
|  |    (c) 2018-2019 Juergen Mang <mail@jcgames.de> | ||||||
|  |    This project's homepage is: https://github.com/jcorporation/mympd | ||||||
|  |     | ||||||
|  |    myMPD ist fork of: | ||||||
|  |     | ||||||
|  |    ympd | ||||||
|  |    (c) 2013-2014 Andrew Karpow <andy@ndyk.de> | ||||||
|  |    This project's homepage is: http://www.ympd.org | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU General Public License as published by | ||||||
|  |    the Free Software Foundation; version 2 of the License. | ||||||
|  |  | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |    You should have received a copy of the GNU General Public License along | ||||||
|  |    with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string.h> | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  | #include <libgen.h> | ||||||
|  | #include <ctype.h> | ||||||
|  | #include <libgen.h> | ||||||
|  | #include <dirent.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  |  | ||||||
|  | #include "list.h" | ||||||
|  | #include "tiny_queue.h" | ||||||
|  | #include "global.h" | ||||||
|  | #include "mympd_api.h" | ||||||
|  | #include "../dist/src/frozen/frozen.h" | ||||||
|  |  | ||||||
|  | //private definitions | ||||||
|  | static void mympd_api(void *arg_request, void *arg_config); | ||||||
|  | static int mympd_api_syscmd(char *buffer, const char *cmd, void *arg_config); | ||||||
|  |  | ||||||
|  | //public functions | ||||||
|  | void *mympd_api_loop(void *arg_config) { | ||||||
|  |     while (s_signal_received == 0) { | ||||||
|  |         struct work_request_t *req = tiny_queue_shift(mympd_api_queue); | ||||||
|  |         mympd_api(req, arg_config); | ||||||
|  |     } | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //private functions | ||||||
|  | static void mympd_api(void *arg_request, void *arg_config) { | ||||||
|  |     struct work_request_t *request = (struct work_request_t*) arg_request; | ||||||
|  |     size_t len = 0; | ||||||
|  |     char buffer[MAX_SIZE]; | ||||||
|  |     int je; | ||||||
|  |     char *p_charbuf1; | ||||||
|  |     LOG_VERBOSE() printf("MYMPD API request: %.*s\n", request->length, request->data); | ||||||
|  |      | ||||||
|  |     if (request->cmd_id == MYMPD_API_SYSCMD) { | ||||||
|  |         if (config.syscmds == true) { | ||||||
|  |             je = json_scanf(request->data, request->length, "{data: {cmd: %Q}}", &p_charbuf1); | ||||||
|  |             if (je == 1) { | ||||||
|  |                 len = mympd_api_syscmd(buffer, p_charbuf1, arg_config); | ||||||
|  |                 free(p_charbuf1); | ||||||
|  |             } | ||||||
|  |         }  | ||||||
|  |         else { | ||||||
|  |             len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"System commands are disabled.\"}"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Unknown cmd_id %u.\"}", request->cmd_id); | ||||||
|  |         printf("ERROR: Unknown cmd_id %u\n", request->cmd_id);     | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (len == 0) { | ||||||
|  |         len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"No response for cmd_id %u.\"}", request->cmd_id); | ||||||
|  |         printf("ERROR: No response for cmd_id %u\n", request->cmd_id); | ||||||
|  |     } | ||||||
|  |     LOG_DEBUG() fprintf(stderr, "DEBUG: Send http response to connection %lu (first 800 chars):\n%*.*s\n", request->conn_id, 0, 800, buffer); | ||||||
|  |  | ||||||
|  |     struct work_result_t *response = (struct work_result_t*)malloc(sizeof(struct work_result_t)); | ||||||
|  |     response->conn_id = request->conn_id; | ||||||
|  |     response->length = copy_string(response->data, buffer, MAX_SIZE, len); | ||||||
|  |     tiny_queue_push(web_server_queue, response); | ||||||
|  |  | ||||||
|  |     free(request); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static int mympd_api_syscmd(char *buffer, const char *cmd, void *arg_config) { | ||||||
|  |     int len; | ||||||
|  |     char filename[400]; | ||||||
|  |     char *line; | ||||||
|  |     char *crap; | ||||||
|  |     size_t n = 0; | ||||||
|  |     ssize_t read; | ||||||
|  |     t_config *config = (t_config *) arg_config; | ||||||
|  |      | ||||||
|  |     const int order = list_get_value(config->syscmd_list, cmd); | ||||||
|  |     if (order == -1) { | ||||||
|  |         printf("ERROR: Syscmd not defined: %s\n", cmd); | ||||||
|  |         len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"System command not defined\"}"); | ||||||
|  |         return len; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     snprintf(filename, 400, "%s/syscmds/%d%s", config->etcdir, order, cmd); | ||||||
|  |     FILE *fp = fopen(filename, "r");     | ||||||
|  |     if (fp == NULL) { | ||||||
|  |         len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't execute cmd %s.\"}", cmd); | ||||||
|  |         printf("ERROR: Can't execute syscmd \"%s\"\n", cmd); | ||||||
|  |         return len; | ||||||
|  |     } | ||||||
|  |     read = getline(&line, &n, fp); | ||||||
|  |     fclose(fp); | ||||||
|  |     if (read > 0) { | ||||||
|  |         strtok_r(line, "\n", &crap); | ||||||
|  |         if (system(line) == 0) { | ||||||
|  |             len = snprintf(buffer, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Executed cmd %s.\"}", cmd); | ||||||
|  |             LOG_VERBOSE2() printf("Executed syscmd: \"%s\"\n", line); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Executing cmd %s failed.\"}", cmd); | ||||||
|  |             printf("ERROR: Executing syscmd \"%s\" failed.\n", cmd); | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         len = snprintf(buffer, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't execute cmd %s.\"}", cmd); | ||||||
|  |         printf("ERROR: Can't execute syscmd \"%s\"\n", cmd); | ||||||
|  |     } | ||||||
|  |     CHECK_RETURN_LEN();     | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								src/mympd_api.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/mympd_api.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* myMPD | ||||||
|  |    (c) 2018-2019 Juergen Mang <mail@jcgames.de> | ||||||
|  |    This project's homepage is: https://github.com/jcorporation/mympd | ||||||
|  |     | ||||||
|  |    myMPD ist fork of: | ||||||
|  |     | ||||||
|  |    ympd | ||||||
|  |    (c) 2013-2014 Andrew Karpow <andy@ndyk.de> | ||||||
|  |    This project's homepage is: http://www.ympd.org | ||||||
|  |     | ||||||
|  |    This program is free software; you can redistribute it and/or modify | ||||||
|  |    it under the terms of the GNU General Public License as published by | ||||||
|  |    the Free Software Foundation; version 2 of the License. | ||||||
|  |  | ||||||
|  |    This program is distributed in the hope that it will be useful, | ||||||
|  |    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
|  |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||||
|  |    GNU General Public License for more details. | ||||||
|  |  | ||||||
|  |    You should have received a copy of the GNU General Public License along | ||||||
|  |    with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|  |    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | #ifndef __MYMPD_API_H__ | ||||||
|  | #define __MYMPD_API_H__ | ||||||
|  |  | ||||||
|  | void *mympd_api_loop(void *arg_config); | ||||||
|  |  | ||||||
|  | #endif | ||||||
| @@ -23,25 +23,31 @@ | |||||||
| */ | */ | ||||||
|  |  | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <pthread.h> | ||||||
|  |  | ||||||
|  | #include "list.h" | ||||||
|  | #include "tiny_queue.h" | ||||||
| #include "global.h" | #include "global.h" | ||||||
| #include "web_server.h" | #include "web_server.h" | ||||||
| #include "mpd_client.h" | #include "mpd_client.h" | ||||||
| #include "../dist/src/mongoose/mongoose.h" | #include "../dist/src/mongoose/mongoose.h" | ||||||
|  | #include "../dist/src/frozen/frozen.h" | ||||||
|  |  | ||||||
| //non-api definitions | //private definitions | ||||||
| static int is_websocket(const struct mg_connection *nc); | static int is_websocket(const struct mg_connection *nc); | ||||||
| static void ev_handler(struct mg_connection *nc, int ev, void *ev_data); | static void ev_handler(struct mg_connection *nc, int ev, void *ev_data); | ||||||
| static void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data); | static void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data); | ||||||
| static void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response); | static void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response); | ||||||
| static void send_api_response(struct mg_mgr *mgr, struct work_result_t *response); | static void send_api_response(struct mg_mgr *mgr, struct work_result_t *response); | ||||||
|  | static bool handle_api(long conn_id, const char *request, int request_len); | ||||||
|  |  | ||||||
| typedef struct t_user_data { | typedef struct t_user_data { | ||||||
|     void *config; //pointer to mympd config |     void *config; //pointer to mympd config | ||||||
|     long conn_id;  |     long conn_id;  | ||||||
| } t_user_data; | } t_user_data; | ||||||
|  |  | ||||||
| //api functions | //public functions | ||||||
| bool web_server_init(void *arg_mgr, void *arg_config) { | bool web_server_init(void *arg_mgr, void *arg_config) { | ||||||
|     struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr; |     struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr; | ||||||
|     t_config *config = (t_config *) arg_config; |     t_config *config = (t_config *) arg_config; | ||||||
| @@ -93,13 +99,13 @@ bool web_server_init(void *arg_mgr, void *arg_config) { | |||||||
|     return mgr; |     return mgr; | ||||||
| } | } | ||||||
|  |  | ||||||
| void web_server_free(void *arg) { | void web_server_free(void *arg_mgr) { | ||||||
|     struct mg_mgr *mgr = (struct mg_mgr *) arg; |     struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr; | ||||||
|     mg_mgr_free(mgr); |     mg_mgr_free(mgr); | ||||||
| } | } | ||||||
|  |  | ||||||
| void *web_server_loop(void *arg) { | void *web_server_loop(void *arg_mgr) { | ||||||
|     struct mg_mgr *mgr = (struct mg_mgr *) arg; |     struct mg_mgr *mgr = (struct mg_mgr *) arg_mgr; | ||||||
|     while (s_signal_received == 0) { |     while (s_signal_received == 0) { | ||||||
|         mg_mgr_poll(mgr, 100); |         mg_mgr_poll(mgr, 100); | ||||||
|         unsigned web_server_queue_length = tiny_queue_length(web_server_queue); |         unsigned web_server_queue_length = tiny_queue_length(web_server_queue); | ||||||
| @@ -119,7 +125,7 @@ void *web_server_loop(void *arg) { | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| //non-api functions | //private functions | ||||||
| static int is_websocket(const struct mg_connection *nc) { | static int is_websocket(const struct mg_connection *nc) { | ||||||
|     return nc->flags & MG_F_IS_WEBSOCKET; |     return nc->flags & MG_F_IS_WEBSOCKET; | ||||||
| } | } | ||||||
| @@ -160,7 +166,7 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { | |||||||
|             else |             else | ||||||
|                 user_data->conn_id = 1; |                 user_data->conn_id = 1; | ||||||
|              |              | ||||||
|             //remove mgr user_data and set connection specific user_data |             //replace mgr user_data with connection specific user_data | ||||||
|             t_user_data *nc_user_data = (t_user_data*)malloc(sizeof(t_user_data)); |             t_user_data *nc_user_data = (t_user_data*)malloc(sizeof(t_user_data)); | ||||||
|             nc_user_data->config = config; |             nc_user_data->config = config; | ||||||
|             nc_user_data->conn_id = user_data->conn_id; |             nc_user_data->conn_id = user_data->conn_id; | ||||||
| @@ -188,10 +194,13 @@ static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { | |||||||
|             struct http_message *hm = (struct http_message *) ev_data; |             struct http_message *hm = (struct http_message *) ev_data; | ||||||
|             LOG_VERBOSE2() printf("HTTP request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p); |             LOG_VERBOSE2() printf("HTTP request (%ld): %.*s\n", user_data->conn_id, hm->uri.len, hm->uri.p); | ||||||
|             if (mg_vcmp(&hm->uri, "/api") == 0) { |             if (mg_vcmp(&hm->uri, "/api") == 0) { | ||||||
|                 struct work_request_t *request = (struct work_request_t*)malloc(sizeof(struct work_request_t)); |                 bool rc = handle_api(user_data->conn_id, hm->body.p, hm->body.len); | ||||||
|                 request->conn_id = user_data->conn_id; |                 if (rc == false) { | ||||||
|                 request->length = copy_string(request->data, hm->body.p, 1000, hm->body.len); |                     printf("ERROR: Invalid API request.\n"); | ||||||
|                 tiny_queue_push(mpd_client_queue, request); |                     char *response = "{\"type\": \"error\", \"data\": \"Invalid API request\"}"; | ||||||
|  |                     mg_send_head(nc, 200, strlen(response), "Content-Type: application/json"); | ||||||
|  |                     mg_printf(nc, "%s", response); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 static struct mg_serve_http_opts s_http_server_opts; |                 static struct mg_serve_http_opts s_http_server_opts; | ||||||
| @@ -239,3 +248,28 @@ static void ev_handler_redirect(struct mg_connection *nc, int ev, void *ev_data) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static bool handle_api(long conn_id, const char *request_body, int request_len) { | ||||||
|  |     char *cmd; | ||||||
|  |      | ||||||
|  |     LOG_VERBOSE() printf("API request: %.*s\n", request_len, request_body); | ||||||
|  |     const int je = json_scanf(request_body, request_len, "{cmd: %Q}", &cmd); | ||||||
|  |     if (je < 1) | ||||||
|  |         return false; | ||||||
|  |  | ||||||
|  |     enum mypd_cmd_ids cmd_id = get_cmd_id(cmd); | ||||||
|  |     if (cmd_id == 0) | ||||||
|  |         return false; | ||||||
|  |      | ||||||
|  |     struct work_request_t *request = (struct work_request_t*)malloc(sizeof(struct work_request_t)); | ||||||
|  |     request->conn_id = conn_id; | ||||||
|  |     request->cmd_id = cmd_id; | ||||||
|  |     request->length = copy_string(request->data, request_body, 1000, request_len); | ||||||
|  |      | ||||||
|  |     if (strncmp(cmd, "MYMPD_API_", 10) == 0) | ||||||
|  |         tiny_queue_push(mympd_api_queue, request); | ||||||
|  |     else | ||||||
|  |         tiny_queue_push(mpd_client_queue, request); | ||||||
|  |          | ||||||
|  |     return true; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -25,24 +25,8 @@ | |||||||
| #ifndef __WEB_SERVER_H__ | #ifndef __WEB_SERVER_H__ | ||||||
| #define __WEB_SERVER_H__ | #define __WEB_SERVER_H__ | ||||||
|  |  | ||||||
| #include "tiny_queue.h" | void *web_server_loop(void *arg_mgr); | ||||||
|  |  | ||||||
| tiny_queue_t *web_server_queue; |  | ||||||
|  |  | ||||||
| struct work_request_t { |  | ||||||
|     long conn_id;  // needed to identify the connection where to send the reply |  | ||||||
|     char data[1000]; |  | ||||||
|     int length; |  | ||||||
| } work_request_t; |  | ||||||
|  |  | ||||||
| struct work_result_t { |  | ||||||
|     long conn_id;  // needed to identify the connection where to send the reply |  | ||||||
|     char data[MAX_SIZE]; |  | ||||||
|     int length; |  | ||||||
| } work_result_t; |  | ||||||
|  |  | ||||||
| void *web_server_loop(void *arg); |  | ||||||
| bool web_server_init(void *arg_mgr, void *arg_config); | bool web_server_init(void *arg_mgr, void *arg_config); | ||||||
| void web_server_free(void *arg); | void web_server_free(void *arg_mgr); | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation