diff --git a/inc/lektor/database.h b/inc/lektor/database.h index e26b78f14089117b8bc4c83e49ecf6e248bbf5a9..475206c5e695c6419e26f7077487e4d6236edb19 100644 --- a/inc/lektor/database.h +++ b/inc/lektor/database.h @@ -30,7 +30,7 @@ bool database_detach(sqlite3 *db, const char *name); /* Get information on the queue and currently playing kara. */ bool database_queue_state(sqlite3 *db, struct lkt_queue_state *res); -bool database_queue_current_kara(sqlite3 *db, struct kara_metadata *res); +bool database_queue_current_kara(sqlite3 *db, struct kara_metadata *res, int *id); bool database_queue_set_paused(sqlite3 *db, bool paused); bool database_queue_set_current_index(sqlite3 *db, int idx); diff --git a/src/commands.c b/src/commands.c index cc65c13ab4f96061dedccdbc0462a0bdacc9f594..1c5254629204d094134de368286e49adac14bd12 100644 --- a/src/commands.c +++ b/src/commands.c @@ -98,7 +98,7 @@ command_currentsong(struct lkt_state *srv, size_t c) memset(&kara, 0, sizeof(struct kara_metadata)); - if (!database_queue_current_kara(srv->db, &kara)) + if (!database_queue_current_kara(srv->db, &kara, NULL)) fprintf(stderr, " ! command_currentsong: Failed to get information about the current kara\n"); out = lkt_message_new(); @@ -371,6 +371,7 @@ command_delid(sqlite3 *db, struct lkt_win *win, char *id_str, enum mpd_idle_flag (void) win; long id; char *endptr; + int uri = 0; errno = 0; *watch_mask_ptr |= MPD_IDLE_PLAYLIST; @@ -386,6 +387,15 @@ command_delid(sqlite3 *db, struct lkt_win *win, char *id_str, enum mpd_idle_flag return false; } + /* If one day we allow suppression of the current kara, will need the `win` + pointer to reload the kara in the same position (but the kara won't be + the same). */ + database_queue_current_kara(db, NULL, &uri); + if (id == (long) uri) { + fprintf(stderr, " . command_delid: Can't delete the currently playing kara\n"); + return false; + } + return database_queue_del_id(db, id); } diff --git a/src/database/queue.c b/src/database/queue.c index 473a03df24648a04240ef19495f9154657b746e8..1ec0e4292ae8c8821db2cfc6cddfdbd6335fbf54 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -53,10 +53,10 @@ error: } bool -database_queue_current_kara(sqlite3 *db, struct kara_metadata *res) +database_queue_current_kara(sqlite3 *db, struct kara_metadata *res, int *id) { static const char *SQL_STMT = - "SELECT song_name, source_name, category, language, author_name, song_type, song_number" + "SELECT song_name, source_name, category, language, author_name, song_type, song_number, kara_id" " FROM kara" " JOIN queue_ ON kara_id = kara.id" " JOIN queue_state ON current = position"; @@ -64,9 +64,12 @@ database_queue_current_kara(sqlite3 *db, struct kara_metadata *res) int ret = false; SQLITE_PREPARE(db, stmt, SQL_STMT, error); - memset(res, 0, sizeof(struct kara_metadata)); if (sqlite3_step(stmt) == SQLITE_ROW) { + /* Here use gotos because of optimisations done by compilators. + Most of the time it won't be NULL. */ + if (!res) + goto no_metadata; strncpy(res->song_name, (const char *) sqlite3_column_text(stmt, 0), LEKTOR_TAG_MAX - 1); strncpy(res->source_name, (const char *) sqlite3_column_text(stmt, 1), LEKTOR_TAG_MAX - 1); strncpy(res->category, (const char *) sqlite3_column_text(stmt, 2), LEKTOR_TAG_MAX - 1); @@ -74,6 +77,10 @@ database_queue_current_kara(sqlite3 *db, struct kara_metadata *res) strncpy(res->author_name, (const char *) sqlite3_column_text(stmt, 4), LEKTOR_TAG_MAX - 1); strncpy(res->song_type, (const char *) sqlite3_column_text(stmt, 5), LEKTOR_TAG_MAX - 1); res->song_number = sqlite3_column_int(stmt, 6); +no_metadata: + /* Most of the time this will be NULL. */ + if (id) + *id = sqlite3_column_int(stmt, 7); } else { fprintf(stderr, " ! database_queue_current_kara: failed: %s\n", sqlite3_errmsg(db)); @@ -307,14 +314,16 @@ bool database_queue_del_id(sqlite3 *db, int id) { static const char *SQL_TEMPLATE = - "WITH before(pos) AS (SELECT position FROM queue_ JOIN queue_state WHERE position < current ORDER BY position DESC LIMIT 1)" + "BEGIN TRANSACTION;" + "WITH before(pos) AS (SELECT position FROM queue_ JOIN queue_state WHERE position < current ORDER BY position DESC LIMIT 1) " "UPDATE queue_state SET current = CASE" " WHEN current IS NULL THEN NULL" - " ELSE (SELECT pos FROM before)" - "END WHERE current >= (SELECT position FROM queue_ WHERE kara_id = %d);" - "DELETE FROM queue WHERE kara_id = %d;"; + " ELSE (SELECT pos FROM before) " + "END WHERE current > (SELECT position FROM queue_ WHERE kara_id = %d);" + "DELETE FROM queue WHERE kara_id = %d;" + "COMMIT TRANSACTION;"; char SQL[LKT_MAX_SQLITE_STATEMENT]; - snprintf(SQL, LKT_MAX_SQLITE_STATEMENT - 1, SQL_TEMPLATE, id, id); + snprintf(SQL, LKT_MAX_SQLITE_STATEMENT - 1, SQL_TEMPLATE, id, id, id); SQL[LKT_MAX_SQLITE_STATEMENT - 1] = '\0'; SQLITE_EXEC(db, SQL, error); return true;