00001 #include <lightmediascanner_db.h> 00002 #include "lightmediascanner_db_private.h" 00003 #include <stdlib.h> 00004 #include <stdio.h> 00005 00006 struct lms_db_playlist { 00007 sqlite3 *db; 00008 sqlite3_stmt *insert; 00009 unsigned int _references; 00010 unsigned int _is_started:1; 00011 }; 00012 00013 static struct lms_db_cache _cache = {0, NULL}; 00014 00015 static int 00016 _db_table_updater_playlists_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { 00017 char *errmsg; 00018 int r, ret; 00019 00020 errmsg = NULL; 00021 r = sqlite3_exec(db, 00022 "CREATE TABLE IF NOT EXISTS playlists (" 00023 "id INTEGER PRIMARY KEY, " 00024 "title TEXT, " 00025 "n_entries INTEGER NOT NULL" 00026 ")", 00027 NULL, NULL, &errmsg); 00028 if (r != SQLITE_OK) { 00029 fprintf(stderr, "ERROR: could not create 'playlists' table: %s\n", 00030 errmsg); 00031 sqlite3_free(errmsg); 00032 return -1; 00033 } 00034 00035 r = sqlite3_exec(db, 00036 "CREATE INDEX IF NOT EXISTS playlists_title_idx ON " 00037 "playlists (title)", 00038 NULL, NULL, &errmsg); 00039 if (r != SQLITE_OK) { 00040 fprintf(stderr, 00041 "ERROR: could not create 'playlists_title_idx' index: %s\n", 00042 errmsg); 00043 sqlite3_free(errmsg); 00044 return -2; 00045 } 00046 00047 ret = lms_db_create_trigger_if_not_exists(db, 00048 "delete_playlists_on_files_deleted " 00049 "DELETE ON files FOR EACH ROW BEGIN " 00050 " DELETE FROM playlists WHERE id = OLD.id; END;"); 00051 if (ret != 0) 00052 goto done; 00053 00054 ret = lms_db_create_trigger_if_not_exists(db, 00055 "delete_files_on_playlists_deleted " 00056 "DELETE ON playlists FOR EACH ROW BEGIN " 00057 " DELETE FROM files WHERE id = OLD.id; END;"); 00058 00059 done: 00060 return ret; 00061 } 00062 00063 static lms_db_table_updater_t _db_table_updater_playlists[] = { 00064 _db_table_updater_playlists_0 00065 }; 00066 00067 00068 static int 00069 _db_create_table_if_required(sqlite3 *db) 00070 { 00071 return lms_db_table_update_if_required(db, "playlists", 00072 LMS_ARRAY_SIZE(_db_table_updater_playlists), 00073 _db_table_updater_playlists); 00074 } 00075 00090 lms_db_playlist_t * 00091 lms_db_playlist_new(sqlite3 *db) 00092 { 00093 lms_db_playlist_t *ldp; 00094 void *p; 00095 00096 if (lms_db_cache_get(&_cache, db, &p) == 0) { 00097 ldp = p; 00098 ldp->_references++; 00099 return ldp; 00100 } 00101 00102 if (!db) 00103 return NULL; 00104 00105 if (_db_create_table_if_required(db) != 0) { 00106 fprintf(stderr, "ERROR: could not create table.\n"); 00107 return NULL; 00108 } 00109 00110 ldp = calloc(1, sizeof(lms_db_playlist_t)); 00111 ldp->_references = 1; 00112 ldp->db = db; 00113 00114 if (lms_db_cache_add(&_cache, db, ldp) != 0) { 00115 lms_db_playlist_free(ldp); 00116 return NULL; 00117 } 00118 00119 return ldp; 00120 } 00121 00134 int 00135 lms_db_playlist_start(lms_db_playlist_t *ldp) 00136 { 00137 if (!ldp) 00138 return -1; 00139 if (ldp->_is_started) 00140 return 0; 00141 00142 ldp->insert = lms_db_compile_stmt(ldp->db, 00143 "INSERT OR REPLACE INTO playlists (id, title, n_entries) " 00144 "VALUES (?, ?, ?)"); 00145 if (!ldp->insert) 00146 return -2; 00147 00148 ldp->_is_started = 1; 00149 return 0; 00150 } 00151 00164 int 00165 lms_db_playlist_free(lms_db_playlist_t *ldp) 00166 { 00167 int r; 00168 00169 if (!ldp) 00170 return -1; 00171 if (ldp->_references == 0) { 00172 fprintf(stderr, "ERROR: over-called lms_db_playlist_free(%p)\n", ldp); 00173 return -1; 00174 } 00175 00176 ldp->_references--; 00177 if (ldp->_references > 0) 00178 return 0; 00179 00180 if (ldp->insert) 00181 lms_db_finalize_stmt(ldp->insert, "insert"); 00182 00183 r = lms_db_cache_del(&_cache, ldp->db, ldp); 00184 free(ldp); 00185 00186 return r; 00187 } 00188 00189 static int 00190 _db_insert(lms_db_playlist_t *ldp, const struct lms_playlist_info *info) 00191 { 00192 sqlite3_stmt *stmt; 00193 int r, ret; 00194 00195 stmt = ldp->insert; 00196 00197 ret = lms_db_bind_int64(stmt, 1, info->id); 00198 if (ret != 0) 00199 goto done; 00200 00201 ret = lms_db_bind_text(stmt, 2, info->title.str, info->title.len); 00202 if (ret != 0) 00203 goto done; 00204 00205 ret = lms_db_bind_int(stmt, 3, info->n_entries); 00206 if (ret != 0) 00207 goto done; 00208 00209 r = sqlite3_step(stmt); 00210 if (r != SQLITE_DONE) { 00211 fprintf(stderr, "ERROR: could not insert playlist info: %s\n", 00212 sqlite3_errmsg(ldp->db)); 00213 ret = -4; 00214 goto done; 00215 } 00216 00217 ret = 0; 00218 00219 done: 00220 lms_db_reset_stmt(stmt); 00221 00222 return ret; 00223 } 00224 00236 int 00237 lms_db_playlist_add(lms_db_playlist_t *ldp, struct lms_playlist_info *info) 00238 { 00239 if (!ldp) 00240 return -1; 00241 if (!info) 00242 return -2; 00243 if (info->id < 1) 00244 return -3; 00245 00246 return _db_insert(ldp, info); 00247 }