/* build an XML doc containing information about currently running sources. * If a mountpoint is passed then that source will not be added to the XML * doc even if the source is running */ xmlDocPtr admin_build_sourcelist (const char *mount) { avl_node *node; source_t *source; xmlNodePtr xmlnode, srcnode; xmlDocPtr doc; char buf[22]; time_t now = time(NULL); doc = xmlNewDoc(XMLSTR("1.0")); xmlnode = xmlNewDocNode(doc, NULL, XMLSTR("icestats"), NULL); xmlDocSetRootElement(doc, xmlnode); if (mount) { xmlNewChild(xmlnode, NULL, XMLSTR("current_source"), XMLSTR(mount)); } node = avl_get_first(global.source_tree); while(node) { source = (source_t *)node->key; if (mount && strcmp (mount, source->mount) == 0) { node = avl_get_next (node); continue; } thread_mutex_lock (&source->lock); if (source_available (source)) { ice_config_t *config; mount_proxy *mountinfo; srcnode = xmlNewChild (xmlnode, NULL, XMLSTR("source"), NULL); xmlSetProp (srcnode, XMLSTR("mount"), XMLSTR(source->mount)); snprintf (buf, sizeof(buf), "%lu", source->listeners); xmlNewChild (srcnode, NULL, XMLSTR("listeners"), XMLSTR(buf)); config = config_get_config(); mountinfo = config_find_mount (config, source->mount); if (mountinfo) { if (mountinfo->auth) { xmlNewChild (srcnode, NULL, XMLSTR("authenticator"), XMLSTR(mountinfo->auth->type)); } if (mountinfo->fallback_mount) xmlNewChild (srcnode, NULL, XMLSTR("fallback"), XMLSTR(mountinfo->fallback_mount)); } config_release_config(); if (source_running (source)) { if (source->client) { snprintf (buf, sizeof(buf), "%lu", (unsigned long)(now - source->client->connection.con_time)); xmlNewChild (srcnode, NULL, XMLSTR("Connected"), XMLSTR(buf)); } xmlNewChild (srcnode, NULL, XMLSTR("content-type"), XMLSTR(source->format->contenttype)); } } thread_mutex_unlock (&source->lock); node = avl_get_next(node); } return(doc); }
static int command_metadata (client_t *client, source_t *source, int response) { const char *song, *title, *artist, *artwork, *charset, *url; format_plugin_t *plugin; xmlDocPtr doc; xmlNodePtr node; int same_ip = 1; doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); DEBUG0("Got metadata update request"); COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "url", url); COMMAND_OPTIONAL(client, "artwork", artwork); COMMAND_OPTIONAL(client, "charset", charset); plugin = source->format; if (source_running (source)) if (strcmp (client->connection.ip, source->client->connection.ip) != 0) if (response == RAW && connection_check_admin_pass (client->parser) == 0) same_ip = 0; do { if (same_ip == 0 || plugin == NULL) break; if (artwork) stats_event (source->mount, "artwork", artwork); if (plugin->set_tag) { if (url) { plugin->set_tag (plugin, "url", url, charset); INFO2 ("Metadata url on %s set to \"%s\"", source->mount, url); } if (song) { plugin->set_tag (plugin, "artist", NULL, NULL); plugin->set_tag (plugin, "title", song, charset); INFO2("Metadata song on %s set to \"%s\"", source->mount, song); } if (artist) { plugin->set_tag (plugin, "artist", artist, charset); INFO2 ("Metadata artist on %s changed to \"%s\"", source->mount, artist); } if (title) { plugin->set_tag (plugin, "title", title, charset); INFO2 ("Metadata title on %s changed to \"%s\"", source->mount, title); } /* updates are now done, let them be pushed into the stream */ plugin->set_tag (plugin, NULL, NULL, charset); } else { break; } thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); } while (0); INFO1 ("Metadata on mountpoint %s prevented", source->mount); thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Mountpoint will not accept this URL update")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); }
static int command_metadata (client_t *client, source_t *source, int response) { const char *song, *title, *artist, *artwork, *charset, *url; format_plugin_t *plugin; xmlDocPtr doc; xmlNodePtr node; int same_ip = 1; doc = xmlNewDoc(XMLSTR("1.0")); node = xmlNewDocNode(doc, NULL, XMLSTR("iceresponse"), NULL); xmlDocSetRootElement(doc, node); DEBUG0("Got metadata update request"); COMMAND_OPTIONAL(client, "song", song); COMMAND_OPTIONAL(client, "title", title); COMMAND_OPTIONAL(client, "artist", artist); COMMAND_OPTIONAL(client, "url", url); COMMAND_OPTIONAL(client, "artwork", artwork); COMMAND_OPTIONAL(client, "charset", charset); plugin = source->format; if (source_running (source)) if (strcmp (client->connection.ip, source->client->connection.ip) != 0) if (response == RAW && connection_check_admin_pass (client->parser) == 0) same_ip = 0; /* Update stream metadata if needed */ if (same_ip) { static const struct { const char *param; const char *stat_name; const char *hdr[3]; } fwd[] = { {"xstreamname", "server_name", {"ice-name", "icy-name", "x-audiocast-name"}}, {"xstreamdesc", "server_description", {"ice-description", "icy-description", "x-audiocast-description"}}, {"xstreamurl", "server_url", {"ice-url", "icy-url", "x-audiocast-url"}}, {"xstreamgenre", "genre", {"ice-genre", "icy-genre", "x-audiocast-genre"}} }; unsigned i; for (i = 0; i < sizeof(fwd) / sizeof(*fwd); i++) { const char *value; unsigned j; COMMAND_OPTIONAL(client, fwd[i].param, value); if (value && *value) { value = auto_recode(value); if (source->format->charset) stats_set_conv (source->stats, fwd[i].stat_name, value, source->format->charset); else stats_set (source->stats, fwd[i].stat_name, value); } else if (value) { stats_set (source->stats, fwd[i].stat_name, NULL); } for (j = 0; j < 3; j++) { if (j == 0 && value && *value) { httpp_setvar(source->format->parser, fwd[i].hdr[j], value); } else if (value && !*value) { httpp_deletevar(source->format->parser, fwd[i].hdr[j]); } } } } do { if (same_ip == 0 || plugin == NULL) break; /* Charset detection (if none specified) */ if (!charset) { const char *r; int len; charset = "UTF8"; #define CCONV(s) \ if (s && (r = auto_recode(s))) { \ len = strlen(r); \ s = alloca(len + 1); \ memcpy((char*)s, r, len + 1); \ } CCONV(title); CCONV(song); CCONV(artist); } /* Now send prepared metadata */ if (artwork) stats_event (source->mount, "artwork", artwork); if (plugin->set_tag) { if (url) { plugin->set_tag (plugin, "url", url, charset); INFO2 ("Metadata url on %s set to \"%s\"", source->mount, url); } if (song) { plugin->set_tag (plugin, "artist", NULL, NULL); plugin->set_tag (plugin, "title", song, charset); INFO2("Metadata song on %s set to \"%s\"", source->mount, song); } if (artist) { plugin->set_tag (plugin, "artist", artist, charset); INFO2 ("Metadata artist on %s changed to \"%s\"", source->mount, artist); } if (title) { plugin->set_tag (plugin, "title", title, charset); INFO2 ("Metadata title on %s changed to \"%s\"", source->mount, title); } /* updates are now done, let them be pushed into the stream */ plugin->set_tag (plugin, NULL, NULL, NULL); } else { break; } thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Metadata update successful")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); } while (0); thread_mutex_unlock (&source->lock); xmlNewChild(node, NULL, XMLSTR("message"), XMLSTR("Mountpoint will not accept this URL update")); xmlNewChild(node, NULL, XMLSTR("return"), XMLSTR("1")); return admin_send_response(doc, client, response, "response.xsl"); }