4.2.0r10
[enigma2.git] / usr / include / enigma2 / lib / components / media_database.h
1 #ifndef __lib_components_mediadatabase_h_
2 #define __lib_components_mediadatabase_h_
3
4 #include <lib/base/message.h>
5 #include <lib/base/stl_types.h>
6 #include <lib/base/thread.h>
7 #include <lib/components/file_monitor.h>
8 #include <lib/components/media_scanner.h>
9
10 #include <QSqlQuery>
11 #include <QSqlDatabase>
12
13 #ifndef SWIG
14 struct query_data
15 {
16         std::string query_string;
17         file_metadata result;
18 };
19
20 struct insert_result
21 {
22         long long id;
23         bool created;
24         bool error;
25         bool skipped;
26         insert_result(long long id = 0, bool created = true, bool error = false, bool skipped = false) :
27                         id(id), created(created), error(error), skipped(skipped)
28         {
29         }
30 };
31 #endif
32
33 class eMediaDatabaseHandler;
34
35 class eMediaDatabaseResult : public iObject
36 {
37         DECLARE_REF(eMediaDatabaseResult)
38         bool m_error;
39         int m_rowsAffected;
40         int m_lastInsertId;
41         std::string m_errorDriverText;
42         std::string m_errorDatabaseText;
43         stringMapVector m_data;
44 public:
45 #ifdef SWIG
46         eMediaDatabaseResult();
47         ~eMediaDatabaseResult();
48 #endif
49         bool error(){ return m_error; };
50         int rowsAffected(){ return m_rowsAffected; };
51         int lastInsertId(){ return m_lastInsertId; };
52         std::string errorDriverText(){ return m_errorDriverText; };
53         std::string errorDatabaseText(){ return m_errorDatabaseText; };
54         stringMapVector data(){ return m_data; };
55 #ifndef SWIG
56         void setError(bool error){ m_error = error; };
57         void setRowsAffected(int rowsAffected){ m_rowsAffected = rowsAffected; };
58         void setLastInsertId(int lastInsertId){ m_lastInsertId = lastInsertId; };
59         void setErrorDriverText( const std::string &errorDriverText ){ m_errorDriverText = errorDriverText; };
60         void setErrorDatabaseText( const std::string &errorDatabaseText){ m_errorDatabaseText = errorDatabaseText; };
61         stringMapVector *dataPtr(){ return &m_data; };
62 #endif
63
64 };
65
66 class eMediaDatabase : public sigc::trackable
67 {
68         static eMediaDatabase *instance;
69         eMediaScanner *m_scanner;
70         eMediaDatabaseHandler *m_db;
71         std::vector<eFileWatch*> m_watches;
72         std::map<std::string, sigc::connection> m_watchconns;
73         typedef void (eMediaDatabase::*table_line_extension_func)(stringMap *item, QSqlQuery*);
74
75 #ifdef SWIG
76         eMediaDatabase();
77         ~eMediaDatabase();
78 #endif
79
80 public:
81         static const char FIELD_ID[];
82         static const char FIELD_FILE_ID[];
83         static const char FIELD_DIR_ID[];
84         static const char FIELD_ALBUM_ID[];
85         static const char FIELD_ARTIST_ID[];
86         static const char FIELD_GENRE_ID[];
87         static const char FIELD_CODEC_ID[];
88         static const char FIELD_PATH[];
89         static const char FIELD_FILENAME[];
90         static const char FIELD_SIZE[];
91         static const char FIELD_DURATION[];
92         static const char FIELD_POPULARITY[];
93         static const char FIELD_LASTPLAYPOS[];
94         static const char FIELD_LASTPLAYED[];
95         static const char FIELD_LASTMODIFIED[];
96         static const char FIELD_LASTUPDATED[];
97         static const char FIELD_TITLE[];
98         static const char FIELD_TRACK[];
99         static const char FIELD_TRACKS_TOTAL[];
100         static const char FIELD_DATE[];
101         static const char FIELD_COMMENT[];
102         static const char FIELD_ARTIST[];
103         static const char FIELD_ALBUM[];
104         static const char FIELD_GENRE[];
105         static const char FIELD_CODEC[];
106         static const char FIELD_CODEC_LONG[];
107         static const char FIELD_WIDTH[];
108         static const char FIELD_HEIGHT[];
109         static const char FIELD_FRAMERATE[];
110         static const char FIELD_HD[];
111         static const char FIELD_WIDESCREEN[];
112         static const char FIELD_RECORDING[];
113         static const char FIELD_PLAYLIST_NAME[];
114         static const char FIELD_FILE_URI[];
115         static const char FIELD_POS[];
116         static const char FIELD_DESCRIPTION[];
117         static const char FIELD_SERVICEREFRENCE[];
118         static const char FIELD_TYPE[];
119         static const char FIELD_NAME[];
120
121         static eMediaDatabase *getInstance();
122
123 #ifndef SWIG
124         eMediaDatabase();
125         ~eMediaDatabase();
126
127         eMediaDatabaseHandler *getDatabaseHandler();
128
129         void addToDatabase(const std::list<file_metadata> &data);
130         bool _dbAddAudio(const file_data &fmd, const audio_track &at, const audio_metadata &amd);
131         bool _dbAddVideo(const file_data &fmd, const video_data &vt);
132
133         void onScanStatistics(std::string dir, uint64_t total, uint64_t successful, uint64_t skipped);
134         void onScanFinished(std::string dir, uint64_t total, uint64_t successful, uint64_t skipped);
135         void onInsertFinished(uint64_t success, uint64_t skipped, uint64_t errors, std::list<int> ids);
136
137         ePtr<eMediaDatabaseResult> resultFromQuery(QSqlQuery* qry, table_line_extension_func extendItem=0);
138         void extendPlaylistItemAttributes(stringMap *item, QSqlQuery *qry);
139
140         void onProcessEvents(bool finished);
141         void onFileChanged(eFileWatch *watch, eFileEvent event);
142
143 #endif
144         std::string getCurrentScanPath();
145         std::vector<std::string> *getEnqueuedPaths();
146
147         void addPath(const std::string &path, bool watch=false);
148         void rescanPath(const std::string &path, bool isRecording=false);
149         bool requestScanStatistics();
150         ePtr<eMediaDatabaseResult> setParentDirectoryWatched(int dir_id, bool watched);
151         ePtr<eMediaDatabaseResult> deleteParentDirectory(int dir_id);
152         ePtr<eMediaDatabaseResult> getParentDirectories();
153
154         ePtr<eMediaDatabaseResult> filterAudio(const std::string &needle, int limit = -1, int offset = 0);
155         ePtr<eMediaDatabaseResult> filterByAlbum(const std::string &album, int limit = -1, int offset = 0);
156         ePtr<eMediaDatabaseResult> filterByArtistAlbum(const std::string &artist, const std::string &album, int limit = -1, int offset = 0);
157         ePtr<eMediaDatabaseResult> filterByArtist(const std::string &artist, int limit = -1, int offset = 0);
158         ePtr<eMediaDatabaseResult> filterByGenre(const std::string &genre, int limit = -1, int offset = 0);
159         ePtr<eMediaDatabaseResult> filterByTitle(const std::string &title, int limit = -1, int offset = 0);
160         ePtr<eMediaDatabaseResult> getAllArtists(int limit = -1, int offset = 0);
161         ePtr<eMediaDatabaseResult> getArtists(const std::string &artist, int limit = -1, int offset = 0);
162         ePtr<eMediaDatabaseResult> getAllAlbums(int limit = -1, int offset = 0);
163         ePtr<eMediaDatabaseResult> getAlbums(const std::string &album, int limit = -1, int offset = 0);
164         ePtr<eMediaDatabaseResult> getAlbumsByArtist(const std::string &artist, int limit = -1, int offset = 0);
165         ePtr<eMediaDatabaseResult> getAllAudio(int limit = -1, int offset = 0);
166         ePtr<eMediaDatabaseResult> getAllVideos(int limit = -1, int offset = 0);
167
168         ePtr<eMediaDatabaseResult> addRecording(const std::string &filepath, const std::string & title, int created);
169         ePtr<eMediaDatabaseResult> getAllRecordings(int limit = -1, int offset = 0);
170         ePtr<eMediaDatabaseResult> getRecordings(const std::string &dir, const std::list<std::string> &tags = std::list<std::string>(), int limit = -1, int offset = 0);
171         ePtr<eMediaDatabaseResult> getRecordMeta(int file_id);
172         ePtr<eMediaDatabaseResult> setRecordMeta(int file_id, const std::string & ref, const std::string &name, const std::string &description, const std::string &service_data, int64_t duration);
173         ePtr<eMediaDatabaseResult> getRecordEit(int file_id);
174         ePtr<eMediaDatabaseResult> setRecordEit(int file_id, uint8_t eit_raw[]);
175
176         ePtr<eMediaDatabaseResult> getFileByPath(const std::string &filepath);
177
178         ePtr<eMediaDatabaseResult> setFileAttribute(int file_id, const std::string &key, const std::string &value);
179         ePtr<eMediaDatabaseResult> deleteFileAttribute(int file_id, const std::string &key);
180         ePtr<eMediaDatabaseResult> getFileAttributes(int file_id);
181         ePtr<eMediaDatabaseResult> getFileAttribute(int file_id, const std::string &key);
182
183         ePtr<eMediaDatabaseResult> addPlaylist(const std::string &name, int type);
184         ePtr<eMediaDatabaseResult> getPlaylist(int id);
185         ePtr<eMediaDatabaseResult> getPlaylistByName(const std::string &name, int type);
186         ePtr<eMediaDatabaseResult> getPlaylistItemsById(int id);
187         ePtr<eMediaDatabaseResult> getPlaylistItemsByName(const std::string &name, int type=-1);
188         ePtr<eMediaDatabaseResult> getPlaylists(int type=-1);
189         ePtr<eMediaDatabaseResult> addToPlaylistById(int playlist_id, int file_id, int pos);
190         ePtr<eMediaDatabaseResult> addToPlaylistByUri(int playlist_id, const std::string &uri, int pos, const stringMap &attributes);
191         ePtr<eMediaDatabaseResult> updatePlaylistItem(int playlist_id, stringMap item);
192         ePtr<eMediaDatabaseResult> clearPlaylist(int playlist_id);
193         ePtr<eMediaDatabaseResult> savePlaylist(int playlist_id, const std::string &name, int type, const stringMapVector &items);
194
195         ePtr<eMediaDatabaseResult> removeFile(int file_id);
196         ePtr<eMediaDatabaseResult> query(const std::string &sql, const stringList &values=stringList(), bool rw = false);
197
198         /* void scanStatistics( std::string, uint64_t, uint64_t, uint64_t ); */
199         eSignal4<void, std::string, uint64_t, uint64_t, uint64_t> scanStatistics;
200         /* void scanFinished( std::string, uint64_t, uint64_t, uint64_t ); */
201         eSignal4<void, std::string, uint64_t, uint64_t, uint64_t> scanFinished;
202         /* void insertFinished(uint64_t, uint64_t, uint64_t, PyObject*); */
203         eSignal4<void, uint64_t, uint64_t, uint64_t, intList > insertFinished;
204         /* void priorityInsertFinished ( char*, uint64_t, uint64_t, uint64_t, int ); */
205         eSignal5<void, const char *, uint64_t, uint64_t, uint64_t, int> priorityInsertFinished;
206 };
207
208 SWIG_TEMPLATE_TYPEDEF(ePtr<eMediaDatabaseResult>, eMediaDatabaseResultPtr);
209
210 #ifndef SWIG
211
212 class eVersionedDatabase {
213 public:
214         virtual ~eVersionedDatabase(){};
215 protected:
216         void checkVersion(const QSqlDatabase &db_rw, int requiredVersion);
217         virtual bool upgradeSchema(int from)=0;
218 };
219
220 class eMediaDatabaseHandler : public eVersionedDatabase, public eMainloop_native, public eThread, public sigc::trackable
221 {
222         int SCHEMA_VERSION = 1;
223
224         std::string normalizePath(const std::string &path);
225         bool upgradeSchema(int from);
226         bool upgradeSchema0_to_1();
227 public:
228         eMediaDatabaseHandler();
229         ~eMediaDatabaseHandler();
230
231         static pthread_mutex_t priority_files_lock, files_lock;
232
233         void insertList(const std::string &dir, std::list<file_metadata> files);
234         void priorityInsert(const file_metadata &file);
235         void thread();
236
237         void transaction();
238         void commit();
239
240         int addParentDirectory(const std::string &dir, bool watch);
241         bool isParentDirectory(int dir_id);
242         QSqlQuery setParentDirectoryWatched(int dir_id, bool watched);
243         QSqlQuery deleteDirectory(int dir_id);
244         QSqlQuery deleteDirectory(const std::string &dir);
245         QSqlQuery moveDirectory(const std::string &from, const std::string &to);
246         QSqlQuery getParentDirectories();
247
248         QSqlQuery filterAudio(const std::string &needle, int limit = -1, int offset = 0);
249         QSqlQuery filterByAlbum(const std::string &album, int limit = -1, int offset = 0);
250         QSqlQuery filterByArtistAlbum(const std::string &artist, const std::string &album, int limit = -1, int offset = 0);
251         QSqlQuery filterByArtist(const std::string &artist, int limit = -1, int offset = 0);
252         QSqlQuery filterByGenre(const std::string &genre, int limit = -1, int offset = 0);
253         QSqlQuery filterByTitle(const std::string &title, int limit = -1, int offset = 0);
254
255         QSqlQuery getAllArtists(int limit = -1, int offset = 0);
256         QSqlQuery getArtists(const std::string &artist, int limit = -1, int offset = 0);
257         QSqlQuery getAllAlbums(int limit = -1, int offset = 0);
258         QSqlQuery getAlbums(const std::string &album, int limit = -1, int offset = 0);
259         QSqlQuery getAlbumsByArtist(const std::string &artist, int limit = -1, int offset = 0);
260
261         QSqlQuery getAllAudio(int limit = -1, int offset = 0);
262         QSqlQuery getAllVideos(int limit = -1, int offset = 0);
263
264         //Recordings
265         QSqlQuery addRecording(const std::string &filepath, const std::string & title, int created);
266         QSqlQuery getAllRecordings(int limit = -1, int offset = 0);
267         QSqlQuery getRecordings(const std::string &dir, const std::list<std::string> &tags = std::list<std::string>(), int limit = -1, int offset = 0);
268         QSqlQuery getRecordMeta(int file_id);
269         QSqlQuery setRecordMeta(int file_id, const std::string & ref, const std::string &name, const std::string &description, const std::string &service_data, int64_t duration);
270         QSqlQuery getRecordEit(int file_id);
271         QSqlQuery setRecordEit(int file_id, const uint8_t eit_raw[]);
272
273         QSqlQuery getByFile(const std::string &filepath);
274         QSqlQuery getAudioByFile(const std::string &filepath);
275         QSqlQuery getVideoByFile(const std::string &filepath);
276
277         QSqlQuery getById(int id);
278         QSqlQuery getAudioById(int id);
279         QSqlQuery getVideoById(int id);
280
281         QSqlQuery setFileAttribute(int file_id, const std::string &key, const std::string &value);
282         QSqlQuery deleteFileAttribute(int file_id, const std::string &key);
283         QSqlQuery getFileAttributes(int file_id);
284         QSqlQuery getFileAttribute(int file_id, const std::string &key);
285
286         QSqlQuery addPlaylist(const std::string &name, int type);
287         QSqlQuery getPlaylistById(int id);
288         QSqlQuery getPlaylistByName(const std::string &name, int type);
289         QSqlQuery getPlaylistItemsById(int id);
290         QSqlQuery getPlaylistItemsByName(const std::string &name, int type);
291         QSqlQuery getPlaylists(int type);
292         QSqlQuery addToPlaylistById(int playlist_id, int file_id, int pos);
293         QSqlQuery addToPlaylistByUri(int playlist_id, const std::string &uri, int pos, const stringMap &attributes=stringMap());
294         void condensePlaylistItemAttributes(stringMap *item);
295         QSqlQuery updatePlaylistItemInternal(int playlist_id, int item_id, int file_id, const std::string &file_uri, int pos, stringMap *attributes);
296         QSqlQuery updatePlaylistItem(int playlist_id, stringMap *attributes);
297         QSqlQuery getPlaylistItemAttribute(int playlist_item_id, const std::string &key);
298         QSqlQuery getPlaylistItemAttributes(int playlist_item_id);
299         QSqlQuery clearPlaylist(int id);
300         QSqlQuery savePlaylist(int playlist_id, const std::string &name, int type, const stringMapVector &items);
301
302         QSqlQuery removeFile(int file_id);
303
304         QSqlQuery query(const std::string &sql, const stringList &values=stringList(), bool rw = false);
305
306         Signal4<void, uint64_t, uint64_t, uint64_t, std::list<int> > insertFinished;
307         Signal5<void, char*, uint64_t, uint64_t, uint64_t, int> priorityInsertFinished;
308
309 private:
310         enum {
311                 COMMIT_ERROR=-3,
312                 INSERT_ERROR=-2,
313                 INSERT_SKIPPED=-1,
314         };
315
316         struct DbMessage
317         {
318                 int type;
319                 char* filename;
320                 uint64_t errors;
321                 uint64_t successful;
322                 uint64_t skipped;
323                 int file_id;
324                 enum
325                 {
326                         quit=-1,
327                         update,
328                         done_list,
329                         done_single
330                 };
331
332                 DbMessage(int type=0, char* filename=0, uint64_t errors=0, uint64_t successful=0, uint64_t skipped=0, int file_id=0) :
333                 type(type), filename(filename), errors(errors), successful(successful), skipped(skipped), file_id(file_id) {}
334         };
335
336         eFixedMessagePump<DbMessage> m_messages_to_thread;
337         eFixedMessagePump<DbMessage> m_messages_from_thread;
338
339         bool m_immediate_cancel;
340         int m_dummy; //for sqlite shared cache init;
341
342         std::list<file_metadata> m_priority_files;
343         std::list<file_metadata> m_files;
344         std::list<int> m_inserted_ids;
345         std::list<std::string> m_directories;
346         std::string m_parent_dir;
347         int m_parent_dir_id;
348
349         QSqlDatabase m_db_rw, m_db_ro;
350
351         QSqlQuery m_qry_insert_file;
352         QSqlQuery m_qry_insert_directory;
353         QSqlQuery m_qry_insert_codec;
354         QSqlQuery m_qry_insert_audio_track;
355         QSqlQuery m_qry_insert_audio_meta;
356         QSqlQuery m_qry_insert_artist;
357         QSqlQuery m_qry_insert_album;
358         QSqlQuery m_qry_insert_genre;
359         QSqlQuery m_qry_insert_video;
360         QSqlQuery m_qry_insert_location;
361         QSqlQuery m_qry_insert_tag;
362
363         QSqlQuery m_qry_delete_file;
364         QSqlQuery m_qry_update_file;
365
366         QSqlQuery m_qry_get_file_by_id;
367         QSqlQuery m_qry_get_file_lastmodified;
368         QSqlQuery m_qry_get_directory_by_id;
369         QSqlQuery m_qry_get_directory_by_path;
370         QSqlQuery m_qry_get_codec_by_id;
371         QSqlQuery m_qry_get_codec_by_name;
372         QSqlQuery m_qry_get_audio_tracks_by_file_id;
373         QSqlQuery m_qry_get_audio_meta_by_file_id;
374         QSqlQuery m_qry_get_artist_by_id;
375         QSqlQuery m_qry_get_artist_by_name;
376         QSqlQuery m_qry_get_album_by_id;
377         QSqlQuery m_qry_get_album_by_name;
378         QSqlQuery m_qry_get_genre_by_id;
379         QSqlQuery m_qry_get_genre_by_name;
380         QSqlQuery m_qry_get_video_by_file_id;
381         QSqlQuery m_qry_get_location_by_id;
382         QSqlQuery m_qry_get_tag_by_id;
383         QSqlQuery m_qry_get_tag_by_name;
384
385         QSqlQuery m_qry_check_file;
386         QSqlQuery m_qry_check_directory;
387         QSqlQuery m_qry_check_codec;
388         QSqlQuery m_qry_check_audio_track;
389         QSqlQuery m_qry_check_artist;
390         QSqlQuery m_qry_check_album;
391         QSqlQuery m_qry_check_genre;
392         QSqlQuery m_qry_check_tag;
393
394         void processFileLists();
395         insert_result processSingleFile(const file_metadata &fmd, bool has_parent=false);
396         void gotMessage(const DbMessage &message);
397
398         QString genSelectAllById(const QString &table);
399         QString genSelectAllBySingleField(const QString &table, const QString &field);
400         QString genSelectGetIdSimple(const QString &table, const QString &field);
401
402         const long long getIdSimple(QSqlQuery *statement, bool clear = true);
403         insert_result insertError(int id=INSERT_ERROR);
404         insert_result insertAndCleanup(QSqlQuery *statement);
405
406         insert_result getSetDirectory(int parent_id, const std::string &path, bool parent = false, bool watch = false);
407         insert_result getSetFile(int dir_id, const std::string &name, int64_t size, int type, int64_t duration, int64_t lastmodified, int popularity=0, int64_t lastplaypos=0 );
408         int getFileLastModified(int dir_id, const std::string &name, file_data *data);
409         insert_result getSetCodec(const std::string &codec, const std::string &codec_long);
410         insert_result setAudioTrack(int file_id, int codec_id, const std::string &lang);
411         insert_result getSetArtist(const std::string &artist);
412         insert_result getSetAlbum(int artist_id, const std::string &album);
413         insert_result getSetGenre(const std::string &genre);
414         insert_result setAudioMeta(int file_id, int artist_id, int album_artist_id, int album_id, int genre_id, const audio_metadata &amd);
415         insert_result setVideoTrack(int file_id, int codec_id, const video_data &vd);
416 };
417 #endif //eDatabaseThread
418 #endif