Arduino DLNA Server
Loading...
Searching...
No Matches
SdFatContentProvider.h
Go to the documentation of this file.
1
2
8#include "DLNA.h"
10
11namespace tiny_dlna {
12
32template <typename FS>
34 public:
41 bool begin(FS& fs, const char* rootPath) {
42 return directoryTree.begin(fs, rootPath);
43 }
44
46 void end() {
47 directoryTree.end();
48 resultNodes_.clear();
49 }
50
51 size_t size() { return directoryTree.size(); }
52
71 void prepareData(const char* objectID, ContentQueryType queryType,
72 const char* filter, int startingIndex, int requestedCount,
73 const char* sortCriteria, int& numberReturned,
74 int& totalMatches, int& updateID, void* reference) {
75 // Store parameters in class variables
76 objectID_ = objectID;
77 queryType_ = queryType;
78 filter_ = filter;
79 startingIndex_ = startingIndex;
80 requestedCount_ = requestedCount;
81 sortCriteria_ = sortCriteria;
82 reference_ = reference;
83
84 // Clear previous results
85 resultNodes_.clear();
86
87 // Calculate actual values based on directory tree and query type
88 updateID = 0; // Can increment this when content changes
89
90 if (queryType == ContentQueryType::BrowseMetadata) {
91 // Metadata for a single object
92 TreeNode* node =
93 objectID ? findNodeByObjectID(objectID) : &directoryTree.root();
94 if (node && !isHidden(node)) {
95 resultNodes_.push_back(node);
96 totalMatches = 1;
97 numberReturned = 1;
98 } else {
99 totalMatches = 0;
100 numberReturned = 0;
101 }
102 } else if (queryType == ContentQueryType::BrowseChildren) {
103 // Browse children of a container (directory)
104 TreeNode* parentNode =
105 objectID ? findNodeByObjectID(objectID) : &directoryTree.root();
106 if (parentNode) {
107 // Collect all children, filter out hidden
108 resultNodes_.clear();
109 for (auto* child : parentNode->children) {
110 if (!isHidden(child)) {
111 resultNodes_.push_back(child);
112 }
113 }
114 totalMatches = static_cast<int>(resultNodes_.size());
115
116 // Apply pagination
117 int available = totalMatches - startingIndex;
118 if (available < 0) available = 0;
119 numberReturned = (requestedCount == 0)
120 ? available
121 : std::min(requestedCount, available);
122 } else {
123 totalMatches = 0;
124 numberReturned = 0;
125 }
126 } else {
127 // Search - return all files, filter out hidden
128 auto allFiles = directoryTree.getAllFiles();
129 resultNodes_.clear();
130 for (auto* node : allFiles) {
131 if (!isHidden(node)) {
132 resultNodes_.push_back(node);
133 }
134 }
135 totalMatches = static_cast<int>(resultNodes_.size());
136
137 // Apply pagination
138 int available = totalMatches - startingIndex;
139 if (available < 0) available = 0;
140 numberReturned = (requestedCount == 0)
141 ? available
142 : std::min(requestedCount, available);
143 }
144
145 DlnaLogger.log(DlnaLogLevel::Info,
146 "Number of results: Total=%d, Returned=%d", totalMatches,
147 numberReturned);
148 }
149
155 bool isHidden(TreeNode* node) const {
156 return node == nullptr || (!node->file_name.empty() && node->file_name[0] == '.');
157 }
158
170 bool getData(int index, MediaItem& item, void* reference = nullptr) {
171 // Calculate the actual index into resultNodes_
172 int adjustedIndex = startingIndex_ + index;
173
174 // Validate index
175 if (adjustedIndex < 0 ||
176 adjustedIndex >= static_cast<int>(resultNodes_.size())) {
177 return false;
178 }
179
180 TreeNode* node = resultNodes_[adjustedIndex];
181 if (!node) return false;
182
183 // Populate MediaItem from TreeNode
184 // Use member strings for pointer lifetime
185 currentId_ = std::to_string(node->id);
186 item.id = currentId_.c_str();
187
188 // Parent ID
189 if (node->parent) {
190 currentParentId_ = std::to_string(node->parent->id);
191 item.parentID = currentParentId_.c_str();
192 } else {
193 item.parentID = "0";
194 }
195
196 item.title = node->file_name.c_str();
197 item.restricted = true;
198
199 if (node->is_dir) {
201 item.resourceURI = nullptr;
202 item.mimeType = nullptr;
203 } else {
204 // File - determine class from MIME type
205 currentMime_ = node->getMime();
206 if (currentMime_.empty()) currentMime_ = "application/octet-stream";
207 item.mimeType = currentMime_.c_str();
208
209 if (currentMime_.find("audio") != std::string::npos) {
211 } else if (currentMime_.find("video") != std::string::npos) {
213 } else if (currentMime_.find("image") != std::string::npos) {
215 } else {
217 }
218
219 // Resource URI: baseURL + basePath + ?ID=id
220 char urlBuffer[80];
221 snprintf(urlBuffer, sizeof(urlBuffer), "/%s?ID=%u", path, node->id);
222 currentPath_ = urlBuffer;
223 item.resourceURI = currentPath_.c_str();
224 }
225
226 item.albumArtURI = nullptr;
227
228 return true;
229 }
230
232 const char* getPath() {
233 return path;
234 }
235
237 void setPath(const char* p) {
238 path = p;
239 }
240
242 TreeNode& getTreeNodeById(uint32_t id) {
243 return directoryTree.getTreeNodeById(id);
244 }
245
246 protected:
248 const char* path = "/file";
249
250 // Store query parameters for getData
251 const char* objectID_ = nullptr;
253 const char* filter_ = nullptr;
256 const char* sortCriteria_ = nullptr;
257 void* reference_ = nullptr;
258
259 // Collected results from prepareData
260 std::vector<TreeNode*, AllocatorPSRAM<TreeNode*>> resultNodes_;
261
262 // String storage for MediaItem pointers (lifetime managed by class)
267
273 TreeNode* findNodeByObjectID(const char* objectID) {
274 if (!objectID) return nullptr;
275 uint32_t id = std::stoul(objectID);
276 return &directoryTree.getTreeNodeById(id);
277 }
278};
279
280} // namespace tiny_dlna
In-memory directory tree built from SdFat recursive listings.
Content provider for DLNA media server using SdFat filesystem.
Definition: SdFatContentProvider.h:33
const char * sortCriteria_
Definition: SdFatContentProvider.h:256
void end()
Releases all resources and clears the directory tree.
Definition: SdFatContentProvider.h:46
stringPSRAM currentPath_
Current resource path string.
Definition: SdFatContentProvider.h:265
bool getData(int index, MediaItem &item, void *reference=nullptr)
Retrieves a single media item by index.
Definition: SdFatContentProvider.h:170
bool isHidden(TreeNode *node) const
Returns true if the node is hidden (file or directory name starts with '.')
Definition: SdFatContentProvider.h:155
std::vector< TreeNode *, AllocatorPSRAM< TreeNode * > > resultNodes_
Definition: SdFatContentProvider.h:260
stringPSRAM currentId_
Current item ID string.
Definition: SdFatContentProvider.h:263
stringPSRAM currentParentId_
Current parent ID string.
Definition: SdFatContentProvider.h:264
int requestedCount_
Definition: SdFatContentProvider.h:255
const char * objectID_
Definition: SdFatContentProvider.h:251
void * reference_
Definition: SdFatContentProvider.h:257
const char * filter_
Definition: SdFatContentProvider.h:253
const char * getPath()
Provides the path prefix for resource URIs.
Definition: SdFatContentProvider.h:232
const char * path
Definition: SdFatContentProvider.h:248
int startingIndex_
Definition: SdFatContentProvider.h:254
ContentQueryType queryType_
Definition: SdFatContentProvider.h:252
void prepareData(const char *objectID, ContentQueryType queryType, const char *filter, int startingIndex, int requestedCount, const char *sortCriteria, int &numberReturned, int &totalMatches, int &updateID, void *reference)
Prepares data for a DLNA content query.
Definition: SdFatContentProvider.h:71
TreeNode & getTreeNodeById(uint32_t id)
Returns the full file path by node ID.
Definition: SdFatContentProvider.h:242
TreeNode * findNodeByObjectID(const char *objectID)
Finds a tree node by its object ID string.
Definition: SdFatContentProvider.h:273
bool begin(FS &fs, const char *rootPath)
Initializes the content provider and scans the filesystem.
Definition: SdFatContentProvider.h:41
SdFatDirectoryTree< FS > directoryTree
Definition: SdFatContentProvider.h:247
void setPath(const char *p)
Sets the path prefix for resource URIs.
Definition: SdFatContentProvider.h:237
stringPSRAM currentMime_
Current MIME type string.
Definition: SdFatContentProvider.h:266
size_t size()
Definition: SdFatContentProvider.h:51
Simple in-memory directory tree built using SdFat recursive directory listing.
Definition: SdFatDirectoryTree.h:33
Node in the directory tree representing either a file or a directory.
Definition: TreeNode.h:18
std::string getMime() const
Very basic MIME inference based on file extension.
Definition: TreeNode.h:66
std::vector< TreeNode *, AllocatorPSRAM< TreeNode * > > children
Definition: TreeNode.h:23
uint32_t id
Definition: TreeNode.h:21
stringPSRAM file_name
Definition: TreeNode.h:22
bool is_dir
Definition: TreeNode.h:27
TreeNode * parent
Definition: TreeNode.h:24
Definition: Allocator.h:13
ContentQueryType
Type of content query for DLNA browsing/searching.
Definition: DLNACommon.h:36
std::basic_string< char, std::char_traits< char >, AllocatorPSRAM< char > > stringPSRAM
Definition: Allocator.h:106
Media item description used to build DIDL-Lite entries.
Definition: MediaItem.h:24
const char * parentID
Definition: MediaItem.h:26
const char * mimeType
Definition: MediaItem.h:30
const char * id
Definition: MediaItem.h:25
MediaItemClass itemClass
Definition: MediaItem.h:31
bool restricted
Definition: MediaItem.h:27
const char * title
Definition: MediaItem.h:28
const char * resourceURI
Definition: MediaItem.h:29
const char * albumArtURI
Definition: MediaItem.h:32