Arduino DLNA Server
Loading...
Searching...
No Matches
DLNAControlPointMediaServer.h
Go to the documentation of this file.
1// Header-only control point helper for MediaServer devices
2#pragma once
3
4#include "dlna/Action.h"
6
7namespace tiny_dlna {
8
18 public:
19 typedef void (*XMLCallback)(const char* name, const char* test,
20 const char* attributes);
21 typedef void (*NotificationCallback)(void* reference, const char* sid,
22 const char* varName,
23 const char* newValue);
24
37 IUDPService& udp)
38 : p_mgr(&mgr), p_http(&http), p_udp(&udp) {}
39
42
50 bool begin(uint32_t minWaitMs = 3000, uint32_t maxWaitMs = 60000) {
53 "DLNAControlPointMediaServer::begin: device_type_filter='%s'",
55 if (!p_mgr) {
56 DlnaLogger.log(DlnaLogLevel::Error, "mgr instance not set");
57 return false;
58 }
59 if (!p_http) {
60 DlnaLogger.log(DlnaLogLevel::Error, "http instance not set");
61 return false;
62 }
63 if (!p_udp) {
64 DlnaLogger.log(DlnaLogLevel::Error, "udp instance not set");
65 return false;
66 }
67 return p_mgr->begin(*p_http, *p_udp, device_type_filter, minWaitMs,
68 maxWaitMs);
69 }
70
72 void setHttp(DLNAHttpRequest& http) { p_http = &http; }
73
75 void setUdp(IUDPService& udp) { p_udp = &udp; }
76
82 // count only devices matching the device_type_filter
83 int count = 0;
84 for (auto& d : p_mgr->getDevices()) {
85 const char* dt = d.getDeviceType();
86 if (!device_type_filter || StrView(dt).contains(device_type_filter))
87 count++;
88 }
89 return count;
90 }
91
96 const ActionReply& getLastReply() const { return last_reply; }
97
103 void setDeviceIndex(int idx) { p_mgr->setDeviceIndex(idx); }
104
108 }
109
116 void setDeviceTypeFilter(const char* filter) {
118 }
119
124 void setReference(void* ref) { reference = ref; }
125
140 bool browse(int startingIndex, int requestedCount, ContentQueryType queryType,
141 XMLCallback XMLCallback, int& numberReturned, int& totalMatches,
142 int& updateID) {
143 // Register item callback
144 this->p_mgr->onResultNode(XMLCallback);
145 // Build and post browse action
146 DLNAServiceInfo& svc =
147 selectService("urn:upnp-org:serviceId:ContentDirectory");
148 if (!svc) return false;
149 ActionRequest& act =
150 createBrowseAction(svc, queryType, startingIndex, requestedCount);
151 p_mgr->addAction(act);
153 if (!last_reply) return false;
154
155 // parse numeric result fields
156 parseNumericFields(last_reply, numberReturned, totalMatches, updateID);
157
158 return true;
159 }
160
175 bool search(int startingIndex, int requestedCount, XMLCallback XMLCallback,
176 int& numberReturned, int& totalMatches, int& updateID,
177 const char* searchCriteria = "", const char* filter = "",
178 const char* sortCriteria = "") {
179 // Register item callback
180 this->p_mgr->onResultNode(XMLCallback);
181
182 DLNAServiceInfo& svc =
183 selectService("urn:upnp-org:serviceId:ContentDirectory");
184 if (!svc) return false;
185
186 ActionRequest& act =
187 createSearchAction(svc, searchCriteria, filter, startingIndex,
188 requestedCount, sortCriteria);
189 p_mgr->addAction(act);
191 if (!last_reply) return false;
192
193 parseNumericFields(last_reply, numberReturned, totalMatches, updateID);
194 return true;
195 }
196
203 "ControlPointMediaServer::getSystemUpdateID");
204 DLNAServiceInfo& svc =
205 selectService("urn:upnp-org:serviceId:ContentDirectory");
206 if (!svc) return -1;
207 ActionRequest act{svc, "GetSystemUpdateID"};
208 p_mgr->addAction(act);
210 if (!last_reply) return -1;
211 const char* v = last_reply.findArgument("Id");
212 if (!v) v = last_reply.findArgument("Id");
213 return v ? atoi(v) : -1;
214 }
215
220 const char* getSearchCapabilities() {
222 "ControlPointMediaServer::getSearchCapabilities");
223 DLNAServiceInfo& svc =
224 selectService("urn:upnp-org:serviceId:ContentDirectory");
225 if (!svc) return nullptr;
226 ActionRequest act{svc, "GetSearchCapabilities"};
227 p_mgr->addAction(act);
229 if (!last_reply) return nullptr;
230 return last_reply.findArgument("SearchCaps");
231 }
232
237 const char* getSortCapabilities() {
239 "ControlPointMediaServer::getSortCapabilities");
240 DLNAServiceInfo& svc =
241 selectService("urn:upnp-org:serviceId:ContentDirectory");
242 if (!svc) return nullptr;
243 ActionRequest act{svc, "GetSortCapabilities"};
244 p_mgr->addAction(act);
246 if (!last_reply) return nullptr;
247 return last_reply.findArgument("SortCaps");
248 }
249
254 const char* getProtocolInfo() {
256 "ControlPointMediaServer::getProtocolInfo");
257 DLNAServiceInfo& svc =
258 selectService("urn:upnp-org:serviceId:ConnectionManager");
259 if (!svc) return nullptr;
260 ActionRequest act{svc, "GetProtocolInfo"};
261 p_mgr->addAction(act);
263 if (!last_reply) return nullptr;
264 return last_reply.findArgument("Source");
265 }
266
271 void setObjectID(const char* id) { object_id = id; }
272
277 const char* getObjectID() const { return object_id; }
278
279 protected:
282 "urn:schemas-upnp-org:device:MediaServer:1";
286 void* reference = nullptr;
287 const char* object_id = "0";
288 // transport references (optional) - must be set before calling begin()
290 IUDPService* p_udp = nullptr;
291
293 static void processNotification(void* reference, const char* sid,
294 const char* varName, const char* newValue) {
295 // Log every notification invocation for debugging/visibility
297 "processNotification sid='%s' var='%s' value='%s'",
298 sid ? sid : "(null)", varName ? varName : "(null)",
299 newValue ? newValue : "(null)");
300 }
301
305 "ControlPointMediaServer::selectService: id='%s'", id);
306 // Build list of devices matching the optional filter
308 if (s) return s;
309
310 // fallback: global search
311 return p_mgr->getService(id);
312 }
313
316 ContentQueryType queryType,
317 int startingIndex, int requestedCount) {
318 const char* browseFlag = (queryType == ContentQueryType::BrowseMetadata)
319 ? "BrowseMetadata"
320 : "BrowseDirectChildren";
321 static ActionRequest act{svc, "Browse"};
322 // Use the canonical argument name expected by ContentDirectory: "ObjectID"
323 act.addArgument("ObjectID", object_id);
324 act.addArgument("BrowseFlag", browseFlag);
325 act.addArgument("Filter", "");
326 char buf[32];
327 snprintf(buf, sizeof(buf), "%d", startingIndex);
328 act.addArgument("StartingIndex", buf);
329 snprintf(buf, sizeof(buf), "%d", requestedCount);
330 act.addArgument("RequestedCount", buf);
331 act.addArgument("SortCriteria", "");
332 return act;
333 }
334
337 const char* searchCriteria,
338 const char* filter, int startingIndex,
339 int requestedCount,
340 const char* sortCriteria) {
341 static ActionRequest act{svc, "Search"};
342 act.addArgument("ContainerID", object_id);
343 act.addArgument("SearchCriteria", searchCriteria ? searchCriteria : "");
344 act.addArgument("Filter", filter ? filter : "");
345 char buf[32];
346 snprintf(buf, sizeof(buf), "%d", startingIndex);
347 act.addArgument("StartingIndex", buf);
348 snprintf(buf, sizeof(buf), "%d", requestedCount);
349 act.addArgument("RequestedCount", buf);
350 act.addArgument("SortCriteria", sortCriteria ? sortCriteria : "");
351 return act;
352 }
353
355 void parseNumericFields(ActionReply& reply, int& numberReturned,
356 int& totalMatches, int& updateID) {
358 "ControlPointMediaServer::parseNumericFields");
359 const char* nret = reply.findArgument("NumberReturned");
360 const char* tmatch = reply.findArgument("TotalMatches");
361 const char* uid = reply.findArgument("UpdateID");
362 numberReturned = nret ? atoi(nret) : 0;
363 totalMatches = tmatch ? atoi(tmatch) : 0;
364 updateID = uid ? atoi(uid) : 0;
365 }
366};
367
368} // namespace tiny_dlna
Represents the result of invoking a DLNA service Action.
Definition: Action.h:50
const char * findArgument(const char *name)
Definition: Action.h:72
Represents a request to invoke a remote DLNA service action.
Definition: Action.h:109
Helper class to control/query a MediaServer from a control point.
Definition: DLNAControlPointMediaServer.h:17
ActionRequest & createSearchAction(DLNAServiceInfo &svc, const char *searchCriteria, const char *filter, int startingIndex, int requestedCount, const char *sortCriteria)
Build a Search ActionRequest.
Definition: DLNAControlPointMediaServer.h:336
void * reference
Definition: DLNAControlPointMediaServer.h:286
bool browse(int startingIndex, int requestedCount, ContentQueryType queryType, XMLCallback XMLCallback, int &numberReturned, int &totalMatches, int &updateID)
Browse the given object_id and invoke callback for each returned xml element.
Definition: DLNAControlPointMediaServer.h:140
DLNAControlPointMediaServer()=default
Default constructor.
DLNAServiceInfo & selectService(const char *id)
Select service by id.
Definition: DLNAControlPointMediaServer.h:303
void(* NotificationCallback)(void *reference, const char *sid, const char *varName, const char *newValue)
Definition: DLNAControlPointMediaServer.h:21
DLNAHttpRequest * p_http
Definition: DLNAControlPointMediaServer.h:289
const char * getObjectID() const
Return the current object id used for browse.
Definition: DLNAControlPointMediaServer.h:277
DLNAControlPoint * p_mgr
Definition: DLNAControlPointMediaServer.h:280
void setSubscribeNotificationsActive(bool flag)
Activate/deactivate subscription notifications.
Definition: DLNAControlPointMediaServer.h:106
IUDPService * p_udp
Definition: DLNAControlPointMediaServer.h:290
void setUdp(IUDPService &udp)
Setter for UDP service used for discovery (SSDP)
Definition: DLNAControlPointMediaServer.h:75
const char * getSearchCapabilities()
Get the ContentDirectory SearchCapabilities string.
Definition: DLNAControlPointMediaServer.h:220
void setDLNAControlPoint(DLNAControlPoint &m)
Set the control point manager instance (required before using helper)
Definition: DLNAControlPointMediaServer.h:41
const char * getSortCapabilities()
Get the ContentDirectory SortCapabilities string.
Definition: DLNAControlPointMediaServer.h:237
DLNAControlPointMediaServer(DLNAControlPoint &mgr, DLNAHttpRequest &http, IUDPService &udp)
Construct helper with references to control point manager and required transport instances (HTTP for ...
Definition: DLNAControlPointMediaServer.h:36
const char * object_id
Definition: DLNAControlPointMediaServer.h:287
bool begin(uint32_t minWaitMs=3000, uint32_t maxWaitMs=60000)
Begin discovery and processing (forwards to underlying control point)
Definition: DLNAControlPointMediaServer.h:50
const char * device_type_filter_default
Definition: DLNAControlPointMediaServer.h:281
ActionRequest & createBrowseAction(DLNAServiceInfo &svc, ContentQueryType queryType, int startingIndex, int requestedCount)
Build a Browse ActionRequest.
Definition: DLNAControlPointMediaServer.h:315
static void processNotification(void *reference, const char *sid, const char *varName, const char *newValue)
Notification callback: just log for now.
Definition: DLNAControlPointMediaServer.h:293
const char * device_type_filter
Definition: DLNAControlPointMediaServer.h:283
void setDeviceTypeFilter(const char *filter)
Restrict this helper to devices of the given device type.
Definition: DLNAControlPointMediaServer.h:116
bool search(int startingIndex, int requestedCount, XMLCallback XMLCallback, int &numberReturned, int &totalMatches, int &updateID, const char *searchCriteria="", const char *filter="", const char *sortCriteria="")
Search the ContentDirectory using SearchCriteria and invoke callback for each returned xml element.
Definition: DLNAControlPointMediaServer.h:175
void setObjectID(const char *id)
Set the object id used for browse operations (default: "0")
Definition: DLNAControlPointMediaServer.h:271
int getSystemUpdateID()
Get current SystemUpdateID for the ContentDirectory.
Definition: DLNAControlPointMediaServer.h:201
void setDeviceIndex(int idx)
Select a device by index (0-based) for subsequent actions. By default 0 is used.
Definition: DLNAControlPointMediaServer.h:103
const ActionReply & getLastReply() const
Return the ActionReply from the last synchronous request.
Definition: DLNAControlPointMediaServer.h:96
const char * getProtocolInfo()
Query ConnectionManager:GetProtocolInfo.
Definition: DLNAControlPointMediaServer.h:254
int getDeviceCount()
Return number of discovered devices known to the control point.
Definition: DLNAControlPointMediaServer.h:81
void setHttp(DLNAHttpRequest &http)
Setter for the HTTP wrapper used for subscriptions and callbacks.
Definition: DLNAControlPointMediaServer.h:72
ActionReply last_reply
Definition: DLNAControlPointMediaServer.h:284
void parseNumericFields(ActionReply &reply, int &numberReturned, int &totalMatches, int &updateID)
Parse numeric result fields from an ActionReply.
Definition: DLNAControlPointMediaServer.h:355
void setReference(void *ref)
Attach an opaque reference pointer passed to callbacks.
Definition: DLNAControlPointMediaServer.h:124
StringRegistry strings
Definition: DLNAControlPointMediaServer.h:285
Lightweight DLNA control point manager.
Definition: DLNAControlPoint.h:62
ActionRequest & addAction(ActionRequest act)
Registers a method that will be called.
Definition: DLNAControlPoint.h:243
DLNADeviceInfo & getDevice()
Provides the device information of the actually selected device.
Definition: DLNAControlPoint.h:325
Vector< DLNADeviceInfo > & getDevices()
Definition: DLNAControlPoint.h:365
bool begin(DLNAHttpRequest &http, IUDPService &udp, const char *searchTarget="ssdp:all", uint32_t minWaitMs=3000, uint32_t maxWaitMs=60000)
Start discovery by sending M-SEARCH requests and process replies.
Definition: DLNAControlPoint.h:126
DLNAServiceInfo & getService(const char *id)
Provide addess to the service information.
Definition: DLNAControlPoint.h:314
void setDeviceIndex(int idx)
Selects the default device by index.
Definition: DLNAControlPoint.h:84
void onResultNode(std::function< void(const char *nodeName, const char *text, const char *attributes)> cb)
Definition: DLNAControlPoint.h:108
void setSubscribeNotificationsActive(bool flag)
Activate/deactivate subscription notifications.
Definition: DLNAControlPoint.h:470
ActionReply & executeActions(XMLCallback xmlProcessor=nullptr)
Executes action and parses the reply xml to collect the reply entries. If an XML processor is provide...
Definition: DLNAControlPoint.h:257
DLNAServiceInfo & getService(const char *id)
Finds a service definition by name.
Definition: DLNADeviceInfo.h:146
Attributes needed for the DLNA Service Definition.
Definition: DLNAServiceInfo.h:16
Simple API to process get, put, post, del http requests I tried to use Arduino HttpClient,...
Definition: HttpRequest.h:23
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
Make sure that a string is stored only once.
Definition: StringRegistry.h:12
Definition: AllocationTracker.h:9
ContentQueryType
Type of content query for DLNA browsing/searching.
Definition: DLNACommon.h:36
LoggerClass DlnaLogger
Definition: Logger.cpp:5
std::function< void(Client &client, ActionReply &reply)> XMLCallback
Definition: DLNAControlPoint.h:22