mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 13:53:00 +00:00 
			
		
		
		
	Feat: initial working code
This commit is contained in:
		| @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 2.6) | |||||||
|  |  | ||||||
| project (mympd C) | project (mympd C) | ||||||
| set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake/") | ||||||
| set(CPACK_PACKAGE_VERSION_MAJOR "4") | set(CPACK_PACKAGE_VERSION_MAJOR "5") | ||||||
| set(CPACK_PACKAGE_VERSION_MINOR "7") | set(CPACK_PACKAGE_VERSION_MINOR "0") | ||||||
| set(CPACK_PACKAGE_VERSION_PATCH "2") | set(CPACK_PACKAGE_VERSION_PATCH "0") | ||||||
|  |  | ||||||
| if(CMAKE_BUILD_TYPE MATCHES RELEASE) | if(CMAKE_BUILD_TYPE MATCHES RELEASE) | ||||||
|     set(ASSETS_PATH "/usr/share/${PROJECT_NAME}/htdocs") |     set(ASSETS_PATH "/usr/share/${PROJECT_NAME}/htdocs") | ||||||
| @@ -21,7 +21,7 @@ include_directories(${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}	${LIBMPDCLIENT_I | |||||||
|  |  | ||||||
| include(CheckCSourceCompiles) | include(CheckCSourceCompiles) | ||||||
|  |  | ||||||
| set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -pedantic -D MG_ENABLE_SSL -D MG_ENABLE_IPV6 -D MG_DISABLE_MQTT -D MG_DISABLE_MQTT_BROKER -D MG_DISABLE_DNS_SERVER -D MG_DISABLE_COAP -D MG_DISABLE_HTTP_CGI -D MG_DISABLE_HTTP_SSI -D MG_DISABLE_HTTP_WEBDAV") | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -pedantic -D MG_ENABLE_SSL -D MG_ENABLE_THREADS -D MG_ENABLE_IPV6 -D MG_DISABLE_MQTT -D MG_DISABLE_MQTT_BROKER -D MG_DISABLE_DNS_SERVER -D MG_DISABLE_COAP -D MG_DISABLE_HTTP_CGI -D MG_DISABLE_HTTP_SSI -D MG_DISABLE_HTTP_WEBDAV") | ||||||
| set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -D_FORTIFY_SOURCE=2 -fstack-protector -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=shift -fsanitize=integer-divide-by-zero -fsanitize=unreachable -fsanitize=vla-bound -fsanitize=null -fsanitize=return -fsanitize=signed-integer-overflow -fsanitize=bounds -fsanitize=bounds-strict -fsanitize=alignment -fsanitize=object-size -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=nonnull-attribute -fsanitize=returns-nonnull-attribute -fsanitize=bool -fsanitize=enum -fsanitize=vptr -static-libasan") | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -D_FORTIFY_SOURCE=2 -fstack-protector -fsanitize=address -fno-omit-frame-pointer -fsanitize=undefined -fsanitize=shift -fsanitize=integer-divide-by-zero -fsanitize=unreachable -fsanitize=vla-bound -fsanitize=null -fsanitize=return -fsanitize=signed-integer-overflow -fsanitize=bounds -fsanitize=bounds-strict -fsanitize=alignment -fsanitize=object-size -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=nonnull-attribute -fsanitize=returns-nonnull-attribute -fsanitize=bool -fsanitize=enum -fsanitize=vptr -static-libasan") | ||||||
|  |  | ||||||
| find_package(OpenSSL REQUIRED) | find_package(OpenSSL REQUIRED) | ||||||
| @@ -31,8 +31,10 @@ set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS NS_ENABLE_SSL) | |||||||
| set(SOURCES | set(SOURCES | ||||||
|     src/mympd.c |     src/mympd.c | ||||||
|     src/mpd_client.c |     src/mpd_client.c | ||||||
|  |     src/web_server.c | ||||||
|     src/list.c |     src/list.c | ||||||
|     src/validate.c |     src/tiny_queue.c | ||||||
|  |     src/common.c | ||||||
|     dist/src/mongoose/mongoose.c |     dist/src/mongoose/mongoose.c | ||||||
|     dist/src/frozen/frozen.c |     dist/src/frozen/frozen.c | ||||||
|     dist/src/inih/ini.c |     dist/src/inih/ini.c | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								PKGBUILD
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								PKGBUILD
									
									
									
									
									
								
							| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
| pkgname=mympd | pkgname=mympd | ||||||
| _pkgname=myMPD | _pkgname=myMPD | ||||||
| pkgver=4.7.2 | pkgver=5.0.0 | ||||||
| pkgrel=1 | pkgrel=1 | ||||||
| pkgdesc="myMPD is a standalone and mobile friendly web mpdclient." | pkgdesc="myMPD is a standalone and mobile friendly web mpdclient." | ||||||
| arch=('x86_64' 'armv7h' 'aarch64') | arch=('x86_64' 'armv7h' 'aarch64') | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| # (c) 2018 Juergen Mang <mail@jcgames.de> | # (c) 2018 Juergen Mang <mail@jcgames.de> | ||||||
|  |  | ||||||
| Name:           myMPD | Name:           myMPD | ||||||
| Version:        4.7.2 | Version:        5.0.0 | ||||||
| Release:        0  | Release:        0  | ||||||
| License:        GPL-2.0  | License:        GPL-2.0  | ||||||
| Group:          Productivity/Multimedia/Sound/Players | Group:          Productivity/Multimedia/Sound/Players | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/changelog
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,5 @@ | |||||||
| mympd (4.7.2-1) stable; urgency=medium | mympd (5.0.0-1) stable; urgency=medium | ||||||
|  |  | ||||||
|   * Release from master |   * Release from master | ||||||
|  |  | ||||||
|  -- Juergen Mang <mail@jcgames.de>  Fri, 07 Dec 2018 17:12:12 +0000 |  -- Juergen Mang <mail@jcgames.de>  Fri, 04 Jan 2019 09:01:07 +0000 | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| var CACHE = 'myMPD-cache-v4.7.2'; | var CACHE = 'myMPD-cache-v5.0.0'; | ||||||
| var urlsToCache = [ | var urlsToCache = [ | ||||||
|     '/', |     '/', | ||||||
|     '/player.html', |     '/player.html', | ||||||
|   | |||||||
| @@ -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
 | ||||||
|     |     | ||||||
|    myMPD ist fork of: |    myMPD ist fork of: | ||||||
| @@ -26,7 +26,7 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include "validate.h" | #include "common.h" | ||||||
| 
 | 
 | ||||||
| void sanitize_string(const char *data) { | void sanitize_string(const char *data) { | ||||||
|     static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz" |     static char ok_chars[] = "abcdefghijklmnopqrstuvwxyz" | ||||||
| @@ -38,18 +38,11 @@ void sanitize_string(const char *data) { | |||||||
|         *cp = '_'; |         *cp = '_'; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int validate_path(char *path, const char *basepath) { | int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len) { | ||||||
|     char *rpath = NULL; |     if (dst_len == 0 || src_len == 0) | ||||||
|     char *ptr; |  | ||||||
|     ptr = realpath(path, rpath); |  | ||||||
|     if (ptr == NULL) |  | ||||||
|         return 1; |  | ||||||
|     if (strncmp(basepath, ptr, strlen(basepath)) == 0) { |  | ||||||
|         free(rpath); |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     size_t const max = (src_len < dst_len) ? src_len : dst_len -1; | ||||||
|     else { |     memcpy(dest, src, max); | ||||||
|         free(rpath); |     dest[max] = '\0'; | ||||||
|         return 1; |     return max; | ||||||
|     } |  | ||||||
| } | } | ||||||
							
								
								
									
										72
									
								
								src/common.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/common.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | |||||||
|  | /* 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 __COMMON_H__ | ||||||
|  | #define __COMMON_H__ | ||||||
|  |  | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #define MAX_SIZE 2048 * 400 | ||||||
|  | #define MAX_ELEMENTS_PER_PAGE 400 | ||||||
|  |  | ||||||
|  | #define LOG_INFO() if (config.loglevel >= 1)  | ||||||
|  | #define LOG_VERBOSE() if (config.loglevel >= 2)  | ||||||
|  | #define LOG_DEBUG() if (config.loglevel == 3)  | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     long mpdport; | ||||||
|  |     const char *mpdhost; | ||||||
|  |     const char *mpdpass; | ||||||
|  |     const char *webport; | ||||||
|  |     bool ssl; | ||||||
|  |     const char *sslport; | ||||||
|  |     const char *sslcert; | ||||||
|  |     const char *sslkey; | ||||||
|  |     const char *user; | ||||||
|  |     bool coverimage; | ||||||
|  |     const char *coverimagename; | ||||||
|  |     long coverimagesize; | ||||||
|  |     bool stickers; | ||||||
|  |     bool mixramp; | ||||||
|  |     const char *taglist; | ||||||
|  |     const char *searchtaglist; | ||||||
|  |     const char *browsetaglist; | ||||||
|  |     bool smartpls; | ||||||
|  |     const char *varlibdir; | ||||||
|  |     const char *etcdir; | ||||||
|  |     unsigned long max_elements_per_page; | ||||||
|  |     bool syscmds; | ||||||
|  |     bool localplayer; | ||||||
|  |     long streamport; | ||||||
|  |     const char *streamurl; | ||||||
|  |     unsigned long last_played_count; | ||||||
|  |     long loglevel; | ||||||
|  | } t_config; | ||||||
|  |  | ||||||
|  | t_config config; | ||||||
|  |  | ||||||
|  | void sanitize_string(const char *data); | ||||||
|  | int copy_string(char * const dest, char const * const src, size_t const dst_len, size_t const src_len); | ||||||
|  | #endif | ||||||
| @@ -18,6 +18,9 @@ | |||||||
|    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
| */ | */ | ||||||
|  |  | ||||||
|  | #ifndef __LIST_H__ | ||||||
|  | #define __LIST_H__ | ||||||
|  |  | ||||||
| struct node { | struct node { | ||||||
|     char *data; |     char *data; | ||||||
|     long value; |     long value; | ||||||
| @@ -43,3 +46,4 @@ int list_shuffle(struct list *l); | |||||||
| int list_sort_by_value(struct list *l, bool order); | int list_sort_by_value(struct list *l, bool order); | ||||||
| int list_swap_item(struct node *n1, struct node *n2); | int list_swap_item(struct node *n1, struct node *n2); | ||||||
| struct node *list_node_at(const struct list * l, unsigned index); | struct node *list_node_at(const struct list * l, unsigned index); | ||||||
|  | #endif | ||||||
|   | |||||||
							
								
								
									
										269
									
								
								src/mpd_client.c
									
									
									
									
									
								
							
							
						
						
									
										269
									
								
								src/mpd_client.c
									
									
									
									
									
								
							| @@ -32,8 +32,9 @@ | |||||||
| #include <poll.h> | #include <poll.h> | ||||||
| #include <mpd/client.h> | #include <mpd/client.h> | ||||||
|  |  | ||||||
|  | #include "common.h" | ||||||
| #include "mpd_client.h" | #include "mpd_client.h" | ||||||
| #include "validate.h" | #include "web_server.h" | ||||||
| #include "config.h" | #include "config.h" | ||||||
| #include "../dist/src/frozen/frozen.h" | #include "../dist/src/frozen/frozen.h" | ||||||
|  |  | ||||||
| @@ -49,9 +50,7 @@ static inline enum mpd_cmd_ids get_cmd_id(const char *cmd) { | |||||||
|     return -1; |     return -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| enum mpd_idle idle_bitmask_save = 0; | void mympd_api(struct work_request_t *request) { | ||||||
|  |  | ||||||
| void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { |  | ||||||
|     size_t n = 0; |     size_t n = 0; | ||||||
|     char *cmd; |     char *cmd; | ||||||
|     unsigned int uint_buf1, uint_buf2, uint_rc; |     unsigned int uint_buf1, uint_buf2, uint_rc; | ||||||
| @@ -61,49 +60,40 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|     char *p_charbuf1, *p_charbuf2, *p_charbuf3, *p_charbuf4; |     char *p_charbuf1, *p_charbuf2, *p_charbuf3, *p_charbuf4; | ||||||
|     char p_char[4]; |     char p_char[4]; | ||||||
|     enum mpd_cmd_ids cmd_id; |     enum mpd_cmd_ids cmd_id; | ||||||
|     struct pollfd fds[1]; |  | ||||||
|     int pollrc; |  | ||||||
|     #ifdef DEBUG |     #ifdef DEBUG | ||||||
|     struct timespec start, end; |     struct timespec start, end; | ||||||
|     #endif |     #endif | ||||||
|      |      | ||||||
|     LOG_VERBOSE() printf("API request: %s\n", msg.p); |     LOG_VERBOSE() printf("API request: %.*s\n", request->length, request->data); | ||||||
|      |      | ||||||
|     je = json_scanf(msg.p, msg.len, "{cmd: %Q}", &cmd); |     je = json_scanf(request->data, request->length, "{cmd: %Q}", &cmd); | ||||||
|     if (je == 1)  |     if (je == 1) { | ||||||
|         cmd_id = get_cmd_id(cmd); |         cmd_id = get_cmd_id(cmd); | ||||||
|     else |     } | ||||||
|         cmd_id = get_cmd_id("MPD_API_UNKNOWN"); |     else { | ||||||
|  |         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Invalid API request.\"}"); | ||||||
|  |         printf("Error: Invalid API request.\n"); | ||||||
|  |         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, mpd.buf, MAX_SIZE, n); | ||||||
|  |         tiny_queue_push(web_server_queue, response); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     if (cmd_id == -1) |     if (cmd_id == -1) | ||||||
|         cmd_id = get_cmd_id("MPD_API_UNKNOWN"); |         cmd_id = get_cmd_id("MPD_API_UNKNOWN"); | ||||||
|  |  | ||||||
|     LOG_DEBUG() fprintf(stderr, "DEBUG: Leaving mpd idle mode\n"); |  | ||||||
|     if (mpd_send_noidle(mpd.conn)) { |  | ||||||
|     //save idle events (processing later) |  | ||||||
|         LOG_DEBUG() fprintf(stderr, "DEBUG: Checking for idle events\n"); |  | ||||||
|         fds[0].fd = mpd_connection_get_fd(mpd.conn); |  | ||||||
|         fds[0].events = POLLIN; |  | ||||||
|         pollrc = poll(fds, 1, 200); |  | ||||||
|         if (pollrc > 0) { |  | ||||||
|             idle_bitmask_save = mpd_recv_idle(mpd.conn, false); |  | ||||||
|             if (idle_bitmask_save > 0) |  | ||||||
|                 LOG_DEBUG() fprintf(stderr, "DEBUG: Idle event before request: %d\n", idle_bitmask_save); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     mpd_response_finish(mpd.conn); |  | ||||||
|     //handle request |  | ||||||
|     #ifdef DEBUG |     #ifdef DEBUG | ||||||
|     clock_gettime(CLOCK_MONOTONIC_RAW, &start); |     clock_gettime(CLOCK_MONOTONIC_RAW, &start); | ||||||
|     #endif |     #endif | ||||||
|     switch(cmd_id) { |     switch(cmd_id) { | ||||||
|         case MPD_API_UNKNOWN: |         case MPD_API_UNKNOWN: | ||||||
|             n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Unknown request\"}"); |             n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Unknown request\"}"); | ||||||
|             printf("Unknown API request: %s\n", msg.p); |             printf("Unknown API request: %.*s\n", request->length, request->data); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_LIKE: |         case MPD_API_LIKE: | ||||||
|             if (config.stickers) { |             if (config.stickers) { | ||||||
|                 je = json_scanf(msg.p, msg.len, "{data: {uri: %Q, like: %d}}", &p_charbuf1, &uint_buf1); |                 je = json_scanf(request->data, request->length, "{data: {uri: %Q, like: %d}}", &p_charbuf1, &uint_buf1); | ||||||
|                 if (je == 2) {         |                 if (je == 2) {         | ||||||
|                     if (!mympd_like_song_uri(p_charbuf1, uint_buf1)) |                     if (!mympd_like_song_uri(p_charbuf1, uint_buf1)) | ||||||
|                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set like.\"}"); |                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set like.\"}"); | ||||||
| @@ -118,10 +108,10 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_COLS_SAVE: |         case MPD_API_COLS_SAVE: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {table: %Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {table: %Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 char column_list[800]; |                 char column_list[800]; | ||||||
|                 snprintf(column_list, 800, "%.*s", msg.len, msg.p); |                 snprintf(column_list, 800, "%.*s", request->length, request->data); | ||||||
|                 char *cols = strchr(column_list, '['); |                 char *cols = strchr(column_list, '['); | ||||||
|                 int len = strlen(cols);  |                 int len = strlen(cols);  | ||||||
|                 if (len > 1) |                 if (len > 1) | ||||||
| @@ -169,7 +159,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             break; |             break; | ||||||
|         case MPD_API_SYSCMD: |         case MPD_API_SYSCMD: | ||||||
|             if (config.syscmds == true) { |             if (config.syscmds == true) { | ||||||
|                 je = json_scanf(msg.p, msg.len, "{data: {cmd: %Q}}", &p_charbuf1); |                 je = json_scanf(request->data, request->length, "{data: {cmd: %Q}}", &p_charbuf1); | ||||||
|                 if (je == 1) { |                 if (je == 1) { | ||||||
|                     int_buf1 = list_get_value(&syscmds, p_charbuf1); |                     int_buf1 = list_get_value(&syscmds, p_charbuf1); | ||||||
|                     if (int_buf1 > -1) |                     if (int_buf1 > -1) | ||||||
| @@ -188,73 +178,73 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             n = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length); |             n = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_SETTINGS_SET: |         case MPD_API_SETTINGS_SET: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {notificationWeb: %B}}", &mympd_state.notificationWeb); |             je = json_scanf(request->data, request->length, "{data: {notificationWeb: %B}}", &mympd_state.notificationWeb); | ||||||
|             if (je == 1) |             if (je == 1) | ||||||
|                 if (!mympd_state_set("notificationWeb", (mympd_state.notificationWeb == true ? "true" : "false"))) |                 if (!mympd_state_set("notificationWeb", (mympd_state.notificationWeb == true ? "true" : "false"))) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state notificationWeb.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state notificationWeb.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {notificationPage: %B}}", &mympd_state.notificationPage); |             je = json_scanf(request->data, request->length, "{data: {notificationPage: %B}}", &mympd_state.notificationPage); | ||||||
|             if (je == 1) |             if (je == 1) | ||||||
|                 if (!mympd_state_set("notificationPage", (mympd_state.notificationPage == true ? "true" : "false"))) |                 if (!mympd_state_set("notificationPage", (mympd_state.notificationPage == true ? "true" : "false"))) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state notificationPage.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state notificationPage.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {jukeboxMode: %d}}", &mympd_state.jukeboxMode); |             je = json_scanf(request->data, request->length, "{data: {jukeboxMode: %d}}", &mympd_state.jukeboxMode); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 snprintf(p_char, 4, "%d", mympd_state.jukeboxMode); |                 snprintf(p_char, 4, "%d", mympd_state.jukeboxMode); | ||||||
|                 if (!mympd_state_set("jukeboxMode", p_char)) |                 if (!mympd_state_set("jukeboxMode", p_char)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxMode.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxMode.\"}"); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {jukeboxPlaylist: %Q}}", &mympd_state.jukeboxPlaylist); |             je = json_scanf(request->data, request->length, "{data: {jukeboxPlaylist: %Q}}", &mympd_state.jukeboxPlaylist); | ||||||
|             if (je == 1) |             if (je == 1) | ||||||
|                 if (!mympd_state_set("jukeboxPlaylist", mympd_state.jukeboxPlaylist)) |                 if (!mympd_state_set("jukeboxPlaylist", mympd_state.jukeboxPlaylist)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxPlaylist.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxPlaylist.\"}"); | ||||||
|  |  | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {jukeboxQueueLength: %d}}", &mympd_state.jukeboxQueueLength); |             je = json_scanf(request->data, request->length, "{data: {jukeboxQueueLength: %d}}", &mympd_state.jukeboxQueueLength); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 snprintf(p_char, 4, "%d", mympd_state.jukeboxQueueLength); |                 snprintf(p_char, 4, "%d", mympd_state.jukeboxQueueLength); | ||||||
|                 if (!mympd_state_set("jukeboxQueueLength", p_char)) |                 if (!mympd_state_set("jukeboxQueueLength", p_char)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxQueueLength.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set state jukeboxQueueLength.\"}"); | ||||||
|             } |             } | ||||||
|          |          | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {random: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {random: %u}}", &uint_buf1); | ||||||
|             if (je == 1)         |             if (je == 1)         | ||||||
|                 if (!mpd_run_random(mpd.conn, uint_buf1)) |                 if (!mpd_run_random(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state random.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state random.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {repeat: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {repeat: %u}}", &uint_buf1); | ||||||
|             if (je == 1)         |             if (je == 1)         | ||||||
|                 if (!mpd_run_repeat(mpd.conn, uint_buf1)) |                 if (!mpd_run_repeat(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state repeat.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state repeat.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {consume: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {consume: %u}}", &uint_buf1); | ||||||
|             if (je == 1)         |             if (je == 1)         | ||||||
|                 if (!mpd_run_consume(mpd.conn, uint_buf1)) |                 if (!mpd_run_consume(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state consume.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state consume.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {single: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {single: %u}}", &uint_buf1); | ||||||
|             if (je == 1) |             if (je == 1) | ||||||
|                 if (!mpd_run_single(mpd.conn, uint_buf1)) |                 if (!mpd_run_single(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state single.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state single.\"}"); | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {crossfade: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {crossfade: %u}}", &uint_buf1); | ||||||
|             if (je == 1) |             if (je == 1) | ||||||
|                 if (!mpd_run_crossfade(mpd.conn, uint_buf1)) |                 if (!mpd_run_crossfade(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state crossfade.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state crossfade.\"}"); | ||||||
|              |              | ||||||
|             if (config.mixramp) { |             if (config.mixramp) { | ||||||
|                 je = json_scanf(msg.p, msg.len, "{data: {mixrampdb: %f}}", &float_buf); |                 je = json_scanf(request->data, request->length, "{data: {mixrampdb: %f}}", &float_buf); | ||||||
|                 if (je == 1)         |                 if (je == 1)         | ||||||
|                     if (!mpd_run_mixrampdb(mpd.conn, float_buf)) |                     if (!mpd_run_mixrampdb(mpd.conn, float_buf)) | ||||||
|                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state mixrampdb.\"}"); |                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state mixrampdb.\"}"); | ||||||
|              |              | ||||||
|                 je = json_scanf(msg.p, msg.len, "{data: {mixrampdelay: %f}}", &float_buf); |                 je = json_scanf(request->data, request->length, "{data: {mixrampdelay: %f}}", &float_buf); | ||||||
|                 if (je == 1) |                 if (je == 1) | ||||||
|                     if (!mpd_run_mixrampdelay(mpd.conn, float_buf)) |                     if (!mpd_run_mixrampdelay(mpd.conn, float_buf)) | ||||||
|                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state mixrampdelay.\"}"); |                         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state mixrampdelay.\"}"); | ||||||
|             } |             } | ||||||
|              |              | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {replaygain: %Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {replaygain: %Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (!mpd_send_command(mpd.conn, "replay_gain_mode", p_charbuf1, NULL)) |                 if (!mpd_send_command(mpd.conn, "replay_gain_mode", p_charbuf1, NULL)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state replaygain.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Can't set mpd state replaygain.\"}"); | ||||||
| @@ -287,11 +277,11 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Smart Playlists update failed\"}"); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Smart Playlists update failed\"}"); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_SMARTPLS_SAVE: |         case MPD_API_SMARTPLS_SAVE: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {type: %Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {type: %Q}}", &p_charbuf1); | ||||||
|             n = 1; |             n = 1; | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (strcmp(p_charbuf1, "sticker") == 0) { |                 if (strcmp(p_charbuf1, "sticker") == 0) { | ||||||
|                     je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q, sticker: %Q, maxentries: %d}}", &p_charbuf2, &p_charbuf3, &int_buf1); |                     je = json_scanf(request->data, request->length, "{data: {playlist: %Q, sticker: %Q, maxentries: %d}}", &p_charbuf2, &p_charbuf3, &int_buf1); | ||||||
|                     if (je == 3) { |                     if (je == 3) { | ||||||
|                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, p_charbuf3, NULL, int_buf1, 0); |                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, p_charbuf3, NULL, int_buf1, 0); | ||||||
|                         free(p_charbuf2); |                         free(p_charbuf2); | ||||||
| @@ -299,14 +289,14 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 else if (strcmp(p_charbuf1, "newest") == 0) { |                 else if (strcmp(p_charbuf1, "newest") == 0) { | ||||||
|                     je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q, timerange: %d}}", &p_charbuf2, &int_buf1); |                     je = json_scanf(request->data, request->length, "{data: {playlist: %Q, timerange: %d}}", &p_charbuf2, &int_buf1); | ||||||
|                     if (je == 2) { |                     if (je == 2) { | ||||||
|                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, NULL, NULL, 0, int_buf1); |                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, NULL, NULL, 0, int_buf1); | ||||||
|                         free(p_charbuf2); |                         free(p_charbuf2); | ||||||
|                     } |                     } | ||||||
|                 }             |                 }             | ||||||
|                 else if (strcmp(p_charbuf1, "search") == 0) { |                 else if (strcmp(p_charbuf1, "search") == 0) { | ||||||
|                     je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q, tag: %Q, searchstr: %Q}}", &p_charbuf2, &p_charbuf3, &p_charbuf4); |                     je = json_scanf(request->data, request->length, "{data: {playlist: %Q, tag: %Q, searchstr: %Q}}", &p_charbuf2, &p_charbuf3, &p_charbuf4); | ||||||
|                     if (je == 3) { |                     if (je == 3) { | ||||||
|                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, p_charbuf3, p_charbuf4, 0, 0); |                         n = mympd_smartpls_save(p_charbuf1, p_charbuf2, p_charbuf3, p_charbuf4, 0, 0); | ||||||
|                         free(p_charbuf2); |                         free(p_charbuf2); | ||||||
| @@ -322,7 +312,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Saving playlist failed\"}"); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Saving playlist failed\"}"); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_SMARTPLS_GET: |         case MPD_API_SMARTPLS_GET: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {playlist: %Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {playlist: %Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 n = mympd_smartpls_put(mpd.buf, p_charbuf1); |                 n = mympd_smartpls_put(mpd.buf, p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -382,7 +372,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             n = mympd_queue_crop(mpd.buf); |             n = mympd_queue_crop(mpd.buf); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_RM_TRACK: |         case MPD_API_QUEUE_RM_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {track:%u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {track:%u}}", &uint_buf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_delete_id(mpd.conn, uint_buf1)) |                 if (mpd_run_delete_id(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -393,7 +383,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_RM_RANGE: |         case MPD_API_QUEUE_RM_RANGE: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {start: %u, end: %u}}", &uint_buf1, &uint_buf2); |             je = json_scanf(request->data, request->length, "{data: {start: %u, end: %u}}", &uint_buf1, &uint_buf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 if (mpd_run_delete_range(mpd.conn, uint_buf1, uint_buf2)) |                 if (mpd_run_delete_range(mpd.conn, uint_buf1, uint_buf2)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -404,7 +394,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_MOVE_TRACK: |         case MPD_API_QUEUE_MOVE_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {from: %u, to: %u}}", &uint_buf1, &uint_buf2); |             je = json_scanf(request->data, request->length, "{data: {from: %u, to: %u}}", &uint_buf1, &uint_buf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 uint_buf1--; |                 uint_buf1--; | ||||||
|                 uint_buf2--; |                 uint_buf2--; | ||||||
| @@ -419,7 +409,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_MOVE_TRACK: |         case MPD_API_PLAYLIST_MOVE_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {plist: %Q, from: %u, to: %u }}", &p_charbuf1, &uint_buf1, &uint_buf2); |             je = json_scanf(request->data, request->length, "{data: {plist: %Q, from: %u, to: %u }}", &p_charbuf1, &uint_buf1, &uint_buf2); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 uint_buf1--; |                 uint_buf1--; | ||||||
|                 uint_buf2--; |                 uint_buf2--; | ||||||
| @@ -437,7 +427,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYER_PLAY_TRACK: |         case MPD_API_PLAYER_PLAY_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: { track:%u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: { track:%u}}", &uint_buf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_play_id(mpd.conn, uint_buf1)) |                 if (mpd_run_play_id(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -451,7 +441,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             n = mympd_put_outputs(mpd.buf); |             n = mympd_put_outputs(mpd.buf); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYER_TOGGLE_OUTPUT: |         case MPD_API_PLAYER_TOGGLE_OUTPUT: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {output: %u, state: %u}}", &uint_buf1, &uint_buf2); |             je = json_scanf(request->data, request->length, "{data: {output: %u, state: %u}}", &uint_buf1, &uint_buf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 if (uint_buf2) { |                 if (uint_buf2) { | ||||||
|                     if (mpd_run_enable_output(mpd.conn, uint_buf1)) |                     if (mpd_run_enable_output(mpd.conn, uint_buf1)) | ||||||
| @@ -472,7 +462,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYER_VOLUME_SET: |         case MPD_API_PLAYER_VOLUME_SET: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {volume:%u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {volume:%u}}", &uint_buf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_set_volume(mpd.conn, uint_buf1)) |                 if (mpd_run_set_volume(mpd.conn, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -486,7 +476,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             n = mympd_put_volume(mpd.buf); |             n = mympd_put_volume(mpd.buf); | ||||||
|             break;             |             break;             | ||||||
|         case MPD_API_PLAYER_SEEK: |         case MPD_API_PLAYER_SEEK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {songid: %u, seek: %u}}", &uint_buf1, &uint_buf2); |             je = json_scanf(request->data, request->length, "{data: {songid: %u, seek: %u}}", &uint_buf1, &uint_buf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 if (mpd_run_seek_id(mpd.conn, uint_buf1, uint_buf2)) |                 if (mpd_run_seek_id(mpd.conn, uint_buf1, uint_buf2)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -497,13 +487,13 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_LIST: |         case MPD_API_QUEUE_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {offset: %u}}", &uint_buf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 n = mympd_put_queue(mpd.buf, uint_buf1, &mpd.queue_version, &mpd.queue_length); |                 n = mympd_put_queue(mpd.buf, uint_buf1, &mpd.queue_version, &mpd.queue_length); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_LAST_PLAYED: |         case MPD_API_QUEUE_LAST_PLAYED: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset: %u}}", &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {offset: %u}}", &uint_buf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 n = mympd_put_last_played_songs(mpd.buf, uint_buf1); |                 n = mympd_put_last_played_songs(mpd.buf, uint_buf1); | ||||||
|             } |             } | ||||||
| @@ -512,14 +502,14 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|                 n = mympd_put_current_song(mpd.buf); |                 n = mympd_put_current_song(mpd.buf); | ||||||
|             break; |             break; | ||||||
|         case MPD_API_DATABASE_SONGDETAILS: |         case MPD_API_DATABASE_SONGDETAILS: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: { uri: %Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: { uri: %Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 n = mympd_put_songdetails(mpd.buf, p_charbuf1); |                 n = mympd_put_songdetails(mpd.buf, p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
|             } |             } | ||||||
|             break;             |             break;             | ||||||
|         case MPD_API_DATABASE_TAG_LIST: |         case MPD_API_DATABASE_TAG_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {offset: %u, filter: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 n = mympd_put_db_tag(mpd.buf, uint_buf1, p_charbuf2, "", "", p_charbuf1); |                 n = mympd_put_db_tag(mpd.buf, uint_buf1, p_charbuf2, "", "", p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -527,7 +517,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_DATABASE_TAG_ALBUM_LIST: |         case MPD_API_DATABASE_TAG_ALBUM_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q, search: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2, &p_charbuf3); |             je = json_scanf(request->data, request->length, "{data: {offset: %u, filter: %Q, search: %Q, tag: %Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2, &p_charbuf3); | ||||||
|             if (je == 4) { |             if (je == 4) { | ||||||
|                 n = mympd_put_db_tag(mpd.buf, uint_buf1, "Album", p_charbuf3, p_charbuf2, p_charbuf1); |                 n = mympd_put_db_tag(mpd.buf, uint_buf1, "Album", p_charbuf3, p_charbuf2, p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -536,7 +526,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST: |         case MPD_API_DATABASE_TAG_ALBUM_TITLE_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {album: %Q, search: %Q, tag: %Q}}", &p_charbuf1, &p_charbuf2, &p_charbuf3); |             je = json_scanf(request->data, request->length, "{data: {album: %Q, search: %Q, tag: %Q}}", &p_charbuf1, &p_charbuf2, &p_charbuf3); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 n = mympd_put_songs_in_album(mpd.buf, p_charbuf1, p_charbuf2, p_charbuf3); |                 n = mympd_put_songs_in_album(mpd.buf, p_charbuf1, p_charbuf2, p_charbuf3); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -545,7 +535,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             }  |             }  | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_RENAME: |         case MPD_API_PLAYLIST_RENAME: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {from: %Q, to: %Q}}", &p_charbuf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {from: %Q, to: %Q}}", &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 //rename smart playlist |                 //rename smart playlist | ||||||
|                 char old_pl_file[400]; |                 char old_pl_file[400]; | ||||||
| @@ -583,14 +573,14 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break;             |             break;             | ||||||
|         case MPD_API_PLAYLIST_LIST: |         case MPD_API_PLAYLIST_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset: %u, filter: %Q}}", &uint_buf1, &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {offset: %u, filter: %Q}}", &uint_buf1, &p_charbuf1); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 n = mympd_put_playlists(mpd.buf, uint_buf1, p_charbuf1); |                 n = mympd_put_playlists(mpd.buf, uint_buf1, p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_CONTENT_LIST: |         case MPD_API_PLAYLIST_CONTENT_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri: %Q, offset:%u, filter:%Q}}", &p_charbuf1, &uint_buf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {uri: %Q, offset:%u, filter:%Q}}", &p_charbuf1, &uint_buf1, &p_charbuf2); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 n = mympd_put_playlist_list(mpd.buf, p_charbuf1, uint_buf1, p_charbuf2); |                 n = mympd_put_playlist_list(mpd.buf, p_charbuf1, uint_buf1, p_charbuf2); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -598,7 +588,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_ADD_TRACK: |         case MPD_API_PLAYLIST_ADD_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {plist:%Q, uri:%Q}}", &p_charbuf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {plist:%Q, uri:%Q}}", &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 if (mpd_run_playlist_add(mpd.conn, p_charbuf1, p_charbuf2)) |                 if (mpd_run_playlist_add(mpd.conn, p_charbuf1, p_charbuf2)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Added %s to playlist %s\"}", p_charbuf2, p_charbuf1); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"Added %s to playlist %s\"}", p_charbuf2, p_charbuf1); | ||||||
| @@ -611,7 +601,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_CLEAR: |         case MPD_API_PLAYLIST_CLEAR: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_playlist_clear(mpd.conn, p_charbuf1)) |                 if (mpd_run_playlist_clear(mpd.conn, p_charbuf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -623,7 +613,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_RM_TRACK: |         case MPD_API_PLAYLIST_RM_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q, track:%u}}", &p_charbuf1, &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q, track:%u}}", &p_charbuf1, &uint_buf1); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 if (mpd_run_playlist_delete(mpd.conn, p_charbuf1, uint_buf1)) |                 if (mpd_run_playlist_delete(mpd.conn, p_charbuf1, uint_buf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -635,7 +625,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_DATABASE_FILESYSTEM_LIST: |         case MPD_API_DATABASE_FILESYSTEM_LIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset:%u, filter:%Q, path:%Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {offset:%u, filter:%Q, path:%Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 n = mympd_put_browse(mpd.buf, p_charbuf2, uint_buf1, p_charbuf1); |                 n = mympd_put_browse(mpd.buf, p_charbuf2, uint_buf1, p_charbuf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -643,7 +633,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_ADD_TRACK_AFTER: |         case MPD_API_QUEUE_ADD_TRACK_AFTER: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q, to:%d}}", &p_charbuf1, &int_buf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q, to:%d}}", &p_charbuf1, &int_buf1); | ||||||
|             if (je == 2) { |             if (je == 2) { | ||||||
|                 int_rc = mpd_run_add_id_to(mpd.conn, p_charbuf1, int_buf1); |                 int_rc = mpd_run_add_id_to(mpd.conn, p_charbuf1, int_buf1); | ||||||
|                 if (int_rc > -1 )  |                 if (int_rc > -1 )  | ||||||
| @@ -656,7 +646,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_REPLACE_TRACK: |         case MPD_API_QUEUE_REPLACE_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q }}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q }}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (!mpd_run_clear(mpd.conn)) { |                 if (!mpd_run_clear(mpd.conn)) { | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Clearing queue failed.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Clearing queue failed.\"}"); | ||||||
| @@ -676,7 +666,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_ADD_TRACK: |         case MPD_API_QUEUE_ADD_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_add(mpd.conn, p_charbuf1)) |                 if (mpd_run_add(mpd.conn, p_charbuf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -688,7 +678,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_ADD_PLAY_TRACK: |         case MPD_API_QUEUE_ADD_PLAY_TRACK: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 int_buf1 = mpd_run_add_id(mpd.conn, p_charbuf1); |                 int_buf1 = mpd_run_add_id(mpd.conn, p_charbuf1); | ||||||
|                 if (int_buf1 != -1) { |                 if (int_buf1 != -1) { | ||||||
| @@ -707,7 +697,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_REPLACE_PLAYLIST: |         case MPD_API_QUEUE_REPLACE_PLAYLIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {plist:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {plist:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (!mpd_run_clear(mpd.conn)) { |                 if (!mpd_run_clear(mpd.conn)) { | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Clearing queue failed.\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"Clearing queue failed.\"}"); | ||||||
| @@ -727,7 +717,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_ADD_PLAYLIST: |         case MPD_API_QUEUE_ADD_PLAYLIST: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {plist:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {plist:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_load(mpd.conn, p_charbuf1)) |                 if (mpd_run_load(mpd.conn, p_charbuf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -739,7 +729,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_SAVE: |         case MPD_API_QUEUE_SAVE: | ||||||
|             je = json_scanf(msg.p, msg.len, "{ data: {plist:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{ data: {plist:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 if (mpd_run_save(mpd.conn, p_charbuf1)) |                 if (mpd_run_save(mpd.conn, p_charbuf1)) | ||||||
|                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"result\", \"data\": \"ok\"}"); | ||||||
| @@ -751,7 +741,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_QUEUE_SEARCH: |         case MPD_API_QUEUE_SEARCH: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {offset:%u, filter:%Q, searchstr:%Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); |             je = json_scanf(request->data, request->length, "{data: {offset:%u, filter:%Q, searchstr:%Q}}", &uint_buf1, &p_charbuf1, &p_charbuf2); | ||||||
|             if (je == 3) { |             if (je == 3) { | ||||||
|                 n = mympd_search_queue(mpd.buf, p_charbuf1, uint_buf1, p_charbuf2); |                 n = mympd_search_queue(mpd.buf, p_charbuf1, uint_buf1, p_charbuf2); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -759,7 +749,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break;             |             break;             | ||||||
|         case MPD_API_DATABASE_SEARCH: |         case MPD_API_DATABASE_SEARCH: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {searchstr:%Q, filter:%Q, plist:%Q, offset:%u}}", &p_charbuf1, &p_charbuf2, &p_charbuf3, &uint_buf1); |             je = json_scanf(request->data, request->length, "{data: {searchstr:%Q, filter:%Q, plist:%Q, offset:%u}}", &p_charbuf1, &p_charbuf2, &p_charbuf3, &uint_buf1); | ||||||
|             if (je == 4) { |             if (je == 4) { | ||||||
|                 n = mympd_search(mpd.buf, p_charbuf1, p_charbuf2, p_charbuf3, uint_buf1); |                 n = mympd_search(mpd.buf, p_charbuf1, p_charbuf2, p_charbuf3, uint_buf1); | ||||||
|                 free(p_charbuf1); |                 free(p_charbuf1); | ||||||
| @@ -767,7 +757,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_DATABASE_SEARCH_ADV: |         case MPD_API_DATABASE_SEARCH_ADV: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {expression:%Q, sort:%Q, sortdesc:%B, plist:%Q, offset:%u}}",  |             je = json_scanf(request->data, request->length, "{data: {expression:%Q, sort:%Q, sortdesc:%B, plist:%Q, offset:%u}}",  | ||||||
|                 &p_charbuf1, &p_charbuf2, &bool_buf, &p_charbuf3, &uint_buf1); |                 &p_charbuf1, &p_charbuf2, &bool_buf, &p_charbuf3, &uint_buf1); | ||||||
|             if (je == 5) { |             if (je == 5) { | ||||||
|                 n = mympd_search_adv(mpd.buf, p_charbuf1, p_charbuf2, bool_buf, NULL, p_charbuf3, uint_buf1); |                 n = mympd_search_adv(mpd.buf, p_charbuf1, p_charbuf2, bool_buf, NULL, p_charbuf3, uint_buf1); | ||||||
| @@ -785,7 +775,7 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case MPD_API_PLAYLIST_RM: |         case MPD_API_PLAYLIST_RM: | ||||||
|             je = json_scanf(msg.p, msg.len, "{data: {uri:%Q}}", &p_charbuf1); |             je = json_scanf(request->data, request->length, "{data: {uri:%Q}}", &p_charbuf1); | ||||||
|             if (je == 1) { |             if (je == 1) { | ||||||
|                 //remove smart playlist |                 //remove smart playlist | ||||||
|                 char pl_file[400]; |                 char pl_file[400]; | ||||||
| @@ -833,33 +823,31 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|     fprintf(stderr, "DEBUG: Time used: %lu\n", delta_us); |     fprintf(stderr, "DEBUG: Time used: %lu\n", delta_us); | ||||||
|     #endif |     #endif | ||||||
|  |  | ||||||
|     if (n == 0) |     if (n == 0) { | ||||||
|         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"No response for cmd %s\"}", cmd); |         n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"No response for cmd %s.\"}", cmd); | ||||||
|  |     } | ||||||
|  |     LOG_DEBUG() fprintf(stderr, "DEBUG: Send http response to connection %lu (first 800 chars):\n%*.*s\n", request->conn_id, 0, 800, mpd.buf); | ||||||
|  |  | ||||||
|  |     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, mpd.buf, MAX_SIZE, n); | ||||||
|  |     tiny_queue_push(web_server_queue, response); | ||||||
|  |  | ||||||
|     if (is_websocket(nc)) { |  | ||||||
|         LOG_DEBUG() fprintf(stderr, "DEBUG: Send websocket response:\n %s\n", mpd.buf); |  | ||||||
|         mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, mpd.buf, n); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         LOG_DEBUG() fprintf(stderr, "DEBUG: Send http response (first 800 chars):\n%*.*s\n", 0, 800, mpd.buf); |  | ||||||
|         mg_send_http_chunk(nc, mpd.buf, n); |  | ||||||
|     } |  | ||||||
|     free(cmd); |     free(cmd); | ||||||
|     LOG_DEBUG() fprintf(stderr, "DEBUG: Entering mpd idle mode\n"); |     free(request); | ||||||
|     mpd_send_idle(mpd.conn); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void mympd_notify(struct mg_mgr *s) { | void mympd_notify(size_t len) { | ||||||
|     for (struct mg_connection *c = mg_next(s, NULL); c != NULL; c = mg_next(s, c)) { |     LOG_DEBUG() fprintf(stderr, "DEBUG: Websocket notify: %s.\n", mpd.buf); | ||||||
|         if (!is_websocket(c)) |      | ||||||
|             continue; |     struct work_result_t *response = (struct work_result_t*)malloc(sizeof(struct work_result_t)); | ||||||
|         mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, mpd.buf, strlen(mpd.buf)); |     response->conn_id = 0; | ||||||
|     } |     response->length = copy_string(response->data, mpd.buf, MAX_SIZE, len); | ||||||
|     LOG_DEBUG() fprintf(stderr, "DEBUG: Websocket notify: %s\n", mpd.buf); |     tiny_queue_push(web_server_queue, response); | ||||||
| } | } | ||||||
|  |  | ||||||
| void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask) { | void mympd_parse_idle(int idle_bitmask) { | ||||||
|     int len = 0; |     size_t n = 0; | ||||||
|     for (unsigned j = 0;; j++) { |     for (unsigned j = 0;; j++) { | ||||||
|         enum mpd_idle idle_event = 1 << j; |         enum mpd_idle idle_event = 1 << j; | ||||||
|         const char *idle_name = mpd_idle_name(idle_event); |         const char *idle_name = mpd_idle_name(idle_event); | ||||||
| @@ -869,19 +857,19 @@ void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask) { | |||||||
|             LOG_VERBOSE() printf("MPD idle event: %s\n", idle_name); |             LOG_VERBOSE() printf("MPD idle event: %s\n", idle_name); | ||||||
|             switch(idle_event) { |             switch(idle_event) { | ||||||
|                 case MPD_IDLE_DATABASE: |                 case MPD_IDLE_DATABASE: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_database\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_database\"}"); | ||||||
|                     mympd_smartpls_update_all(); |                     mympd_smartpls_update_all(); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_STORED_PLAYLIST: |                 case MPD_IDLE_STORED_PLAYLIST: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_stored_playlist\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_stored_playlist\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_QUEUE: |                 case MPD_IDLE_QUEUE: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_queue\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_queue\"}"); | ||||||
|                     if (mympd_state.jukeboxMode > 0) |                     if (mympd_state.jukeboxMode > 0) | ||||||
|                         mympd_jukebox(); |                         mympd_jukebox(); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_PLAYER: |                 case MPD_IDLE_PLAYER: | ||||||
|                     len = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length); |                     n = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length); | ||||||
|                     if (mpd.song_id != mpd.last_song_id) { |                     if (mpd.song_id != mpd.last_song_id) { | ||||||
|                         if (mpd.last_last_played_id != mpd.song_id) |                         if (mpd.last_last_played_id != mpd.song_id) | ||||||
|                             mympd_last_played_list(mpd.song_id); |                             mympd_last_played_list(mpd.song_id); | ||||||
| @@ -893,31 +881,32 @@ void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask) { | |||||||
|                     } |                     } | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_MIXER: |                 case MPD_IDLE_MIXER: | ||||||
|                     len = mympd_put_volume(mpd.buf); |                     n = mympd_put_volume(mpd.buf); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_OUTPUT: |                 case MPD_IDLE_OUTPUT: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_outputs\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_outputs\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_OPTIONS: |                 case MPD_IDLE_OPTIONS: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_options\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_options\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_UPDATE: |                 case MPD_IDLE_UPDATE: | ||||||
|                     len = mympd_get_updatedb_state(mpd.buf); |                     n = mympd_get_updatedb_state(mpd.buf); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_STICKER: |                 case MPD_IDLE_STICKER: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_sticker\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_sticker\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_SUBSCRIPTION: |                 case MPD_IDLE_SUBSCRIPTION: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_subscription\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_subscription\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_MESSAGE: |                 case MPD_IDLE_MESSAGE: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_message\"}"); |                     n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_message\"}"); | ||||||
|                     break; |                     break; | ||||||
|                 default: |                 default: | ||||||
|                     len = 0; |                     n = 0; | ||||||
|  |             } | ||||||
|  |             if (n > 0) { | ||||||
|  |                 mympd_notify(n); | ||||||
|             } |             } | ||||||
|             if (len > 0) |  | ||||||
|                 mympd_notify(s); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -1039,15 +1028,16 @@ void mympd_mpd_features() { | |||||||
|      |      | ||||||
|     if (LIBMPDCLIENT_CHECK_VERSION(2, 17, 0) && mpd_connection_cmp_server_version(mpd.conn, 0, 21, 0) >= 0) { |     if (LIBMPDCLIENT_CHECK_VERSION(2, 17, 0) && mpd_connection_cmp_server_version(mpd.conn, 0, 21, 0) >= 0) { | ||||||
|         mpd.feat_advsearch = true; |         mpd.feat_advsearch = true; | ||||||
|         LOG_INFO() printf("Enabling advanced search\n"); |         LOG_INFO() printf("Enabling advanced search.\n"); | ||||||
|     }  |     }  | ||||||
|     else  |     else  | ||||||
|         LOG_INFO() printf("Disabling advanced search, depends on mpd >= 0.21.0 and libmpdclient >= 2.17.0\n"); |         LOG_INFO() printf("Disabling advanced search, depends on mpd >= 0.21.0 and libmpdclient >= 2.17.0.\n"); | ||||||
| } | } | ||||||
|  |  | ||||||
| void mympd_idle(struct mg_mgr *s, int timeout) { | void mympd_idle(int timeout) { | ||||||
|     struct pollfd fds[1]; |     struct pollfd fds[1]; | ||||||
|     int pollrc; |     int pollrc; | ||||||
|  |     size_t n = 0; | ||||||
|      |      | ||||||
|     switch (mpd.conn_state) { |     switch (mpd.conn_state) { | ||||||
|         case MPD_DISCONNECTED: |         case MPD_DISCONNECTED: | ||||||
| @@ -1056,24 +1046,24 @@ void mympd_idle(struct mg_mgr *s, int timeout) { | |||||||
|             mpd.conn = mpd_connection_new(config.mpdhost, config.mpdport, mpd.timeout); |             mpd.conn = mpd_connection_new(config.mpdhost, config.mpdport, mpd.timeout); | ||||||
|             if (mpd.conn == NULL) { |             if (mpd.conn == NULL) { | ||||||
|                 printf("MPD connection failed."); |                 printf("MPD connection failed."); | ||||||
|                 snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"disconnected\"}"); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"disconnected\"}"); | ||||||
|                 mympd_notify(s); |                 mympd_notify(n); | ||||||
|                 mpd.conn_state = MPD_FAILURE; |                 mpd.conn_state = MPD_FAILURE; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { |             if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS) { | ||||||
|                 printf("MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); |                 printf("MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); | ||||||
|                 snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); | ||||||
|                 mympd_notify(s); |                 mympd_notify(n); | ||||||
|                 mpd.conn_state = MPD_FAILURE; |                 mpd.conn_state = MPD_FAILURE; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (config.mpdpass && !mpd_run_password(mpd.conn, config.mpdpass)) { |             if (config.mpdpass && !mpd_run_password(mpd.conn, config.mpdpass)) { | ||||||
|                 printf("MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); |                 printf("MPD connection: %s\n", mpd_connection_get_error_message(mpd.conn)); | ||||||
|                 snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); |                 n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"error\", \"data\": \"%s\"}", mpd_connection_get_error_message(mpd.conn)); | ||||||
|                 mympd_notify(s); |                 mympd_notify(n); | ||||||
|                 mpd.conn_state = MPD_FAILURE; |                 mpd.conn_state = MPD_FAILURE; | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
| @@ -1090,8 +1080,8 @@ void mympd_idle(struct mg_mgr *s, int timeout) { | |||||||
|  |  | ||||||
|         case MPD_FAILURE: |         case MPD_FAILURE: | ||||||
|             printf("MPD connection failed.\n"); |             printf("MPD connection failed.\n"); | ||||||
|             snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"disconnected\"}"); |             n = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"disconnected\"}"); | ||||||
|             mympd_notify(s); |             mympd_notify(n); | ||||||
|  |  | ||||||
|         case MPD_DISCONNECT: |         case MPD_DISCONNECT: | ||||||
|         case MPD_RECONNECT: |         case MPD_RECONNECT: | ||||||
| @@ -1105,25 +1095,26 @@ void mympd_idle(struct mg_mgr *s, int timeout) { | |||||||
|             fds[0].fd = mpd_connection_get_fd(mpd.conn); |             fds[0].fd = mpd_connection_get_fd(mpd.conn); | ||||||
|             fds[0].events = POLLIN; |             fds[0].events = POLLIN; | ||||||
|             pollrc = poll(fds, 1, timeout); |             pollrc = poll(fds, 1, timeout); | ||||||
|             if (pollrc > 0 || idle_bitmask_save > 0) { |             unsigned mpd_client_queue_length = tiny_queue_length(mpd_client_queue); | ||||||
|                 //Handle idle event |             if (pollrc > 0 || mpd_client_queue_length > 0) { | ||||||
|                 LOG_DEBUG() fprintf(stderr, "DEBUG: Leaving mpd idle mode\n"); |                 LOG_DEBUG() fprintf(stderr, "DEBUG: Leaving mpd idle mode.\n"); | ||||||
|                 mpd_send_noidle(mpd.conn); |                 mpd_send_noidle(mpd.conn); | ||||||
|                 if (pollrc > 0) { |                 if (pollrc > 0) { | ||||||
|                     LOG_DEBUG() fprintf(stderr, "DEBUG: Checking for idle events\n"); |                     //Handle idle events | ||||||
|  |                     LOG_DEBUG() fprintf(stderr, "DEBUG: Checking for idle events.\n"); | ||||||
|                     enum mpd_idle idle_bitmask = mpd_recv_idle(mpd.conn, false); |                     enum mpd_idle idle_bitmask = mpd_recv_idle(mpd.conn, false); | ||||||
|                     mympd_parse_idle(s, idle_bitmask); |                     mympd_parse_idle(idle_bitmask); | ||||||
|                 }  |                 }  | ||||||
|                 else { |                 else { | ||||||
|                     mpd_response_finish(mpd.conn); |                     mpd_response_finish(mpd.conn); | ||||||
|                 } |                 } | ||||||
|                 if (idle_bitmask_save > 0) { |                 if (mpd_client_queue_length > 0) { | ||||||
|                     //Handle idle event saved in mympd_callback |                     //Handle request | ||||||
|                     LOG_DEBUG() fprintf(stderr, "DEBUG: Handle saved idle event\n"); |                     LOG_DEBUG() fprintf(stderr, "DEBUG: Handle request.\n"); | ||||||
|                     mympd_parse_idle(s, idle_bitmask_save); |                     struct work_request_t *req = tiny_queue_shift(mpd_client_queue); | ||||||
|                     idle_bitmask_save = 0; |                     mympd_api(req); | ||||||
|                 } |                 } | ||||||
|                 LOG_DEBUG() fprintf(stderr, "DEBUG: Entering mpd idle mode\n"); |                 LOG_DEBUG() fprintf(stderr, "DEBUG: Entering mpd idle mode.\n"); | ||||||
|                 mpd_send_idle(mpd.conn); |                 mpd_send_idle(mpd.conn); | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| @@ -2647,7 +2638,7 @@ int mympd_put_stats(char *buffer) { | |||||||
|  |  | ||||||
| void mympd_disconnect() { | void mympd_disconnect() { | ||||||
|     mpd.conn_state = MPD_DISCONNECT; |     mpd.conn_state = MPD_DISCONNECT; | ||||||
|     mympd_idle(NULL, 0); |     mympd_idle(100); | ||||||
| } | } | ||||||
|  |  | ||||||
| int mympd_smartpls_put(char *buffer, char *playlist) { | int mympd_smartpls_put(char *buffer, char *playlist) { | ||||||
|   | |||||||
| @@ -26,7 +26,10 @@ | |||||||
| #define __MPD_CLIENT_H__ | #define __MPD_CLIENT_H__ | ||||||
|  |  | ||||||
| #include "../dist/src/mongoose/mongoose.h" | #include "../dist/src/mongoose/mongoose.h" | ||||||
|  | #include "common.h" | ||||||
|  | #include "web_server.h" | ||||||
| #include "list.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)); \ | ||||||
| @@ -65,13 +68,6 @@ | |||||||
| } while (0) | } while (0) | ||||||
|  |  | ||||||
|  |  | ||||||
| #define LOG_INFO() if (config.loglevel >= 1)  |  | ||||||
| #define LOG_VERBOSE() if (config.loglevel >= 2)  |  | ||||||
| #define LOG_DEBUG() if (config.loglevel == 3)  |  | ||||||
|  |  | ||||||
| #define MAX_SIZE 2048 * 400 |  | ||||||
| #define MAX_ELEMENTS_PER_PAGE 400 |  | ||||||
|  |  | ||||||
| #define GEN_ENUM(X) X, | #define GEN_ENUM(X) X, | ||||||
| #define GEN_STR(X) #X, | #define GEN_STR(X) #X, | ||||||
| #define MPD_CMDS(X) \ | #define MPD_CMDS(X) \ | ||||||
| @@ -153,7 +149,6 @@ struct t_mpd { | |||||||
|  |  | ||||||
|     // Reponse Buffer |     // Reponse Buffer | ||||||
|     char buf[MAX_SIZE]; |     char buf[MAX_SIZE]; | ||||||
|     size_t buf_size; |  | ||||||
|  |  | ||||||
|     // States |     // States | ||||||
|     int song_id; |     int song_id; | ||||||
| @@ -181,38 +176,6 @@ struct list mympd_browsetags; | |||||||
| struct list last_played; | struct list last_played; | ||||||
| struct list syscmds; | struct list syscmds; | ||||||
|  |  | ||||||
| typedef struct { |  | ||||||
|     long mpdport; |  | ||||||
|     const char *mpdhost; |  | ||||||
|     const char *mpdpass; |  | ||||||
|     const char *webport; |  | ||||||
|     bool ssl; |  | ||||||
|     const char *sslport; |  | ||||||
|     const char *sslcert; |  | ||||||
|     const char *sslkey; |  | ||||||
|     const char *user; |  | ||||||
|     bool coverimage; |  | ||||||
|     const char *coverimagename; |  | ||||||
|     long coverimagesize; |  | ||||||
|     bool stickers; |  | ||||||
|     bool mixramp; |  | ||||||
|     const char *taglist; |  | ||||||
|     const char *searchtaglist; |  | ||||||
|     const char *browsetaglist; |  | ||||||
|     bool smartpls; |  | ||||||
|     const char *varlibdir; |  | ||||||
|     const char *etcdir; |  | ||||||
|     unsigned long max_elements_per_page; |  | ||||||
|     bool syscmds; |  | ||||||
|     bool localplayer; |  | ||||||
|     long streamport; |  | ||||||
|     const char *streamurl; |  | ||||||
|     unsigned long last_played_count; |  | ||||||
|     long loglevel; |  | ||||||
| } t_config; |  | ||||||
|  |  | ||||||
| t_config config; |  | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     long playCount; |     long playCount; | ||||||
|     long skipCount; |     long skipCount; | ||||||
| @@ -236,16 +199,13 @@ typedef struct { | |||||||
| } t_mympd_state; | } t_mympd_state; | ||||||
|  |  | ||||||
| t_mympd_state mympd_state; | t_mympd_state mympd_state; | ||||||
|  | tiny_queue_t *mpd_client_queue; | ||||||
| static int is_websocket(const struct mg_connection *nc) { |  | ||||||
|     return nc->flags & MG_F_IS_WEBSOCKET; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int randrange(int n); | int randrange(int n); | ||||||
| void mympd_idle(struct mg_mgr *sm, int timeout); | void mympd_idle(int timeout); | ||||||
| void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask); | void mympd_parse_idle(int idle_bitmask); | ||||||
| void callback_mympd(struct mg_connection *nc, const struct mg_str msg); | void mympd_api(struct work_request_t *request); | ||||||
| void mympd_notify(struct mg_mgr *s); | void mympd_notify(size_t n); | ||||||
| bool mympd_count_song_id(int song_id, char *name, int value); | bool mympd_count_song_id(int song_id, char *name, int value); | ||||||
| bool mympd_count_song_uri(const char *uri, char *name, int value); | bool mympd_count_song_uri(const char *uri, char *name, int value); | ||||||
| bool mympd_like_song_uri(const char *uri, int value); | bool mympd_like_song_uri(const char *uri, int value); | ||||||
|   | |||||||
							
								
								
									
										130
									
								
								src/mympd.c
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								src/mympd.c
									
									
									
									
									
								
							| @@ -30,97 +30,23 @@ | |||||||
| #include <pwd.h> | #include <pwd.h> | ||||||
| #include <grp.h> | #include <grp.h> | ||||||
| #include <libgen.h> | #include <libgen.h> | ||||||
|  | #include <pthread.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" |  | ||||||
| #include "../dist/src/inih/ini.h" | #include "../dist/src/inih/ini.h" | ||||||
|  | #include "common.h" | ||||||
| #include "mpd_client.h" | #include "mpd_client.h" | ||||||
|  | #include "web_server.h" | ||||||
| #include "config.h" | #include "config.h" | ||||||
|  |  | ||||||
| static sig_atomic_t s_signal_received = 0; | static sig_atomic_t s_signal_received = 0; | ||||||
| static struct mg_serve_http_opts s_http_server_opts; |  | ||||||
|  |  | ||||||
|  |  | ||||||
| static void signal_handler(int sig_num) { | static void signal_handler(int sig_num) { | ||||||
|     signal(sig_num, signal_handler);  // Reinstantiate signal handler |     signal(sig_num, signal_handler);  // Reinstantiate signal handler | ||||||
|     s_signal_received = sig_num; |     s_signal_received = sig_num; | ||||||
| } | } | ||||||
|  |  | ||||||
| static void handle_api(struct mg_connection *nc, struct http_message *hm) { |  | ||||||
|     if (!is_websocket(nc)) |  | ||||||
|         mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nContent-Type: application/json\r\n\r\n"); |  | ||||||
|  |  | ||||||
|     char buf[1000] = {0}; |  | ||||||
|     int len = sizeof(buf) - 1 < hm->body.len ? sizeof(buf) - 1 : hm->body.len; |  | ||||||
|     memcpy(buf, hm->body.p, len); |  | ||||||
|     struct mg_str d = {buf, len}; |  | ||||||
|     callback_mympd(nc, d); |  | ||||||
|  |  | ||||||
|     if (!is_websocket(nc)) |  | ||||||
|         mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */ |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { |  | ||||||
|     switch(ev) { |  | ||||||
|         case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: { |  | ||||||
|             struct http_message *hm = (struct http_message *) ev_data; |  | ||||||
|             LOG_VERBOSE() printf("New websocket request: %.*s\n", hm->uri.len, hm->uri.p); |  | ||||||
|             if (mg_vcmp(&hm->uri, "/ws") != 0) { |  | ||||||
|                 printf("ERROR: Websocket request not to /ws, closing connection\n"); |  | ||||||
|                 mg_printf(nc, "%s", "HTTP/1.1 403 FORBIDDEN\r\n\r\n"); |  | ||||||
|                 nc->flags |= MG_F_SEND_AND_CLOSE; |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { |  | ||||||
|              LOG_VERBOSE() printf("New Websocket connection established\n"); |  | ||||||
|              struct mg_str d = mg_mk_str("{\"cmd\":\"MPD_API_WELCOME\"}"); |  | ||||||
|              callback_mympd(nc, d); |  | ||||||
|              break; |  | ||||||
|         } |  | ||||||
|         case MG_EV_HTTP_REQUEST: { |  | ||||||
|             struct http_message *hm = (struct http_message *) ev_data; |  | ||||||
|             LOG_VERBOSE() printf("HTTP request: %.*s\n", hm->uri.len, hm->uri.p); |  | ||||||
|             if (mg_vcmp(&hm->uri, "/api") == 0) |  | ||||||
|                 handle_api(nc, hm); |  | ||||||
|             else |  | ||||||
|                 mg_serve_http(nc, hm, s_http_server_opts); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case MG_EV_CLOSE: { |  | ||||||
|             if (is_websocket(nc)) { |  | ||||||
|               LOG_VERBOSE() printf("Websocket connection closed\n"); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|               LOG_VERBOSE() printf("HTTP connection closed\n"); |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         }         |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void ev_handler_http(struct mg_connection *nc_http, int ev, void *ev_data) { |  | ||||||
|     char *host; |  | ||||||
|     char host_header[1024]; |  | ||||||
|     switch(ev) { |  | ||||||
|         case MG_EV_HTTP_REQUEST: { |  | ||||||
|             struct http_message *hm = (struct http_message *) ev_data; |  | ||||||
|             struct mg_str *host_hdr = mg_get_http_header(hm, "Host"); |  | ||||||
|             snprintf(host_header, 1024, "%.*s", host_hdr->len, host_hdr->p); |  | ||||||
|             host = strtok(host_header, ":"); |  | ||||||
|             char s_redirect[250]; |  | ||||||
|             if (strcmp(config.sslport, "443") == 0) |  | ||||||
|                 snprintf(s_redirect, 250, "https://%s/", host); |  | ||||||
|             else |  | ||||||
|                 snprintf(s_redirect, 250, "https://%s:%s/", host, config.sslport); |  | ||||||
|             LOG_VERBOSE() printf("Redirecting to %s\n", s_redirect); |  | ||||||
|             mg_http_send_redirect(nc_http, 301, mg_mk_str(s_redirect), mg_mk_str(NULL)); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int inihandler(void* user, const char* section, const char* name, const char* value) { | static int inihandler(void* user, const char* section, const char* name, const char* value) { | ||||||
|     t_config* p_config = (t_config*)user; |     t_config* p_config = (t_config*)user; | ||||||
|     char *crap; |     char *crap; | ||||||
| @@ -373,6 +299,36 @@ bool testdir(char *name, char *dirname) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void *mpd_client_thread(void *arg) { | ||||||
|  |     struct mg_mgr *mgr = (struct mg_mgr *) arg; | ||||||
|  |     while (s_signal_received == 0) { | ||||||
|  |         mympd_idle(100); | ||||||
|  |     } | ||||||
|  |     mympd_disconnect(); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *web_server_thread(void *arg) { | ||||||
|  |     struct mg_mgr *mgr = (struct mg_mgr *) arg; | ||||||
|  |     while (s_signal_received == 0) { | ||||||
|  |         mg_mgr_poll(mgr, 10); | ||||||
|  |         unsigned web_server_queue_length = tiny_queue_length(web_server_queue); | ||||||
|  |         if (web_server_queue_length > 0) { | ||||||
|  |             struct work_result_t *response = tiny_queue_shift(web_server_queue); | ||||||
|  |             if (response->conn_id == 0) { | ||||||
|  |                 //Websocket notify from mpd idle | ||||||
|  |                 send_ws_notify(mgr, response); | ||||||
|  |             }  | ||||||
|  |             else { | ||||||
|  |                 //api response | ||||||
|  |                 send_api_response(mgr, response); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     mg_mgr_free(mgr); | ||||||
|  |     return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
|     struct mg_mgr mgr; |     struct mg_mgr mgr; | ||||||
|     struct mg_connection *nc; |     struct mg_connection *nc; | ||||||
| @@ -380,6 +336,8 @@ int main(int argc, char **argv) { | |||||||
|     struct mg_bind_opts bind_opts; |     struct mg_bind_opts bind_opts; | ||||||
|     const char *err; |     const char *err; | ||||||
|     char testdirname[400]; |     char testdirname[400]; | ||||||
|  |     mpd_client_queue = tiny_queue_create(); | ||||||
|  |     web_server_queue = tiny_queue_create(); | ||||||
|      |      | ||||||
|     //defaults |     //defaults | ||||||
|     config.mpdhost = "127.0.0.1"; |     config.mpdhost = "127.0.0.1"; | ||||||
| @@ -451,7 +409,7 @@ int main(int argc, char **argv) { | |||||||
|     mg_mgr_init(&mgr, NULL); |     mg_mgr_init(&mgr, NULL); | ||||||
|  |  | ||||||
|     if (config.ssl == true) { |     if (config.ssl == true) { | ||||||
|         nc_http = mg_bind(&mgr, config.webport, ev_handler_http); |         nc_http = mg_bind(&mgr, config.webport, ev_handler_redirect); | ||||||
|         if (nc_http == NULL) { |         if (nc_http == NULL) { | ||||||
|             printf("Error listening on port %s\n", config.webport); |             printf("Error listening on port %s\n", config.webport); | ||||||
|             return EXIT_FAILURE; |             return EXIT_FAILURE; | ||||||
| @@ -552,13 +510,25 @@ int main(int argc, char **argv) { | |||||||
|     if (config.ssl == true) |     if (config.ssl == true) | ||||||
|         LOG_INFO() printf("Listening on ssl port %s\n", config.sslport); |         LOG_INFO() printf("Listening on ssl port %s\n", config.sslport); | ||||||
|  |  | ||||||
|  |     pthread_t mpd_client, web_server; | ||||||
|  |     pthread_create(&mpd_client, NULL, mpd_client_thread, &mgr); | ||||||
|  |     pthread_create(&web_server, NULL, web_server_thread, &mgr); | ||||||
|  |  | ||||||
|  |     //Do nothing... | ||||||
|  |  | ||||||
|  |     pthread_join(mpd_client, NULL); | ||||||
|  |     pthread_join(web_server, NULL); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |     mg_start_thread(mpd_client_thread, &mgr); | ||||||
|  |  | ||||||
|     while (s_signal_received == 0) { |     while (s_signal_received == 0) { | ||||||
|         mg_mgr_poll(&mgr, 100); |         mg_mgr_poll(&mgr, 100); | ||||||
|         mympd_idle(&mgr, 0); |  | ||||||
|     } |     } | ||||||
|     mg_mgr_free(&mgr); |     mg_mgr_free(&mgr); | ||||||
|  | */ | ||||||
|  |  | ||||||
|     list_free(&mpd_tags); |     list_free(&mpd_tags); | ||||||
|     list_free(&mympd_tags); |     list_free(&mympd_tags); | ||||||
|     mympd_disconnect(); |  | ||||||
|     return EXIT_SUCCESS; |     return EXIT_SUCCESS; | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										80
									
								
								src/tiny_queue.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/tiny_queue.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | |||||||
|  | /* myMPD | ||||||
|  |    (c) 2018 Juergen Mang <mail@jcgames.de> | ||||||
|  |    This project's homepage is: https://github.com/jcorporation/mympd | ||||||
|  |     | ||||||
|  |    This linked list implementation is based on: https://github.com/joshkunz/ashuffle | ||||||
|  |     | ||||||
|  |    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 <stdlib.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <pthread.h> | ||||||
|  | #include "tiny_queue.h" | ||||||
|  |  | ||||||
|  | tiny_queue_t* tiny_queue_create() { | ||||||
|  |     struct tiny_queue_t* queue = (struct tiny_queue_t*)malloc(sizeof(struct tiny_queue_t)); | ||||||
|  |     queue->head = NULL; | ||||||
|  |     queue->tail = NULL; | ||||||
|  |     queue->length = 0; | ||||||
|  |  | ||||||
|  |     queue->mutex  = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER; | ||||||
|  |     queue->wakeup = (pthread_cond_t)PTHREAD_COND_INITIALIZER; | ||||||
|  |     return queue; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void tiny_queue_push(tiny_queue_t *queue, void *data) { | ||||||
|  |     pthread_mutex_lock(&queue->mutex); | ||||||
|  |     struct tiny_msg_t* new_node = (struct tiny_msg_t*)malloc(sizeof(struct tiny_msg_t)); | ||||||
|  |     new_node->data = data; | ||||||
|  |     new_node->next = NULL; | ||||||
|  |     queue->length++; | ||||||
|  |     if (queue->head == NULL && queue->tail == NULL){ | ||||||
|  |         queue->head = queue->tail = new_node; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         queue->tail->next = new_node; | ||||||
|  |         queue->tail = new_node; | ||||||
|  |     } | ||||||
|  |     pthread_mutex_unlock(&queue->mutex); | ||||||
|  |     pthread_cond_signal(&queue->wakeup); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int tiny_queue_length(tiny_queue_t *queue) { | ||||||
|  |     pthread_mutex_lock(&queue->mutex); | ||||||
|  |     unsigned len = queue->length; | ||||||
|  |     pthread_mutex_unlock(&queue->mutex); | ||||||
|  |     return len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void *tiny_queue_shift(tiny_queue_t *queue) { | ||||||
|  |     pthread_mutex_lock(&queue->mutex); | ||||||
|  |     while (queue->head == NULL) {  | ||||||
|  |         // block if buffer is empty | ||||||
|  |         pthread_cond_wait(&queue->wakeup, &queue->mutex); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     struct tiny_msg_t* current_head = queue->head; | ||||||
|  |     void *data = current_head->data; | ||||||
|  |     if (queue->head == queue->tail) { | ||||||
|  |         queue->head = queue->tail = NULL; | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |         queue->head = queue->head->next; | ||||||
|  |     } | ||||||
|  |     free(current_head); | ||||||
|  |     queue->length--; | ||||||
|  |     pthread_mutex_unlock(&queue->mutex); | ||||||
|  |     return data; | ||||||
|  | } | ||||||
| @@ -2,11 +2,7 @@ | |||||||
|    (c) 2018 Juergen Mang <mail@jcgames.de> |    (c) 2018 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
 | ||||||
|     |     | ||||||
|    myMPD ist fork of: |    This linked list implementation is based on: https://github.com/joshkunz/ashuffle
 | ||||||
|     |  | ||||||
|    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 |    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 |    it under the terms of the GNU General Public License as published by | ||||||
| @@ -21,6 +17,24 @@ | |||||||
|    with this program; if not, write to the Free Software Foundation, Inc., |    with this program; if not, write to the Free Software Foundation, Inc., | ||||||
|    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |    Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||||||
| */ | */ | ||||||
|  | #ifndef __TINY_QUEUE_H__ | ||||||
|  | #define __TINY_QUEUE_H__ | ||||||
| 
 | 
 | ||||||
| void sanitize_string(const char *data); | typedef struct tiny_msg_t { | ||||||
| int validate_path(char *path, const char *basepath); |     void *data; | ||||||
|  |     struct tiny_msg_t *next; | ||||||
|  | } tiny_msg_t; | ||||||
|  | 
 | ||||||
|  | typedef struct tiny_queue_t { | ||||||
|  |     unsigned length; | ||||||
|  |     struct tiny_msg_t *head; | ||||||
|  |     struct tiny_msg_t *tail; | ||||||
|  |     pthread_mutex_t mutex; | ||||||
|  |     pthread_cond_t wakeup; | ||||||
|  | } tiny_queue_t; | ||||||
|  | 
 | ||||||
|  | tiny_queue_t* tiny_queue_create(); | ||||||
|  | void tiny_queue_push(struct tiny_queue_t *queue, void *data); | ||||||
|  | void *tiny_queue_shift(struct tiny_queue_t *queue); | ||||||
|  | int tiny_queue_length(struct tiny_queue_t *queue); | ||||||
|  | #endif | ||||||
							
								
								
									
										144
									
								
								src/web_server.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/web_server.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | |||||||
|  | /* 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 "common.h" | ||||||
|  | #include "config.h" | ||||||
|  | #include "web_server.h" | ||||||
|  | #include "mpd_client.h" | ||||||
|  |  | ||||||
|  | static unsigned long s_next_id = 1; | ||||||
|  |  | ||||||
|  | int is_websocket(const struct mg_connection *nc) { | ||||||
|  |     return nc->flags & MG_F_IS_WEBSOCKET; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response) { | ||||||
|  |     struct mg_connection *c; | ||||||
|  |     LOG_DEBUG() fprintf(stderr, "DEBUG: Got ws notify, broadcasting\n"); | ||||||
|  |      | ||||||
|  |     for (c = mg_next(mgr, NULL); c != NULL; c = mg_next(mgr, c)) { | ||||||
|  |         if (!is_websocket(c)) | ||||||
|  |             continue; | ||||||
|  |         mg_send_websocket_frame(c, WEBSOCKET_OP_TEXT, response->data, response->length); | ||||||
|  |     } | ||||||
|  |     free(response); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void send_api_response(struct mg_mgr *mgr, struct work_result_t *response) { | ||||||
|  |     struct mg_connection *c; | ||||||
|  |     LOG_DEBUG() fprintf(stderr, "DEBUG: Got API response for connection %lu.\n", response->conn_id); | ||||||
|  |      | ||||||
|  |     for (c = mg_next(mgr, NULL); c != NULL; c = mg_next(mgr, c)) { | ||||||
|  |         if (c->user_data != NULL) { | ||||||
|  |             if ((unsigned long)c->user_data == response->conn_id) { | ||||||
|  |                 LOG_DEBUG() fprintf(stderr, "DEBUG: Sending to connection %lu: %s\n", (unsigned long)c->user_data, response->data); | ||||||
|  |                 mg_send_head(c, 200, response->length, "Content-Type: application/json"); | ||||||
|  |                 mg_printf(c, "%s", response->data); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     free(response); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ev_handler(struct mg_connection *nc, int ev, void *ev_data) { | ||||||
|  |     (void) nc; | ||||||
|  |     (void) ev_data; | ||||||
|  |      | ||||||
|  |     switch(ev) { | ||||||
|  |         case MG_EV_ACCEPT: { | ||||||
|  |             nc->user_data = (void *)++s_next_id; | ||||||
|  |             LOG_DEBUG() fprintf(stderr, "DEBUG: New connection id %lu.\n", s_next_id); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST: { | ||||||
|  |             struct http_message *hm = (struct http_message *) ev_data; | ||||||
|  |             LOG_VERBOSE() printf("New websocket request: %.*s\n", hm->uri.len, hm->uri.p); | ||||||
|  |             if (mg_vcmp(&hm->uri, "/ws") != 0) { | ||||||
|  |                 printf("ERROR: Websocket request not to /ws, closing connection\n"); | ||||||
|  |                 mg_printf(nc, "%s", "HTTP/1.1 403 FORBIDDEN\r\n\r\n"); | ||||||
|  |                 nc->flags |= MG_F_SEND_AND_CLOSE; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case MG_EV_WEBSOCKET_HANDSHAKE_DONE: { | ||||||
|  |              LOG_VERBOSE() printf("New Websocket connection established.\n"); | ||||||
|  |              char response[] = "{\"type\": \"welcome\", \"data\": {\"mympdVersion\": \"" MYMPD_VERSION "\"}}"; | ||||||
|  |              mg_send_websocket_frame(nc, WEBSOCKET_OP_TEXT, response, strlen(response)); | ||||||
|  |              break; | ||||||
|  |         } | ||||||
|  |         case MG_EV_HTTP_REQUEST: { | ||||||
|  |             struct http_message *hm = (struct http_message *) ev_data; | ||||||
|  |             LOG_VERBOSE() printf("HTTP request: %.*s\n", hm->uri.len, hm->uri.p); | ||||||
|  |             if (mg_vcmp(&hm->uri, "/api") == 0) { | ||||||
|  |                 struct work_request_t *request = (struct work_request_t*)malloc(sizeof(struct work_request_t)); | ||||||
|  |                 request->conn_id = (unsigned long)nc->user_data; | ||||||
|  |                 request->length = copy_string(request->data, hm->body.p, 1000, hm->body.len); | ||||||
|  |                 //sizeof(request->data) - 1 < hm->body.len ? sizeof(request->data) - 1 : hm->body.len; | ||||||
|  |                 //memcpy(request->data, hm->body.p, request->length); | ||||||
|  |                 tiny_queue_push(mpd_client_queue, request); | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 mg_serve_http(nc, hm, s_http_server_opts); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         case MG_EV_CLOSE: { | ||||||
|  |             if (nc->user_data) { | ||||||
|  |                 LOG_VERBOSE() fprintf(stderr, "HTTP connection %lu closed.\n", (unsigned long)nc->user_data); | ||||||
|  |                 nc->user_data = NULL; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 LOG_VERBOSE() printf("HTTP connection closed.\n"); | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         default: { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data) { | ||||||
|  |     char *host; | ||||||
|  |     char host_header[1024]; | ||||||
|  |     switch(ev) { | ||||||
|  |         case MG_EV_HTTP_REQUEST: { | ||||||
|  |             struct http_message *hm = (struct http_message *) ev_data; | ||||||
|  |             struct mg_str *host_hdr = mg_get_http_header(hm, "Host"); | ||||||
|  |             snprintf(host_header, 1024, "%.*s", host_hdr->len, host_hdr->p); | ||||||
|  |             host = strtok(host_header, ":"); | ||||||
|  |             char s_redirect[250]; | ||||||
|  |             if (strcmp(config.sslport, "443") == 0) | ||||||
|  |                 snprintf(s_redirect, 250, "https://%s/", host); | ||||||
|  |             else | ||||||
|  |                 snprintf(s_redirect, 250, "https://%s:%s/", host, config.sslport); | ||||||
|  |             LOG_VERBOSE() printf("Redirecting to %s\n", s_redirect); | ||||||
|  |             mg_http_send_redirect(nc_http, 301, mg_mk_str(s_redirect), mg_mk_str(NULL)); | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         default: { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										52
									
								
								src/web_server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/web_server.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | |||||||
|  | /* 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 __WEB_SERVER_H__ | ||||||
|  | #define __WEB_SERVER_H__ | ||||||
|  |  | ||||||
|  | #include "../dist/src/mongoose/mongoose.h" | ||||||
|  | #include "tiny_queue.h" | ||||||
|  |  | ||||||
|  | tiny_queue_t *web_server_queue; | ||||||
|  |  | ||||||
|  | struct work_request_t { | ||||||
|  |     unsigned 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 { | ||||||
|  |     unsigned long conn_id;  // needed to identify the connection where to send the reply | ||||||
|  |     char data[MAX_SIZE]; | ||||||
|  |     int length; | ||||||
|  | } work_result_t; | ||||||
|  |  | ||||||
|  | struct mg_serve_http_opts s_http_server_opts; | ||||||
|  |  | ||||||
|  | int is_websocket(const struct mg_connection *nc); | ||||||
|  | void ev_handler(struct mg_connection *nc, int ev, void *ev_data); | ||||||
|  | void ev_handler_redirect(struct mg_connection *nc_http, int ev, void *ev_data); | ||||||
|  | void send_ws_notify(struct mg_mgr *mgr, struct work_result_t *response); | ||||||
|  | void send_api_response(struct mg_mgr *mgr, struct work_result_t *response); | ||||||
|  | #endif | ||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation