mdb_txn_abort(tx);
}
+int dbstate_get(MDB_txn *tx, dbindex *db, dbstate *s) {
+ MDB_val key = { .mv_data = "state", .mv_size = strlen("state") };
+ MDB_val data;
+
+ db->res = mdb_get(tx, db->meta, &key, &data);
+
+ if (db->res == 0) {
+ dbstate *p = (dbstate *)data.mv_data;
+ if (p->size != sizeof(dbstate))
+ return MDB_NOTFOUND;
+ *s = *p;
+ return 0;
+ }
+
+ return db->res;
+}
+
+int dbstate_put(MDB_txn *tx, dbindex *db, dbstate *s) {
+ MDB_val key = { .mv_data = "state", .mv_size = strlen("state") };
+ MDB_val data = { .mv_data = s, .mv_size = sizeof(*s) };
+
+ s->size = sizeof(dbstate);
+
+ return mdb_put(tx, db->meta, &key, &data, 0);
+}
+
// get by_path key
static char *dbfile_path(dbfile *f) {
char *path = malloc(strlen(f->path) + 9);
Player support functions
*/
-// A way to iterate through a lit of files, based on an index or something else
-struct dblist {
-};
-
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
char *artist; // music artist
};
+/* player state, this is passed around as a struct */
+typedef struct dbstate dbstate;
+
+struct dbstate {
+ uint32_t size; // don't need to initialise
+ uint32_t state; // some info on playing
+ uint32_t fileid; // file being played
+ uint64_t pos; // last approximate position
+ time_t stamp; // last update time
+};
+
typedef struct dbindex dbindex;
typedef struct MDB_txn dbtxn;
typedef struct dbscan dbscan;
void dbindex_commit(dbtxn *tx);
void dbindex_abort(dbtxn *tx);
+int dbstate_get(dbtxn *tx, dbindex *db, dbstate *s);
+int dbstate_put(dbtxn *tx, dbindex *db, dbstate *s);
+
+dbdisk *dbdisk_get(dbtxn *tx, dbindex *db, int diskid);
dbdisk *dbdisk_get_uuid(dbtxn *tx, dbindex *db, const char *uuid);
void dbdisk_free(dbdisk *d);
int dbdisk_add(dbtxn *txn, dbindex *db, dbdisk *d);
dbindex *index;
dbfile *playing;
char *playing_path;
+ dbstate playing_state;
int quit;
int paused;
char *data[1]; // data pointers for current output, planar or not, may point to 'buffer'
int nsamples; // nsamples remaining for output
-
};
int audio_mixer_adjust(struct audio_player *ap, int delta);
return -1;
}
+int audio_checkpoint_state(struct audio_player *ap) {
+ dbtxn *tx = dbindex_begin(ap->index, NULL, 0);
+
+ if (tx) {
+ // TODO: meaningful state value
+ if (ap->playing) {
+ ap->playing_state.state = 1;
+ ap->playing_state.fileid = ap->playing->id;
+ } else {
+ ap->playing_state.state = 0;
+ ap->playing_state.fileid = 0;
+ }
+ printf("checkpoint state=%d file=%d '%s'\n", ap->playing_state.state, ap->playing_state.fileid, ap->playing_path);
+ // ap->pos?
+ ap->playing_state.pos = 0;
+ ap->playing_state.stamp = time(NULL);
+ if (dbstate_put(tx, ap->index, &ap->playing_state) == 0) {
+ dbindex_commit(tx);
+ } else {
+ dbindex_abort(tx);
+ }
+ }
+
+ return 0;
+}
+
// Next in play queue
int audio_next_file(struct audio_player *ap) {
int res;
int empty = ap->playing == NULL;
audio_close_media(ap);
+
do {
//res = dbfile_next(ap->index, &ap->playing, &ap->playing_path);
printf("a ap playing = %d\n", ap->playing ? ap->playing->id : -1);
res = 1;
} while (res != 0 && res !=(-30798)); // MDB_NOTFOUND
+ audio_checkpoint_state(ap);
+
//if (res != 0) {
// audio_stop_pcm(ap);
//}
res = 1;
} while (res != 0 && res !=(-30798)); // MDB_NOTFOUND
+ audio_checkpoint_state(ap);
+
//if (res != 0) {
// audio_stop_pcm(ap);
//}
return res;
}
+// first file on restarting server, see if we were playing something last time and start back there
+// TODO: do something with the position
+int audio_restore_state(struct audio_player *ap) {
+ dbtxn *tx = dbindex_begin(ap->index, NULL, 1);
+ int res = -1;
+
+ if (dbstate_get(tx, ap->index, &ap->playing_state) == 0 && ap->playing_state.state == 1) {
+ dbfile *file = dbfile_get(tx, ap->index, ap->playing_state.fileid);
+
+ if (file) {
+ dbdisk *disk = dbdisk_get(tx, ap->index, file->diskid);
+
+ if (disk) {
+ char path[strlen(disk->mount) + strlen(file->path) + 1];
+
+ sprintf(path, "%s%s", disk->mount, file->path);
+ ap->playing = file;
+ ap->playing_path = strdup(path);
+
+ dbdisk_free(disk);
+
+ res = audio_init_media(ap, ap->playing_path);
+ } else {
+ dbfile_free(file);
+ }
+ }
+ }
+
+ dbindex_commit(tx);
+
+ printf("restore state=%d file=%d '%s'\n", ap->playing_state.state, ap->playing_state.fileid, ap->playing_path);
+
+ if (res == 0)
+ return res;
+
+ return audio_next_file(ap);
+}
+
+
void audio_player_control(struct audio_player *ap) {
int ready = notify_msg_ready(ap->player);
AVFrame *frame = av_frame_alloc();
AVFrame *oframe = av_frame_alloc();
- audio_next_file(ap);
+ audio_restore_state(ap);
while (1) {
int res;