diff --git a/CHANGELOG.md b/CHANGELOG.md index 832792fdb8d9ca0b4118b0bb9252813eee072a39..dfe2c0f489ba2e1607920ce22848b6b580141c0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Add SDL2-Image lib to the dependencies (--with-depends) - Add klkt autolaunch option to config file - Remove archlinux package support (replaced by AppImage) +- Add MPD commands: seek, seekid, seekcur, delete (partial) - Fix dl process with the repo module - Fix: the moveid was in fact a move command, no range supported - Bug fix: reduce libs to link to lkt (dear autoconf...) diff --git a/README.md b/README.md index 0e19ed3af58660f4b2668fe6a9025d5ead2c3eea..3f3f16deb69bf9ac0466d0edd252334907c54160 100644 --- a/README.md +++ b/README.md @@ -184,84 +184,84 @@ For the compatibility column, the possible values are the following: - `TODO`: marked as 'to be implemented', check the next releases if it is implemented - nothing: has not been implemented and is not a priority -| MPD command | lektord command | compatibility | compatibility note | -| --------------------------------- | ------------------------- | :-----------: | ----------------------------------------------- | -| `clearerror` | | | not implemented | -| `currentsong` | `currentsong` | ~ | use the lektord tags, not MPD once | -| `idle [subsistem]` | `idle [subsistem]` | + | | -| `status` | `status` | ~ | slight differencies in the duration and time, not working with mpc | -| `stats` | `stats` | ~ | don't send all the stats, only `db_update` | -| `consume {state}` | `consume {state}` | + | | -| `random {state}` | `random {state}` | + | | -| `repeat {state}` | `repeat {state}` | + | | -| `setvol {vol}` | `setvol {vol}` | + | won't display the correct volume, mpv properties flush issue... | -| `getvol` | `getvol` | + | will display the correct value after the end of the kara | -| `single {state}` | `single {state}` | + | | -| `replay_gain_mode {mode}` | | | not implemented | -| `replay_gain_status` | | | not implemented | -| `next` | `next` | + | | -| `pause {state}` | `pause {state}` | CHECK | check compat state | -| `play [songpos]` | `play [songpos]` | + | if no `songpos` passed, defaults to `0` | -| `playid [songid]` | `playid {songid}` | + | get the first found `songid` in the queue | -| `previous` | `previous` | + | | -| `seek {songpos} {time}` | `seek {songpos} {time}` | + | | -| `seekid {songid} {time}` | `seekid {songid} {time}` | + | seek to the first found id, sqlite dependent | -| `seekcur {time}` | `seekcur {time}` | + | | -| `stop` | `stop` | + | | -| `add {uri}` | `add {uri}` | + | | -| `addid {id} [pos]` | `addid {id...}` | ~ | can add multiple songs, but no position support | -| `clear` | `clear` | + | | -| `delete [{POS}/{start:end}]` | | TODO | not implemented | -| `deleteid {songid}` | `deleteid {songid}` | + | delete all kara with that id, skip the current kara if needed | -| `move [{from}/{start:end}] {to}` | | TODO | not implemented | -| `moveid {from} {to}` | `moveid {from} {to}` | ~ | `to` is always an absolute position | -| `playlist` | `playlist` | + | | -| `playlistfind {tag} {needle}` | `playlistfind {uri}` | ~ | uses lektord URIs | -| `playlistid {songid}` | | TODO | not implemented | -| `playlistinfo [[songpos]/[start:end]]` | `playlistinfo` | - | is an alias to `playlist` | -| `playlistsearch {taf} {needle}` | `playlistsearch {uri}` | ~ | uses lektord URIs | -| `plchanges {version} [start:end]` | | | not implemented | -| `plchangesposid {version} [start:end]` | | | not implemented | -| `prio {prio} {start:end}` | | | not implemented | -| `prioid {prio} {id...}` | | | not implemented | -| `rangeid {id} {start:end}` | | | not implemented | -| `shuffle [start:end]` | `shuffle` | ~ | shuffles all the queue | -| `swap {song1} {song2}` | | TODO | not implemented | -| `swap {songid1} {songid2}` | | | not implemented | -| `listplaylist {name}` | `listplaylist {name}` | + | | -| `listplaylistinfo {name}` | `listplaylistinfo {name} {uri}` | - | do a search in the playlist | -| `listplaylists` | `listplaylists` | + | | -| `load {name} [start:end]` | | | not implemented, use `add {uri}` to do that | -| `playlistadd {name} {uri}` | `playlistadd {name} {uri}` | ~ | uses lektord URIs | -| `playlistclear {name}` | `playlistclear {name}` | + | | -| `playlistdelete {name} {songpos}` | `playlistdelete {name} [songid]` | ~ | delete all the playlist if `songpos` is not spesified, uses kara ids, not pos | -| `rename {name} {newname}` | `rename {name} {newname}` | ~ | will fail if the `newplaylist` already exists | -| `rm {name}` | `rm {name}` | + | | -| `save {name}` | `save {name} {destdb}` | - | export a part of the db into as sqlite3 db | -| `count {filt} [group {grptype}]` | | | not implemted | -| `getfingerprint {uri}` | | | not implemted | -| `find {filt} [sort {type}] [window {START:END}]` | `find {uri}` | - | do a simple search in the db with lektord's URIs | -| `findadd {filt} [sort {type}] [window {start:end}]` | `findadd {uri}` | - | same remarks as `find` | -| `list {type} {filt} [group {grptype}]` | | | not implemented | -| `listall [uri]` | | | not implemented | -| `listallinfo [uri]` | | | not implemented | -| `listfiles {uri}` | | | not implemented | -| `lsinfo [uri]` | | | not implemented | -| `search {filt} [sort {type}] [window {start:end}]` | `search {uri}` | - | is an alias to `find` | -| `searchadd {filt} [sort {type}] [window {start:end}]` | `searchadd {uri}` | - | is an alias to `findadd` | -| `update [uri]` | `update` | ~ | doesn't take URIs | -| `rescan [uri]` | `rescan` | ~ | doesn't take URIs | -| `close` | `close` | + | send the `OK` status before closing the socket | -| `kill` | `kill` | + | | -| `password {password}` | `password {password}` | + | | -| `ping` | `ping` | + | | -| `config` | | | not implemented | -| `sticker get {t} {uri} {n}` | `sticker get {type} {uri} {name}` | CHECK | check the return conventions | -| `sticker set {t} {uri} {n} {val}` | `sticker set {t} {uri} {n} {val}` | CHECK | check the return conventions | -| `sticker delete {t} {uri} [n]` | `sticker delete {t} {uri} [n]` | CHECK | check the return conventions | -| `sticker list {type} {uri}` | `sticker list {type} {uri}` | CHECK | check the return conventions | -| `sticker find {t} {uri} {n}` | `sticker find {t} {uri} {n}` | CHECK | check the return conventions | -| `sticker find {t} {uri} {n} {op} {v}` | `sticker find {t} {uri} {n} {op} {v}` | CHECK | check the return conventions, operators are `g`, `e` and `l` | +| MPD command | lektord command | compatibility | compatibility note | +| ----------------------------------------- | ----------------------------- | :-----------: | ----------------------------------------------- | +| `clearerror` | | | not implemented | +| `currentsong` | `currentsong` | ~ | use the lektord tags, not MPD once | +| `idle [subsistem]` | `idle [subsistem]` | + | | +| `status` | `status` | ~ | slight differencies in the duration and time, not working with mpc | +| `stats` | `stats` | ~ | don't send all the stats, only `db_update` | +| `consume {state}` | `consume {state}` | + | | +| `random {state}` | `random {state}` | + | | +| `repeat {state}` | `repeat {state}` | + | | +| `setvol {vol}` | `setvol {vol}` | + | won't display the correct volume, mpv properties flush issue... | +| `getvol` | `getvol` | + | will display the correct value after the end of the kara | +| `single {state}` | `single {state}` | + | | +| `replay_gain_mode {mode}` | | | not implemented | +| `replay_gain_status` | | | not implemented | +| `next` | `next` | + | | +| `pause {state}` | `pause {state}` | CHECK | check compat state | +| `play [songpos]` | `play [songpos]` | + | if no `songpos` passed, defaults to `0` | +| `playid [songid]` | `playid {songid}` | + | get the first found `songid` in the queue | +| `previous` | `previous` | + | | +| `seek {songpos} {time}` | `seek {songpos} {time}` | + | | +| `seekid {songid} {time}` | `seekid {songid} {time}` | + | seek to the first found id, sqlite dependent | +| `seekcur {time}` | `seekcur {time}` | + | | +| `stop` | `stop` | + | | +| `add {uri}` | `add {uri}` | + | | +| `addid {id} [pos]` | `addid {id...}` | ~ | can add multiple songs, but no position support | +| `clear` | `clear` | + | | +| `delete [{pos}/{start:end}]` | `delete {pos}` | - | can take only one position | +| `deleteid {songid}` | `deleteid {songid}` | + | delete all kara with that id, skip the current kara if needed | +| `move [{from}/{start:end}] {to}` | | TODO | not implemented | +| `moveid {from} {to}` | `moveid {from} {to}` | ~ | `to` is always an absolute position | +| `playlist` | `playlist` | + | | +| `playlistfind {tag} {needle}` | `playlistfind {uri}` | ~ | uses lektord URIs | +| `playlistid {songid}` | | TODO | not implemented | +| `playlistinfo [[songpos]/[start:end]]` | `playlistinfo` | - | is an alias to `playlist` | +| `playlistsearch {taf} {needle}` | `playlistsearch {uri}` | ~ | uses lektord URIs | +| `plchanges {version} [start:end]` | | | not implemented | +| `plchangesposid {version} [start:end]` | | | not implemented | +| `prio {prio} {start:end}` | | | not implemented | +| `prioid {prio} {id...}` | | | not implemented | +| `rangeid {id} {start:end}` | | | not implemented | +| `shuffle [start:end]` | `shuffle` | ~ | shuffles all the queue | +| `swap {song1} {song2}` | | TODO | not implemented | +| `swap {songid1} {songid2}` | | | not implemented | +| `listplaylist {name}` | `listplaylist {name}` | + | | +| `listplaylistinfo {name}` | `listplaylistinfo {name} {uri}` | - | do a search in the playlist | +| `listplaylists` | `listplaylists` | + | | +| `load {name} [start:end]` | | | not implemented, use `add {uri}` to do that | +| `playlistadd {name} {uri}` | `playlistadd {name} {uri}` | ~ | uses lektord URIs | +| `playlistclear {name}` | `playlistclear {name}` | + | | +| `playlistdelete {name} {songpos}` | `playlistdelete {name} [songid]` | ~ | delete all the playlist if `songpos` is not spesified, uses kara ids, not pos | +| `rename {name} {newname}` | `rename {name} {newname}` | ~ | will fail if the `newplaylist` already exists | +| `rm {name}` | `rm {name}` | + | | +| `save {name}` | `save {name} {destdb}` | - | export a part of the db into as sqlite3 db | +| `count {filt} [group {grptype}]` | | | not implemted | +| `getfingerprint {uri}` | | | not implemted | +| `find {filt} [sort {type}] [window {START:END}]` | `find {uri}` | - | do a simple search in the db with lektord's URIs | +| `findadd {filt} [sort {type}] [window {start:end}]` | `findadd {uri}` | - | same remarks as `find` | +| `list {type} {filt} [group {grptype}]` | | | not implemented | +| `listall [uri]` | | | not implemented | +| `listallinfo [uri]` | | | not implemented | +| `listfiles {uri}` | | | not implemented | +| `lsinfo [uri]` | | | not implemented | +| `search {filt} [sort {type}] [window {start:end}]` | `search {uri}` | - | is an alias to `find` | +| `searchadd {filt} [sort {type}] [window {start:end}]` | `searchadd {uri}` | - | is an alias to `findadd` | +| `update [uri]` | `update` | ~ | doesn't take URIs | +| `rescan [uri]` | `rescan` | ~ | doesn't take URIs | +| `close` | `close` | + | send the `OK` status before closing the socket | +| `kill` | `kill` | + | | +| `password {password}` | `password {password}` | + | | +| `ping` | `ping` | + | | +| `config` | | | not implemented | +| `sticker get {t} {uri} {n}` | `sticker get {type} {uri} {name}` | CHECK | check the return conventions | +| `sticker set {t} {uri} {n} {val}` | `sticker set {t} {uri} {n} {val}` | CHECK | check the return conventions | +| `sticker delete {t} {uri} [n]` | `sticker delete {t} {uri} [n]` | CHECK | check the return conventions | +| `sticker list {type} {uri}` | `sticker list {type} {uri}` | CHECK | check the return conventions | +| `sticker find {t} {uri} {n}` | `sticker find {t} {uri} {n}` | CHECK | check the return conventions | +| `sticker find {t} {uri} {n} {op} {v}` | `sticker find {t} {uri} {n} {op} {v}` | CHECK | check the return conventions, operators are `g`, `e` and `l` | ### Commands specific to lektord @@ -277,43 +277,43 @@ For the compatibility column, the possible values are the following: ### Commands with no plan for support -| MPD command | Reason / notes | -| --------------------------------- | --------------------------------------------- | -| `readcomments {uri}` | really not a priority | -| `readpicture {uri} {offset}` | really not a priority | -| `albumart {uri} {offset}` | really not a priority | -| `mount {path} {uri}` | no necessity in lektord | -| `unmount {path}` | no necessity in lektord | -| `listmounts` | no necessity in lektord | -| `listneighbors` | no necessity in lektord | -| `partition {name}` | no necessity in lektord | -| `listpartitions` | no necessity in lektord | -| `newpartition {name}` | no necessity in lektord | -| `delpartition {name}` | no necessity in lektord | -| `tagtypes` | tags are handled by kurisu for the moment | -| `tagtypes disable {name...}` | tags are handled by kurisu for the moment | -| `tagtypes enable {name...}` | tags are handled by kurisu for the moment | -| `tagtypes clear` | tags are handled by kurisu for the moment | -| `tagtypes all` | tags are handled by kurisu for the moment | -| `addtagid {songid} {tag} {val}` | tags are handled by kurisu for the moment | -| `cleartagid {songid} [tag]` | tags are handled by kurisu for the moment | -| `crossfade {seconds}` | lektord uses libmpv | -| `mixrampdb {dB}` | lektord uses libmpv | -| `mixrampdelay {seconds}` | lektord uses libmpv | -| `moveoutput {outputname}` | lektord uses libmpv | -| `disableoutput {id}` | lektord uses libmpv | -| `enableoutput {id}` | lektord uses libmpv | -| `toggleoutput {id}` | lektord uses libmpv | -| `outputs` | lektord uses libmpv | -| `outputset {id} {name} {value}` | lektord uses libmpv | -| `commands` | not implemented | -| `notcommands` | not implemented | -| `urlhandlers` | not implemented | -| `decoders` | lektord only suprts mkv files (for mkv tags) | -| `subscribe {name}` | no necessity for p2p messages for the moment | -| `unsubscribe {name}` | no necessity for p2p messages for the moment | -| `channels` | no necessity for p2p messages for the moment | -| `readmessages` | no necessity for p2p messages for the moment | -| `sendmessage {channel} {text}` | no necessity for p2p messages for the moment | -| `searchaddpl {name} {filt} [sort {type}] [window {start:end}]` | `playlistadd` exists | -| `playlistmove {name} {from} {to}` | no necessity in lektord as playlists are shuffled when added to the queue | +| MPD command | Reason / notes | +| ----------------------------------------------------------------- | --------------------------------------------- | +| `readcomments {uri}` | really not a priority | +| `readpicture {uri} {offset}` | really not a priority | +| `albumart {uri} {offset}` | really not a priority | +| `mount {path} {uri}` | no necessity in lektord | +| `unmount {path}` | no necessity in lektord | +| `listmounts` | no necessity in lektord | +| `listneighbors` | no necessity in lektord | +| `partition {name}` | no necessity in lektord | +| `listpartitions` | no necessity in lektord | +| `newpartition {name}` | no necessity in lektord | +| `delpartition {name}` | no necessity in lektord | +| `tagtypes` | tags are handled by kurisu for the moment | +| `tagtypes disable {name...}` | tags are handled by kurisu for the moment | +| `tagtypes enable {name...}` | tags are handled by kurisu for the moment | +| `tagtypes clear` | tags are handled by kurisu for the moment | +| `tagtypes all` | tags are handled by kurisu for the moment | +| `addtagid {songid} {tag} {val}` | tags are handled by kurisu for the moment | +| `cleartagid {songid} [tag]` | tags are handled by kurisu for the moment | +| `crossfade {seconds}` | lektord uses libmpv | +| `mixrampdb {dB}` | lektord uses libmpv | +| `mixrampdelay {seconds}` | lektord uses libmpv | +| `moveoutput {outputname}` | lektord uses libmpv | +| `disableoutput {id}` | lektord uses libmpv | +| `enableoutput {id}` | lektord uses libmpv | +| `toggleoutput {id}` | lektord uses libmpv | +| `outputs` | lektord uses libmpv | +| `outputset {id} {name} {value}` | lektord uses libmpv | +| `commands` | not implemented | +| `notcommands` | not implemented | +| `urlhandlers` | not implemented | +| `decoders` | lektord only suprts mkv files (for mkv tags) | +| `subscribe {name}` | no necessity for p2p messages for the moment | +| `unsubscribe {name}` | no necessity for p2p messages for the moment | +| `channels` | no necessity for p2p messages for the moment | +| `readmessages` | no necessity for p2p messages for the moment | +| `sendmessage {channel} {text}` | no necessity for p2p messages for the moment | +| `searchaddpl {name} {filt} [sort {type}] [window {start:end}]` | `playlistadd` exists | +| `playlistmove {name} {from} {to}` | no necessity in lektord as playlists are shuffled when added to the queue | diff --git a/inc/lektor/commands.h b/inc/lektor/commands.h index 0eb603cbb73672f7f0df08699762f79ea6b82ff1..a519b81ac1f5877eec5afda11c606174437ea617 100644 --- a/inc/lektor/commands.h +++ b/inc/lektor/commands.h @@ -36,6 +36,7 @@ bool command_set_pos(struct lkt_state *srv, int index); /* FIXME: Not used in ne /* The queue */ bool command_add (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX], int priority); bool command_addid (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]); +bool command_del (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]); bool command_delid (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]); bool command_clear (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]); bool command_crop (struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]); diff --git a/src/base/commands.c b/src/base/commands.c index 049afeb3785b8f371ce0352e13215c45c2a333c3..4c6f4afa6c6e43f2a7fc39aa718d34082351fea8 100644 --- a/src/base/commands.c +++ b/src/base/commands.c @@ -368,11 +368,54 @@ command_crop(struct lkt_state *srv, char UNUSED *args[LKT_MESSAGE_ARGS_MAX]) return database_queue_crop(srv->db); } +static inline bool +__skip_current(struct lkt_state *srv) +{ + char filepath[PATH_MAX]; + + if (database_queue_skip_current(srv->db, filepath)) { + if (MOD_CALL(srv->window_mod, "load", filepath)) { + LOG_ERROR("COMMAND", "Failed to skip current kara (loading %s)", filepath); + return false; + } + srv->mpd_idle_events |= MPD_IDLE_PLAYER; + } + + else { + LOG_WARN("COMMAND", "Failed to skip current kara, stop playback"); + MOD_PROC(srv->window_mod, "close"); + return false; + } + + LOG_DEBUG("COMMAND", "Skiped current kara and loaded %s instead", filepath); + return true; +} + +bool +command_del(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) +{ + struct lkt_queue_state queue = { .current = -2 /* Really need this field only */ }; + long pos = -1; + char *endptr = NULL, err = 0; + RETURN_UNLESS(args && args[0], "No position provided", false); + + STRTOL(pos, args[0], endptr, err); + RETURN_IF(err, "STRTOL failed", false); + + database_queue_state(srv->db, &queue); /* At worst, -1 != -2 */ + + RETURN_IF(pos == (long) queue.current && !__skip_current(srv), + "Failed to skip current kara", false); + + srv->mpd_idle_events |= MPD_IDLE_PLAYLIST; + return database_queue_del_pos(srv->db, pos); +} + bool command_delid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) { long id; - char *endptr = NULL, err = 0, filepath[PATH_MAX]; + char *endptr = NULL, err = 0; int uri = 0; RETURN_UNLESS(args[0], "No id provided", false); @@ -380,20 +423,7 @@ command_delid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) RETURN_IF(err, "STRTOL failed", false); database_queue_current_kara(srv->db, NULL, &uri); - - if (id == (long) uri) { - if (database_queue_skip_current(srv->db, filepath)) { - if (MOD_CALL(srv->window_mod, "load", filepath)) { - LOG_ERROR("COMMAND", "Failed to skip current kara to delete id %ld", id); - return false; - } - } - - else { - LOG_WARN("COMMAND", "Failed to skip current kara to delete id %ld, stop playback", id); - MOD_PROC(srv->window_mod, "close"); - } - } + RETURN_IF(id == (long) uri && !__skip_current(srv), "Failed to skip current kara", false); srv->mpd_idle_events |= MPD_IDLE_PLAYLIST; return database_queue_del_id(srv->db, id); @@ -697,8 +727,8 @@ command_set_pos(struct lkt_state *srv, int index) bool command_seek(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) { - int pos, seconds, err_flag; - char *endptr; + int pos, seconds, err_flag = 0; + char *endptr = NULL; RETURN_UNLESS(args && args[0] && args[1], "Invalid arguments", false); STRTOL(pos, args[0], endptr, err_flag); @@ -715,8 +745,8 @@ command_seek(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) bool command_seekid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) { - int id, seconds, err_flag, position; - char *endptr; + int id, seconds, err_flag = 0, position; + char *endptr = NULL; RETURN_UNLESS(args && args[0] && args[1], "Invalid arguments", false); STRTOL(id, args[0], endptr, err_flag); @@ -736,8 +766,8 @@ command_seekid(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) bool command_seekcur(struct lkt_state *srv, char *args[LKT_MESSAGE_ARGS_MAX]) { - int seconds, err_flag; - char *endptr; + int seconds, err_flag = 0; + char *endptr = NULL; RETURN_UNLESS(args && args[0], "Invalid arguments", false); STRTOL(seconds, args[0], endptr, err_flag); diff --git a/src/database/queue.c b/src/database/queue.c index 635c36445f4b5ea91c270d454509eba306ed75ff..69cd03651617e411a5812cd0da58382941d47cc3 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -317,6 +317,52 @@ error: return false; } +bool +database_queue_del_pos(volatile sqlite3 *db, int pos) +{ + bool sta = false; + sqlite3_stmt *stmt = NULL; + struct lkt_queue_state queue; + RETURN_UNLESS(database_queue_state(db, &queue), "Failed to get the queue state", false); + + /* Dec by one position... */ + if (queue.current > pos) { + static const char *SQL = + "BEGIN TRANSACTION;" + "UPDATE queue_state SET current = 1 - current;" + "DELETE FROM queue WHERE position = ?;" + "END TRANSACTION;"; + SQLITE_PREPARE(db, stmt, SQL, failed_in_delete_before); + SQLITE_BIND_INT(db, stmt, 1, pos, failed_in_delete_before); + SQLITE_STEP_DONE(db, stmt, failed_in_delete_before); + sta = true; +failed_in_delete_before: + sqlite3_finalize(stmt); + if (!sta) + SQLITE_DO_ROLLBACK(db); + return sta; + } + + /* EASY! */ + else if (queue.current < pos) { + static const char *SQL = "DELETE FROM queue WHERE position = ?;"; + SQLITE_PREPARE(db, stmt, SQL, failed_in_delete_after); + SQLITE_BIND_INT(db, stmt, 1, pos, failed_in_delete_after); + SQLITE_STEP_DONE(db, stmt, failed_in_delete_after); + sta = true; +failed_in_delete_after: + sqlite3_finalize(stmt); + return sta; + } + + /* Delete the current kara, can't do that because we need to skip it, and + * send signals to the window module to do so, so we just fail here... */ + else { + LOG_ERROR("DB", "Can't delete the currently playing kara at position %d in queue", pos); + return false; + } +} + bool database_queue_next(volatile sqlite3 *db, char filepath[PATH_MAX]) {