mirror of
				https://github.com/SuperBFG7/ympd
				synced 2025-10-31 13:53:00 +00:00 
			
		
		
		
	Feat: jukebox mode #37
This commit is contained in:
		| @@ -709,6 +709,13 @@ | |||||||
|               <div class="invalid-feedback">Must be a number.</div> |               <div class="invalid-feedback">Must be a number.</div> | ||||||
|             </div>             |             </div>             | ||||||
|           </div> |           </div> | ||||||
|  |           <div class="row"> | ||||||
|  |             <div class="form-group col-md-6" data-toggle="buttons"> | ||||||
|  |               <button data-href='{"cmd": "toggleBtn", "options": ["btnJukebox"]}' id="btnJukebox" type="button" class="btn btn-secondary btn-block" title="Jukebox"> | ||||||
|  |                 Jukebox | ||||||
|  |               </button> | ||||||
|  |             </div> | ||||||
|  |           </div> | ||||||
|           <hr/> |           <hr/> | ||||||
|           <div class="row"> |           <div class="row"> | ||||||
|             <div class="form-group col-md-6" data-toggle="buttons"> |             <div class="form-group col-md-6" data-toggle="buttons"> | ||||||
|   | |||||||
| @@ -57,7 +57,6 @@ void callback_mympd(struct mg_connection *nc, const struct mg_str msg) { | |||||||
|     int je, int_buf, int_rc;  |     int je, int_buf, int_rc;  | ||||||
|     float float_buf; |     float float_buf; | ||||||
|     char *p_charbuf1, *p_charbuf2, *p_charbuf3; |     char *p_charbuf1, *p_charbuf2, *p_charbuf3; | ||||||
|     struct mympd_state { int a; int b; } state = { .a = 0, .b = 1 }; |  | ||||||
|     enum mpd_cmd_ids cmd_id; |     enum mpd_cmd_ids cmd_id; | ||||||
|     struct pollfd fds[1]; |     struct pollfd fds[1]; | ||||||
|     int pollrc; |     int pollrc; | ||||||
| @@ -113,11 +112,17 @@ 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: %d, notificationPage: %d}}", &state.a, &state.b); |             je = json_scanf(msg.p, msg.len, "{data: {notificationWeb: %B, notificationPage: %B, jukeboxMode: %B}}",  | ||||||
|             if (je == 2) { |                 &mympd_state.notificationWeb,  | ||||||
|  |                 &mympd_state.notificationPage, | ||||||
|  |                 &mympd_state.jukeboxMode); | ||||||
|  |             if (je == 3) { | ||||||
|                 char tmp_file[200]; |                 char tmp_file[200]; | ||||||
|                 snprintf(tmp_file, 200, "%s.tmp", config.statefile); |                 snprintf(tmp_file, 200, "%s.tmp", config.statefile); | ||||||
|                 json_fprintf(tmp_file, "{notificationWeb: %d, notificationPage: %d}", state.a, state.b); |                 json_fprintf(tmp_file, "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %B}",  | ||||||
|  |                     mympd_state.notificationWeb, | ||||||
|  |                     mympd_state.notificationPage, | ||||||
|  |                     mympd_state.jukeboxMode); | ||||||
|                 rename(tmp_file, config.statefile); |                 rename(tmp_file, config.statefile); | ||||||
|             } |             } | ||||||
|              |              | ||||||
| @@ -541,6 +546,8 @@ void mympd_parse_idle(struct mg_mgr *s, int idle_bitmask) { | |||||||
|                     break; |                     break; | ||||||
|                 case MPD_IDLE_QUEUE: |                 case MPD_IDLE_QUEUE: | ||||||
|                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_queue\"}"); |                     len = snprintf(mpd.buf, MAX_SIZE, "{\"type\": \"update_queue\"}"); | ||||||
|  |                     if (mympd_state.jukeboxMode == true) | ||||||
|  |                         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); |                     len = mympd_put_state(mpd.buf, &mpd.song_id, &mpd.next_song_id, &mpd.last_song_id, &mpd.queue_version, &mpd.queue_length); | ||||||
| @@ -720,6 +727,8 @@ void mympd_idle(struct mg_mgr *s, int timeout) { | |||||||
|             mpd_connection_set_timeout(mpd.conn, mpd.timeout); |             mpd_connection_set_timeout(mpd.conn, mpd.timeout); | ||||||
|             mpd.conn_state = MPD_CONNECTED; |             mpd.conn_state = MPD_CONNECTED; | ||||||
|             mympd_mpd_features(); |             mympd_mpd_features(); | ||||||
|  |             if (mympd_state.jukeboxMode == true) | ||||||
|  |                         mympd_jukebox(); | ||||||
|             mpd_send_idle(mpd.conn); |             mpd_send_idle(mpd.conn); | ||||||
|             break; |             break; | ||||||
|  |  | ||||||
| @@ -908,6 +917,51 @@ char* mympd_get_tag(struct mpd_song const *song, enum mpd_tag_type tag) { | |||||||
|     return str; |     return str; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void mympd_jukebox() { | ||||||
|  |     struct mpd_status *status; | ||||||
|  |     status = mpd_run_status(mpd.conn); | ||||||
|  |     int queue_length, num_songs, rand_song, i; | ||||||
|  |     struct mpd_entity *entity; | ||||||
|  |     const struct mpd_song *song; | ||||||
|  |      | ||||||
|  |     if (!status) { | ||||||
|  |         printf("MPD mpd_run_status: %s\n", mpd_connection_get_error_message(mpd.conn)); | ||||||
|  |         mpd.conn_state = MPD_FAILURE; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     queue_length = mpd_status_get_queue_length(status); | ||||||
|  |     mpd_status_free(status); | ||||||
|  |     if (queue_length > 0) | ||||||
|  |         return; | ||||||
|  |      | ||||||
|  |     struct mpd_stats *stats = mpd_run_stats(mpd.conn); | ||||||
|  |     num_songs = mpd_stats_get_number_of_songs(stats); | ||||||
|  |     mpd_stats_free(stats); | ||||||
|  |     num_songs--; | ||||||
|  |     if (num_songs > 0) { | ||||||
|  |         srand((unsigned int)time(NULL)); | ||||||
|  |         rand_song = rand() % num_songs; | ||||||
|  |         mpd_send_list_all(mpd.conn, "/"); | ||||||
|  |         i = 0; | ||||||
|  |         while ((entity = mpd_recv_entity(mpd.conn)) != NULL) { | ||||||
|  |             if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) { | ||||||
|  |                 if (i == rand_song) | ||||||
|  |                         break; | ||||||
|  |                 i++; | ||||||
|  |             } | ||||||
|  |             mpd_entity_free(entity); | ||||||
|  |         } | ||||||
|  |         mpd_response_finish(mpd.conn); | ||||||
|  |         song = mpd_entity_get_song(entity);         | ||||||
|  |         if (song != NULL) { | ||||||
|  |             printf("Jukebox enabled, playing random song %d/%d\n", rand_song, num_songs); | ||||||
|  |             mpd_run_add(mpd.conn, mpd_song_get_uri(song)); | ||||||
|  |             mpd_run_play(mpd.conn); | ||||||
|  |         } | ||||||
|  |         mpd_entity_free(entity); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length) { | int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length) { | ||||||
|     struct mpd_status *status; |     struct mpd_status *status; | ||||||
|     const struct mpd_audio_format *audioformat; |     const struct mpd_audio_format *audioformat; | ||||||
| @@ -976,21 +1030,8 @@ int mympd_put_settings(char *buffer) { | |||||||
|     struct mpd_status *status; |     struct mpd_status *status; | ||||||
|     char *replaygain = strdup(""); |     char *replaygain = strdup(""); | ||||||
|     int len; |     int len; | ||||||
|     int je; |  | ||||||
|     struct json_out out = JSON_OUT_BUF(buffer, MAX_SIZE); |     struct json_out out = JSON_OUT_BUF(buffer, MAX_SIZE); | ||||||
|     struct mympd_state { int a; int b; } state = { .a = 0, .b = 0 }; |      | ||||||
|     if (access( config.statefile, F_OK ) != -1 ) { |  | ||||||
|         char *content = json_fread(config.statefile); |  | ||||||
|         je = json_scanf(content, strlen(content), "{notificationWeb: %d, notificationPage: %d}", &state.a, &state.b); |  | ||||||
|         if (je != 2) { |  | ||||||
|           state.a = 0; |  | ||||||
|           state.b = 1; |  | ||||||
|         } |  | ||||||
|     } else { |  | ||||||
|         state.a = 0; |  | ||||||
|         state.b = 1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     status = mpd_run_status(mpd.conn); |     status = mpd_run_status(mpd.conn); | ||||||
|     if (!status) { |     if (!status) { | ||||||
|         printf("MPD mpd_run_status: %s\n", mpd_connection_get_error_message(mpd.conn)); |         printf("MPD mpd_run_status: %s\n", mpd_connection_get_error_message(mpd.conn)); | ||||||
| @@ -1009,8 +1050,8 @@ int mympd_put_settings(char *buffer) { | |||||||
|     len = json_printf(&out, "{type: settings, data: {" |     len = json_printf(&out, "{type: settings, data: {" | ||||||
|         "repeat: %d, single: %d, crossfade: %d, consume: %d, random: %d, " |         "repeat: %d, single: %d, crossfade: %d, consume: %d, random: %d, " | ||||||
|         "mixrampdb: %f, mixrampdelay: %f, mpdhost: %Q, mpdport: %d, passwort_set: %B, " |         "mixrampdb: %f, mixrampdelay: %f, mpdhost: %Q, mpdport: %d, passwort_set: %B, " | ||||||
|         "streamport: %d, coverimage: %Q, stickers: %B, mixramp: %B, " |         "streamport: %d, coverimage: %Q, stickers: %B, mixramp: %B, maxElementsPerPage: %d, " | ||||||
|         "maxElementsPerPage: %d, replaygain: %Q, notificationWeb: %d, notificationPage: %d, " |         "replaygain: %Q, notificationWeb: %B, notificationPage: %B, jukeboxMode: %B, " | ||||||
|         "tags: { Artist: %B, Album: %B, AlbumArtist: %B, Title: %B, Track: %B, Genre: %B, Date: %B," |         "tags: { Artist: %B, Album: %B, AlbumArtist: %B, Title: %B, Track: %B, Genre: %B, Date: %B," | ||||||
|         "Composer: %B, Performer: %B }" |         "Composer: %B, Performer: %B }" | ||||||
|         "}}",  |         "}}",  | ||||||
| @@ -1030,8 +1071,9 @@ int mympd_put_settings(char *buffer) { | |||||||
|         config.mixramp, |         config.mixramp, | ||||||
|         MAX_ELEMENTS_PER_PAGE, |         MAX_ELEMENTS_PER_PAGE, | ||||||
|         replaygain, |         replaygain, | ||||||
|         state.a, |         mympd_state.notificationWeb, | ||||||
|         state.b, |         mympd_state.notificationPage, | ||||||
|  |         mympd_state.jukeboxMode, | ||||||
|         mpd.tag_artist, |         mpd.tag_artist, | ||||||
|         mpd.tag_album, |         mpd.tag_album, | ||||||
|         mpd.tag_album_artist, |         mpd.tag_album_artist, | ||||||
|   | |||||||
| @@ -171,6 +171,14 @@ typedef struct { | |||||||
|     long like; |     long like; | ||||||
| } t_sticker; | } t_sticker; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     bool notificationWeb; | ||||||
|  |     bool notificationPage; | ||||||
|  |     bool jukeboxMode; | ||||||
|  | } t_mympd_state; | ||||||
|  |  | ||||||
|  | t_mympd_state mympd_state; | ||||||
|  |  | ||||||
| static int is_websocket(const struct mg_connection *nc) { | static int is_websocket(const struct mg_connection *nc) { | ||||||
|     return nc->flags & MG_F_IS_WEBSOCKET; |     return nc->flags & MG_F_IS_WEBSOCKET; | ||||||
| } | } | ||||||
| @@ -185,6 +193,7 @@ void mympd_like_song_uri(const char *uri, int value); | |||||||
| void mympd_last_played_song_uri(const char *uri); | void mympd_last_played_song_uri(const char *uri); | ||||||
| void mympd_last_played_song_id(int song_id); | void mympd_last_played_song_id(int song_id); | ||||||
| void mympd_get_sticker(const char *uri, t_sticker *sticker); | void mympd_get_sticker(const char *uri, t_sticker *sticker); | ||||||
|  | void mympd_jukebox(); | ||||||
| int mympd_get_updatedb_state(char *buffer); | int mympd_get_updatedb_state(char *buffer); | ||||||
| int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length); | int mympd_put_state(char *buffer, int *current_song_id, int *next_song_id, int *last_song_id, unsigned *queue_version, unsigned *queue_length); | ||||||
| int mympd_put_outputs(char *buffer); | int mympd_put_outputs(char *buffer); | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								src/mympd.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/mympd.c
									
									
									
									
									
								
							| @@ -31,6 +31,7 @@ | |||||||
| #include <grp.h> | #include <grp.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 "mpd_client.h" | #include "mpd_client.h" | ||||||
| #include "config.h" | #include "config.h" | ||||||
| @@ -233,6 +234,23 @@ int main(int argc, char **argv) { | |||||||
|         return EXIT_FAILURE; |         return EXIT_FAILURE; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (access( config.statefile, F_OK ) != -1 ) { | ||||||
|  |         char *content = json_fread(config.statefile); | ||||||
|  |         int je = json_scanf(content, strlen(content), "{notificationWeb: %B, notificationPage: %B, jukeboxMode: %B}",  | ||||||
|  |             &mympd_state.notificationWeb,  | ||||||
|  |             &mympd_state.notificationPage, | ||||||
|  |             &mympd_state.jukeboxMode); | ||||||
|  |         if (je != 3) { | ||||||
|  |             mympd_state.notificationWeb = false; | ||||||
|  |             mympd_state.notificationPage = true; | ||||||
|  |             mympd_state.jukeboxMode = false; | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         mympd_state.notificationWeb = false; | ||||||
|  |         mympd_state.notificationPage = true; | ||||||
|  |         mympd_state.jukeboxMode = false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     signal(SIGTERM, signal_handler); |     signal(SIGTERM, signal_handler); | ||||||
|     signal(SIGINT, signal_handler); |     signal(SIGINT, signal_handler); | ||||||
|     setvbuf(stdout, NULL, _IOLBF, 0); |     setvbuf(stdout, NULL, _IOLBF, 0); | ||||||
| @@ -302,7 +320,6 @@ int main(int argc, char **argv) { | |||||||
|     s_http_server_opts.document_root = SRC_PATH; |     s_http_server_opts.document_root = SRC_PATH; | ||||||
|     s_http_server_opts.enable_directory_listing = "no"; |     s_http_server_opts.enable_directory_listing = "no"; | ||||||
|  |  | ||||||
|  |  | ||||||
|     printf("Listening on http port %s\n", config.webport); |     printf("Listening on http port %s\n", config.webport); | ||||||
|     if (config.ssl == true) |     if (config.ssl == true) | ||||||
|         printf("Listening on ssl port %s\n", config.sslport); |         printf("Listening on ssl port %s\n", config.sslport); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 jcorporation
					jcorporation