diff --git a/inc/lektor/common.h b/inc/lektor/common.h index 8bb0b59b101b6d41f892a48b879ece1d731668e5..a8bebd266fb987126c4a704b26e8bd4a8a8ab021 100644 --- a/inc/lektor/common.h +++ b/inc/lektor/common.h @@ -44,6 +44,8 @@ extern EXIT_FUNCTION ___not_implemented(const char *func, char *file, int line); } \ } +#define unless(cond) if (!(cond)) + #define FAIL_UNLESS(cond, ...) FAIL_IF(!(cond), __VA_ARGS__) #define GOTO_UNLESS(cond, msg, label) GOTO_IF(!(cond), msg, label) #define RETURN_UNLESS(cond, msg, ret) RETURN_IF(!(cond), msg, ret) diff --git a/inc/lektor/internal/dbmacro.h b/inc/lektor/internal/dbmacro.h index e55d5068ed10dae3436c55c6351b0cba3216555b..e99f413ebc17de660aae1757d088eb27f57ba49d 100644 --- a/inc/lektor/internal/dbmacro.h +++ b/inc/lektor/internal/dbmacro.h @@ -62,6 +62,8 @@ #define SQLITE_STEP_ROW(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_ROW, error) #define SQLITE_STEP_DONE(db, stmt, error) SQLITE_STEP(db, stmt, SQLITE_DONE, error) +#define SQLITE_BEGIN_TRANSATION(db, error) SQLITE_EXEC(db, "BEGIN TRANSATION;", error) +#define SQLITE_END_TRANSATION(db, error) SQLITE_EXEC(db, "END TRANSATION;", error) #define SQLITE_DO_ROLLBACK(db) \ LOG_WARN("DB-DEBUG", "DO ROLLBACK \\o/"); \ sqlite3_exec((sqlite3 *)db, "ROLLBACK TRANSACTION;\n", NULL, NULL, NULL); diff --git a/src/database/queue.c b/src/database/queue.c index 221c7cc3c6c02834caef32a82f2fd330f23b23a3..1fe0c1ea2dbfb3d9760e7d7ed3e66dc10d354856 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -98,8 +98,8 @@ database_queue_playtime(lkt_db *db, uint64_t *seconds) static const char *SQL = "SELECT SUM(cached_duration) " "FROM kara " "JOIN queue ON queue.kara_id = kara.id;"; - sqlite3_stmt *stmt = NULL; - *seconds = 0; + sqlite3_stmt *stmt = NULL; + *seconds = 0; SQLITE_PREPARE(db, stmt, SQL, error); SQLITE_STEP_ROW(db, stmt, error); *seconds = (uint64_t)sqlite3_column_int(stmt, 0); @@ -130,8 +130,8 @@ database_queue_current_kara(lkt_db *db, struct kara_metadata *res, int *id) " FROM kara" " JOIN queue ON kara_id = kara.id" " JOIN queue_state ON current = position"; - sqlite3_stmt *stmt = NULL; - int ret = false; + sqlite3_stmt *stmt = NULL; + int ret = false; SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_STEP_ROW(db, stmt, error); @@ -289,7 +289,7 @@ database_queue_add_id(lkt_db *db, int id, int priority) " SELECT kara.id, ?" " FROM kara" " WHERE kara.id = ?;"; - sqlite3_stmt *stmt = NULL; + sqlite3_stmt *stmt = NULL; SQLITE_EXEC(db, "BEGIN TRANSACTION;", error); SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_INT(db, stmt, 1, priority, error); @@ -369,6 +369,8 @@ error: bool database_queue_del_pos(lkt_db *db, int pos) { + /* /!\ WARNING: UGLY GOTOS AT THE END OF THE FUNCTION /!\ */ + bool sta = false; sqlite3_stmt *stmt = NULL; struct lkt_queue_state queue = { .current = -1 }; @@ -435,6 +437,23 @@ error_no_rollback: return sta; } +/* When a kara has been played, MPD specify that its priority shall be reset, + * thus we set it to 1 before passing to the next kara. It's not done when + * passing to the previous kara because the reorder operation would break + * everything in the queue. */ +PRIVATE_FUNCTION bool +___database_queue_reset_current_priority(lkt_db *db) +{ + static const char *SQL_STMT = "UPDATE queue" + " SET priority = 1" + " WHERE position = (SELECT current FROM queue_state LIMIT 1);"; + SQLITE_EXEC(db, SQL_STMT, error); + return true; +error: + LOG_ERROR("DB", "Failed to reset the priority of played kara!"); + return false; +} + bool database_queue_next(lkt_db *db, char filepath[PATH_MAX]) { @@ -454,6 +473,9 @@ database_queue_next(lkt_db *db, char filepath[PATH_MAX]) int code = SQLITE_OK, id; sqlite3_stmt *stmt = NULL; + SQLITE_BEGIN_TRANSATION(db, error_no_stmt); + unless (___database_queue_reset_current_priority(db)) + goto error_no_stmt; SQLITE_PREPARE(db, stmt, SQL_STMT, error); code = sqlite3_step(stmt); @@ -482,9 +504,12 @@ database_queue_next(lkt_db *db, char filepath[PATH_MAX]) } SQLITE_EXEC(db, SQL_UPDATE, error); + SQLITE_END_TRANSATION(db, error); status = true; error: sqlite3_finalize(stmt); +error_no_stmt: + SQLITE_DO_ROLLBACK(db); return status; } @@ -558,8 +583,8 @@ database_queue_swap(lkt_db *db, int from, int to) "SELECT position, priority, kara_id FROM queue WHERE position = ?;"; static const char *SQL_POP_ROW_2 = "DELETE FROM queue WHERE position = ?;"; static const char *SQL_SLAP_MAX = "UPDATE " LKT_PROTECTED_DATABASE ".sqlite_sequence" - " SET seq = (SELECT COUNT(position) FROM queue)" - " WHERE name = 'queue';"; + " SET seq = (SELECT COUNT(position) FROM queue)" + " WHERE name = 'queue';"; static const char *SQL_PUSH_ROW = "INSERT INTO queue (position, priority, kara_id) VALUES (?, ?, ?);"; @@ -693,9 +718,9 @@ database_queue_play(lkt_db *db, int pos) { static const char *SQL_STMT = "UPDATE queue_state SET current = ?, paused = 0" " WHERE current <= 0 OR current IS NULL"; - int code = SQLITE_OK; - bool ret = false; - sqlite3_stmt *stmt = NULL; + int code = SQLITE_OK; + bool ret = false; + sqlite3_stmt *stmt = NULL; SQLITE_PREPARE(db, stmt, SQL_STMT, error); SQLITE_BIND_INT(db, stmt, 1, pos, error); @@ -741,9 +766,9 @@ database_queue_get_current_file(lkt_db *db, char filepath[PATH_MAX]) " FROM kara" " JOIN queue ON kara.id = queue.kara_id" " JOIN queue_state ON queue.position = queue_state.current"; - bool status = false; - int code = SQLITE_OK; - sqlite3_stmt *stmt = NULL; + bool status = false; + int code = SQLITE_OK; + sqlite3_stmt *stmt = NULL; if (filepath == NULL) goto error; @@ -947,8 +972,8 @@ database_queue_dump(lkt_db *db, const char *plt_name) " SELECT DISTINCT kara_id, plt_id.id" " FROM queue, plt_id" " ORDER BY RANDOM();"; - bool ret_code = false; - sqlite3_stmt *stmt = NULL; + bool ret_code = false; + sqlite3_stmt *stmt = NULL; SQLITE_PREPARE(db, stmt, SQL, error); SQLITE_BIND_TEXT(db, stmt, 1, plt_name, error); SQLITE_STEP_DONE(db, stmt, error);