59 int startingIndex,
int requestedCount,
const char* sortCriteria,
60 int& numberReturned,
int& totalMatches,
int& updateID,
void* reference);
160 auto writer = [](Print& out,
void* ref) ->
size_t {
163 result += out.
print(
"<SourceProtocolInfo>\n");
165 result += out.print(
"</SourceProtocolInfo>\n");
166 result += out.print(
"<SinkProtocolInfo>\n");
168 result += out.print(
"</SinkProtocolInfo>\n");
206 for (
size_t i = 0; i <
rules.size(); ++i) {
208 rules[i].handler = handler;
212 rules.push_back({suffix, handler});
239 const char*
st =
"urn:schemas-upnp-org:device:MediaServer:1";
240 const char*
usn =
"uuid:media-server-0000-0000-0000-000000000001";
242 "dc:title,dc:creator,upnp:class,upnp:genre,"
243 "upnp:album,upnp:artist,upnp:albumArtURI";
245 "dc:title,dc:date,upnp:class,upnp:album,upnp:episodeNumber,upnp:"
246 "originalTrackNumber";
256 std::function<
size_t(Print&,
void*)> changeWriter) {
264 auto writer = [](Print& out,
void* ref) ->
size_t {
267 result += out.
print(
"<SystemUpdateID val=\"");
269 result += out.print(
"\"/>\n");
280 auto writer = [](Print& out,
void* ref) ->
size_t {
283 result += out.
print(
"<SourceProtocolInfo>\n");
285 result += out.print(
"</SourceProtocolInfo>\n");
286 result += out.print(
"<SinkProtocolInfo>\n");
288 result += out.print(
"</SinkProtocolInfo>\n");
289 result += out.print(
"<CurrentConnectionIDs>");
291 result += out.print(
"</CurrentConnectionIDs>\n");
309 server->
reply(
"text/xml", [](Print& out) {
318 server->
reply(
"text/xml", [](Print& out) {
326 const char* requestPath,
331 StrView request_path_str(requestPath);
332 if (request_path_str.
contains(
"/CD/"))
334 else if (request_path_str.
contains(
"/CM/"))
338 "eventSubscriptionHandler: Unknown request path: %s",
346 cd.
setup(
"urn:schemas-upnp-org:service:ContentDirectory:1",
347 "urn:upnp-org:serviceId:ContentDirectory",
"/CD/service.xml",
350 [](
HttpServer* server,
const char* requestPath,
376 cm.
setup(
"urn:schemas-upnp-org:service:ConnectionManager:1",
377 "urn:upnp-org:serviceId:ConnectionManager",
"/CM/service.xml",
380 [](
HttpServer* server,
const char* requestPath,
411 for (
const auto& rule :
rules) {
412 if (action_str.
endsWith(rule.suffix)) {
413 return rule.handler(
this, action, server);
425 int numberReturned = 0;
426 int totalMatches = 0;
441 numberReturned, totalMatches, updateID,
reference_);
448 requestedCount, server);
455 int numberReturned = 0;
456 int totalMatches = 0;
471 numberReturned, totalMatches, updateID,
reference_);
478 startingIndex, requestedCount, server);
489 "urn:schemas-upnp-org:service:ContentDirectory:1");
491 chunk.print(
"<SearchCaps>");
493 chunk.println(
"</SearchCaps>");
499 "processActionGetSearchCapabilities (streamed)");
511 "urn:schemas-upnp-org:service:ContentDirectory:1");
513 chunk.print(
"<SortCaps>");
515 chunk.println(
"</SortCaps>");
521 "processActionGetSortCapabilities (streamed)");
533 "urn:schemas-upnp-org:service:ContentDirectory:1");
541 "processActionGetSystemUpdateID (streamed): %d",
556 "urn:schemas-upnp-org:service:ConnectionManager:1");
558 chunk.print(
"<Source>");
560 chunk.println(
"</Source>");
562 chunk.print(
"<Sink>");
564 chunk.println(
"</Sink>");
583 "urn:schemas-upnp-org:service:ConnectionManager:1");
586 chunk.println(
"<ConnectionIDs>01</ConnectionIDs>");
607 "urn:schemas-upnp-org:service:ConnectionManager:1");
610 chunk.println(
"<RcsID>0</RcsID>");
611 chunk.println(
"<AVTransportID>0</AVTransportID>");
614 chunk.print(
"<ProtocolInfo>");
616 chunk.println(
"</ProtocolInfo>");
619 chunk.print(
"<PeerConnectionManager>");
620 chunk.println(
"</PeerConnectionManager>");
621 chunk.println(
"<PeerConnectionID>0</PeerConnectionID>");
624 chunk.println(
"<Direction>Output</Direction><Status>OK</Status>");
635 if (fv.
equals(
"BrowseDirectChildren"))
642 chunk.
print(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n");
644 "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
647 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n");
648 chunk.
print(
"<s:Body>\r\n");
652 chunk.
print(
"</s:Body>\r\n");
653 chunk.
print(
"</s:Envelope>\r\n");
657 const char* serviceNS) {
659 chunk.
printf(
"<u:%s xmlns:u=\"%s\">\r\n", responseName, serviceNS);
663 chunk.
printf(
"</u:%s>\r\n", responseName);
668 int startingIndex,
int requestedCount,
670 int numberReturned = 0;
671 int totalMatches = 0;
677 requestedCount,
nullptr, numberReturned, totalMatches,
688 "urn:schemas-upnp-org:service:ContentDirectory:1");
691 chunk_writer.println(
"<Result>");
693 streamDIDL(chunk_writer, numberReturned, startingIndex);
694 chunk_writer.print(
"</Result>\r\n");
697 chunk_writer.printf(
"<NumberReturned>%d</NumberReturned>\r\n",
699 chunk_writer.printf(
"<TotalMatches>%d</TotalMatches>\r\n", totalMatches);
700 chunk_writer.printf(
"<UpdateID>%d</UpdateID>\r\n", updateID);
713 "<DIDL-Lite xmlns:dc=\"http://purl.org/dc/elements/1.1/\" "
714 "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" "
715 "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\">\r\n");
719 for (
int i = 0; i < numberReturned; ++i) {
721 int idx = startingIndex + i;
725 const char* nodeName =
729 "<%s id=\"%s\" parentID=\"%s\" restricted=\"%d\">", nodeName,
734 chunk_writer.
print(
"<dc:title>");
736 chunk_writer.
print(
"</dc:title>\r\n");
737 if (mediaItemClassStr !=
nullptr) {
738 chunk_writer.
printf(
"<upnp:class>%s</upnp:class>\r\n",
744 if (!url.isEmpty()) {
745 url.replaceAll(
"&",
"&");
747 chunk_writer.
printf(
"<res protocolInfo=\"http-get:*:%s:*\">",
750 chunk_writer.
print(
"</res>\r\n");
752 chunk_writer.
print(
"<res>");
754 chunk_writer.
print(
"</res>\r\n");
758 chunk_writer.
printf(
"</%s>\r\n", nodeName);
762 chunk_writer.
print(
"</DIDL-Lite>\r\n");
768 return "object.item.audioItem.musicTrack";
770 return "object.item.audioItem.audioBroadcast";
772 return "object.item.videoItem.movie";
774 return "object.item.imageItem.photo";
776 return "object.container";
784 const char* requestPath,
834 {
"GetSearchCapabilities",
839 {
"GetSortCapabilities",
844 {
"GetSystemUpdateID",
855 {
"GetCurrentConnectionIDs",
860 {
"GetCurrentConnectionInfo",
Represents a request to invoke a remote DLNA service action.
Definition: Action.h:109
const char * getArgumentValue(const char *name)
Definition: Action.h:133
int getArgumentIntValue(const char *name)
Definition: Action.h:154
const char * action
Definition: Action.h:159
Print implementation for HTTP chunked transfer encoding.
Definition: HttpChunkWriter.h:56
size_t printf(const char *fmt,...)
Definition: HttpChunkWriter.h:118
size_t print(const char *str)
Definition: HttpChunkWriter.h:72
Device Attributes and generation of XML using urn:schemas-upnp-org:device-1-0. We could just return a...
Definition: DLNADeviceInfo.h:27
void setDeviceType(const char *st)
Definition: DLNADeviceInfo.h:48
void print(Print &out)
renders the device xml
Definition: DLNADeviceInfo.h:40
void addService(DLNAServiceInfo s)
Adds a service definition.
Definition: DLNADeviceInfo.h:143
void setManufacturerURL(const char *url)
Definition: DLNADeviceInfo.h:127
void setModelName(const char *name)
Definition: DLNADeviceInfo.h:131
void setSerialNumber(const char *sn)
Definition: DLNADeviceInfo.h:135
void setManufacturer(const char *man)
Definition: DLNADeviceInfo.h:125
void setFriendlyName(const char *name)
Definition: DLNADeviceInfo.h:123
void setModelNumber(const char *number)
Definition: DLNADeviceInfo.h:133
void setBaseURL(const char *url)
Defines the base url.
Definition: DLNADeviceInfo.h:59
Setup of a Basic DLNA Device service. The device registers itself to the network and answers to the D...
Definition: DLNADevice.h:27
void end()
Stops the processing and releases the resources.
Definition: DLNADevice.h:85
void addChange(const char *serviceAbbrev, std::function< size_t(Print &, void *)> changeWriter, void *ref)
Definition: DLNADevice.h:156
bool begin(DLNADeviceInfo &device, IUDPService &udp, HttpServer &server)
start the
Definition: DLNADevice.h:30
static void parseActionRequest(HttpServer *server, const char *requestPath, HttpRequestHandlerLine *hl, ActionRequest &action)
Parses the SOAP content of a DLNA action request.
Definition: DLNADevice.h:275
static void eventSubscriptionHandler(HttpServer *server, const char *requestPath, HttpRequestHandlerLine *hl)
Static handler for SUBSCRIBE/UNSUBSCRIBE requests on service event URLs.
Definition: DLNADevice.h:189
bool loop()
call this method in the Arduino loop as often as possible
Definition: DLNADevice.h:104
ContentDirectory SCPD descriptor for MediaServer.
Definition: DLNAMediaServerDescr.h:160
size_t printDescr(Print &out) override
Emit ContentDirectory SCPD XML.
Definition: DLNAMediaServerDescr.h:170
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:16
const char * scpd_url
Definition: DLNAServiceInfo.h:35
http_callback control_cb
Definition: DLNAServiceInfo.h:40
http_callback scp_cb
Definition: DLNAServiceInfo.h:39
void setup(const char *type, const char *id, const char *scp, http_callback cbScp, const char *control, http_callback cbControl, const char *event, http_callback cbEvent)
Definition: DLNAServiceInfo.h:19
const char * control_url
Definition: DLNAServiceInfo.h:36
const char * subscription_namespace_abbrev
Definition: DLNAServiceInfo.h:49
const char * event_sub_url
Definition: DLNAServiceInfo.h:37
Used to register and process callbacks.
Definition: HttpRequestHandlerLine.h:19
void ** context
Definition: HttpRequestHandlerLine.h:39
A Simple Header only implementation of Http Server that allows the registration of callback functions...
Definition: HttpServer.h:25
void on(const char *url, TinyMethodID method, web_callback_fn fn, void *ctx[]=nullptr, int ctxCount=0)
register a generic handler
Definition: HttpServer.h:90
void replyOK()
write OK reply with 200 SUCCESS
Definition: HttpServer.h:380
Client & client()
Provides the current client.
Definition: HttpServer.h:476
void reply(const char *contentType, Stream &inputStream, int size, int status=200, const char *msg=SUCCESS)
write reply - copies data from input stream with header size
Definition: HttpServer.h:296
void replyNotFound()
write 404 reply
Definition: HttpServer.h:383
void replyChunked(const char *contentType, Stream &inputStream, int status=200, const char *msg=SUCCESS)
chunked reply with data from an input stream
Definition: HttpServer.h:271
Abstract Interface for UDP API.
Definition: IUDPService.h:33
void log(DlnaLogLevel current_level, const char *fmt...)
Print log message.
Definition: Logger.h:40
A simple wrapper to provide string functions on char*. If the underlying char* is a const we do not a...
Definition: StrView.h:18
virtual bool isEmpty()
checks if the string is empty
Definition: StrView.h:383
virtual bool endsWith(const char *str)
checks if the string ends with the indicated substring
Definition: StrView.h:191
virtual bool equals(const char *str)
checks if the string equals indicated parameter string
Definition: StrView.h:177
virtual bool contains(const char *str)
checks if the string contains a substring
Definition: StrView.h:284
String implementation which keeps the data on the heap. We grow the allocated memory only if the copy...
Definition: Str.h:22
static const char * nullStr(const char *str, const char *alt="")
Return str if not null, alt otherwise.
Definition: StringRegistry.h:54
Vector implementation which provides the most important methods as defined by std::vector....
Definition: Vector.h:19
#define DLNA_PROTOCOL_AUDIO
Definition: dlna_config.h:135
Definition: AllocationTracker.h:9
ContentQueryType
Type of content query for DLNA browsing/searching.
Definition: DLNACommon.h:36
MediaItemClass
Definition: MediaItem.h:12
@ T_UNSUBSCRIBE
Definition: HttpHeader.h:46
@ T_SUBSCRIBE
Definition: HttpHeader.h:47
@ T_GET
Definition: HttpHeader.h:37
@ T_POST
Definition: HttpHeader.h:39
LoggerClass DlnaLogger
Definition: Logger.cpp:5