1+ #include " ArduinoFTPClient.h"
2+ #include " AudioSource.h"
3+ #include " vector"
4+
5+ namespace audio_tools {
6+
7+ /* *
8+ * @brief An AudioSource that uses the
9+ * https://github.com/pschatzmann/TinyFTPClient library to retrieve files from a
10+ * FTP Server. You need to provide an FTPClient object to the constructor and
11+ * make sure that you open it before you access the files. The storage of the
12+ * expanded file names is done on the heap, so in order to limit the requested
13+ * memory we can limit the number of files.
14+ *
15+ * @ingroup player
16+ * @author Phil Schatzmann
17+ * @copyright GPLv3
18+ */
19+
20+
21+ class AudioSourceFTP : public AudioSource {
22+ public:
23+ AudioSourceFTP (FTPClient& client, const char * path, const char * ext,
24+ int files = 0 ) {
25+ p_client = &client;
26+ timeout_auto_next_value = 5000 ;
27+ if (path) p_path = path;
28+ setMaxFiles (files);
29+ }
30+
31+ // / Resets the actual data
32+ void begin ()override {
33+ TRACED ();
34+ idx = 0 ;
35+ files.clear ();
36+ addDirectory (p_path);
37+ }
38+
39+ // / Resets the actual data
40+ void end () {
41+ idx = 0 ;
42+ files.clear ();
43+ }
44+
45+ // / Returns next audio stream
46+ Stream* nextStream (int offset) override {
47+ int tmp_idx = idx + offset;
48+ if (!isValidIdx (tmp_idx)) return nullptr ;
49+ return selectStream (tmp_idx);
50+ };
51+
52+ // / Returns previous audio stream
53+ Stream* previousStream (int offset) override { return nextStream (-offset); };
54+
55+ // / Returns audio stream at the indicated index (the index is zero based, so
56+ // / the first value is 0!)
57+ Stream* selectStream (int index) override {
58+ if (!isValidIdx (index)) return nullptr ;
59+ idx = index;
60+ if (file) {
61+ file.close (); // close the previous file
62+ }
63+ file = p_client->open (files[idx].name ());
64+ return &file;
65+ }
66+
67+ // / Retrieves all files and returns the actual index of the stream
68+ int index () override { return idx; }
69+
70+ // / Returns the FTPFile for the indicated path
71+ Stream* selectStream (const char * path) override {
72+ TRACED ();
73+ files.clear ();
74+ idx = 0 ;
75+ addDirectory (path);
76+ return selectStream (0 );
77+ }
78+
79+ // / provides the actual stream (e.g. file) name or url
80+ const char * toStr () override {
81+ return file.name ();
82+ }
83+
84+ // / Defines the max number of files (if value is >0)
85+ void setMaxFiles (int maxCount) { max_files = maxCount; }
86+
87+ // / Adds all the files of a directory
88+ bool addDirectory (const char * path) {
89+ TRACED ();
90+ if (p_client == nullptr ) return false ;
91+ FTPFile dir = p_client->open (path);
92+ addFiles (dir, 1 );
93+ return true ;
94+ }
95+
96+ // / Returns the number of available files
97+ size_t size () { return files.size (); }
98+
99+ protected:
100+ std::vector<FTPFile> files;
101+ FTPClient* p_client = nullptr ;
102+ FTPFile file;
103+ int idx = 0 ;
104+ size_t max_files = 0 ;
105+ const char * p_ext = nullptr ;
106+ const char * p_path = " /" ;
107+ bool is_first = true ;
108+
109+ // / Adds all files recursively
110+ void addFiles (FTPFile& dir, int level) {
111+ if (!endsWith (dir.name (), p_ext)) {
112+ LOGI (" adding file %s" , dir.name ());
113+ files.push_back (std::move (dir));
114+ } else {
115+ for (const auto & file : p_client->ls (dir.name ())) {
116+ if (endsWith (file.name (), p_ext)) {
117+ LOGI (" adding file %s" , file.name ());
118+ files.push_back (std::move (file));
119+ }
120+ if (max_files > 0 && files.size () >= max_files) {
121+ LOGI (" max files reached: %d" , max_files);
122+ return ; // stop if we reached the max number of files
123+ }
124+ }
125+ }
126+ }
127+
128+ bool isValidIdx (int index) {
129+ if (index < 0 ) return false ;
130+ if (index >= files.size ()) {
131+ LOGE (" index %d is out of range (size: %d)" , index, files.size ());
132+ return false ;
133+ }
134+ return true ;
135+ }
136+
137+ bool endsWith (const char * file, const char * ext) {
138+ if (file == nullptr ) return false ;
139+ if (p_ext == nullptr ) return true ;
140+ return (StrView (file).endsWith (ext));
141+ }
142+ };
143+
144+ } // namespace audio_tools
0 commit comments