Add state support and startup state polling for the ui
This commit is contained in:
parent
dc2872309c
commit
1715d437e9
103
drmr.c
103
drmr.c
@ -159,12 +159,26 @@ connect_port(LV2_Handle instance,
|
||||
}
|
||||
}
|
||||
|
||||
static inline LV2_Atom* build_update_message(DrMr *drmr, const char* kit) {
|
||||
static inline LV2_Atom *build_update_message(DrMr *drmr) {
|
||||
LV2_Atom_Forge_Frame set_frame;
|
||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||
(&drmr->forge, &set_frame, 1, drmr->uris.ui_msg);
|
||||
if (drmr->current_path) {
|
||||
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.kit_path,0);
|
||||
lv2_atom_forge_string(&drmr->forge, kit, strlen(kit));
|
||||
lv2_atom_forge_string(&drmr->forge, drmr->current_path, strlen(drmr->current_path));
|
||||
}
|
||||
lv2_atom_forge_pop(&drmr->forge,&set_frame);
|
||||
return msg;
|
||||
}
|
||||
|
||||
static inline LV2_Atom *build_state_message(DrMr *drmr) {
|
||||
LV2_Atom_Forge_Frame set_frame;
|
||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||
(&drmr->forge, &set_frame, 1, drmr->uris.get_state);
|
||||
if (drmr->current_path) {
|
||||
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.kit_path,0);
|
||||
lv2_atom_forge_string(&drmr->forge, drmr->current_path, strlen(drmr->current_path));
|
||||
}
|
||||
lv2_atom_forge_pop(&drmr->forge,&set_frame);
|
||||
return msg;
|
||||
}
|
||||
@ -257,6 +271,10 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
|
||||
drmr->curReq = reqPos;
|
||||
if (tmp) free(tmp);
|
||||
}
|
||||
} else if (obj->body.otype == drmr->uris.get_state) {
|
||||
lv2_atom_forge_frame_time(&drmr->forge, 0);
|
||||
build_state_message(drmr);
|
||||
printf("Sent state message: %s\n",drmr->current_path);
|
||||
}
|
||||
}
|
||||
else printf("unrecognized event\n");
|
||||
@ -272,7 +290,8 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
|
||||
if (current_kit_changed) {
|
||||
current_kit_changed = 0;
|
||||
lv2_atom_forge_frame_time(&drmr->forge, 0);
|
||||
build_update_message(drmr,drmr->current_path);
|
||||
build_update_message(drmr);
|
||||
printf("Sent current path message\n");
|
||||
}
|
||||
|
||||
lv2_atom_forge_pop(&drmr->forge, &seq_frame);
|
||||
@ -330,7 +349,85 @@ static void cleanup(LV2_Handle instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void save_state(LV2_Handle instance,
|
||||
LV2_State_Store_Function store,
|
||||
void* handle,
|
||||
uint32_t flags,
|
||||
const LV2_Feature *const * features) {
|
||||
DrMr *drmr = (DrMr*)instance;
|
||||
LV2_State_Map_Path* map_path = NULL;
|
||||
while(*features) {
|
||||
if (!strcmp((*features)->URI, LV2_STATE__mapPath))
|
||||
map_path = (LV2_State_Map_Path*)((*features)->data);
|
||||
features++;
|
||||
}
|
||||
|
||||
if (map_path == NULL) {
|
||||
fprintf(stderr,"Host does not support map_path, cannot save state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char* mapped_path = map_path->abstract_path(map_path->handle,
|
||||
drmr->current_path);
|
||||
|
||||
if (store(handle,
|
||||
drmr->uris.kit_path,
|
||||
mapped_path,
|
||||
strlen(mapped_path) + 1,
|
||||
drmr->uris.string_urid,
|
||||
LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) {
|
||||
printf("Store failed\n");
|
||||
}
|
||||
}
|
||||
|
||||
void restore_state(LV2_Handle instance,
|
||||
LV2_State_Retrieve_Function retrieve,
|
||||
void* handle,
|
||||
uint32_t flags,
|
||||
const LV2_Feature *const * features) {
|
||||
DrMr* drmr = (DrMr*)instance;
|
||||
size_t size;
|
||||
uint32_t type;
|
||||
uint32_t fgs;
|
||||
|
||||
LV2_State_Map_Path* map_path = NULL;
|
||||
while(*features) {
|
||||
if (!strcmp((*features)->URI, LV2_STATE__mapPath))
|
||||
map_path = (LV2_State_Map_Path*)((*features)->data);
|
||||
features++;
|
||||
}
|
||||
|
||||
if (map_path == NULL) {
|
||||
fprintf(stderr,"Host does not support map_path, cannot restore state\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const char* abstract_path =
|
||||
retrieve(handle, drmr->uris.kit_path, &size, &type, &fgs);
|
||||
|
||||
if (!abstract_path) {
|
||||
fprintf(stderr,"Found no path in state, not restoring\n");
|
||||
return;
|
||||
}
|
||||
|
||||
char *kit_path = map_path->absolute_path(map_path->handle,abstract_path);
|
||||
|
||||
if (kit_path) { // safe as we're in "Instantiation" threading class
|
||||
int reqPos = (drmr->curReq+1)%REQ_BUF_SIZE;
|
||||
char *tmp = NULL;
|
||||
if (reqPos >= 0 && drmr->request_buf[reqPos])
|
||||
tmp = drmr->request_buf[reqPos];
|
||||
drmr->request_buf[reqPos] = strdup(kit_path);
|
||||
drmr->curReq = reqPos;
|
||||
if (tmp) free(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const void* extension_data(const char* uri) {
|
||||
static const LV2_State_Interface state_iface = { save_state, restore_state };
|
||||
if (!strcmp(uri, LV2_STATE_URI "#Interface")) return &state_iface;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
9
drmr.h
9
drmr.h
@ -25,6 +25,7 @@
|
||||
#include "lv2/lv2plug.in/ns/ext/atom/util.h"
|
||||
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
|
||||
#include "lv2/lv2plug.in/ns/ext/state/state.h"
|
||||
|
||||
// drumkit scanned from a hydrogen xml file
|
||||
typedef struct {
|
||||
@ -147,6 +148,8 @@ typedef struct {
|
||||
LV2_URID kit_path;
|
||||
LV2_URID atom_eventTransfer;
|
||||
LV2_URID atom_resource;
|
||||
LV2_URID string_urid;
|
||||
LV2_URID get_state;
|
||||
} drmr_uris;
|
||||
|
||||
typedef struct {
|
||||
@ -190,12 +193,18 @@ void map_drmr_uris(LV2_URID_Map *map,
|
||||
uris->midi_event =
|
||||
map->map(map->handle,
|
||||
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||
uris->string_urid =
|
||||
map->map(map->handle,
|
||||
"http://lv2plug.in/ns/ext/atom#String");
|
||||
uris->ui_msg =
|
||||
map->map(map->handle,
|
||||
DRMR_URI "#uimsg");
|
||||
uris->kit_path =
|
||||
map->map(map->handle,
|
||||
DRMR_URI "#kitpath");
|
||||
uris->kit_path =
|
||||
map->map(map->handle,
|
||||
DRMR_URI "#getstate");
|
||||
uris->atom_eventTransfer =
|
||||
map->map(map->handle, LV2_ATOM__eventTransfer);
|
||||
uris->atom_resource =
|
||||
|
1
drmr.ttl
1
drmr.ttl
@ -19,6 +19,7 @@
|
||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
||||
lv2:requiredFeature urid:map ;
|
||||
ui:ui <http://github.com/nicklan/drmr#ui> ;
|
||||
lv2:extensionData <http://lv2plug.in/ns/ext/state#Interface> ;
|
||||
lv2:port [
|
||||
a lv2:InputPort , atom:MessagePort;
|
||||
atom:bufferType atom:Sequence ;
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
@ -307,7 +309,7 @@ kits* scan_kits() {
|
||||
}
|
||||
|
||||
snprintf(buf,BUFSIZ,"%s/%s/",cur_path,ep->d_name);
|
||||
kit->path = strdup(buf);
|
||||
kit->path = realpath(buf,NULL); // realpath will malloc for us
|
||||
node->skit = kit;
|
||||
struct kit_list * cur_k = scanned_kits;
|
||||
if (cur_k) {
|
||||
|
42
drmr_ui.c
42
drmr_ui.c
@ -14,6 +14,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@ -295,6 +296,14 @@ static LV2_Atom* build_path_message(DrMrUi *ui, const char* path) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
static LV2_Atom* build_get_state_message(DrMrUi *ui) {
|
||||
LV2_Atom_Forge_Frame set_frame;
|
||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||
(&ui->forge, &set_frame, 1, ui->uris.get_state);
|
||||
lv2_atom_forge_pop(&ui->forge,&set_frame);
|
||||
return msg;
|
||||
}
|
||||
|
||||
static void kit_combobox_changed(GtkComboBox* box, gpointer data) {
|
||||
DrMrUi* ui = (DrMrUi*)data;
|
||||
gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box));
|
||||
@ -357,6 +366,20 @@ static GtkWidget *create_position_combo(void)
|
||||
return combo;
|
||||
}
|
||||
|
||||
static gulong expose_id;
|
||||
static gboolean expose_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data) {
|
||||
DrMrUi* ui = (DrMrUi*)data;
|
||||
uint8_t msg_buf[1024];
|
||||
lv2_atom_forge_set_buffer(&ui->forge, msg_buf, 1024);
|
||||
LV2_Atom *msg = build_get_state_message(ui);
|
||||
ui->write(ui->controller,DRMR_CONTROL,
|
||||
lv2_atom_total_size(msg),
|
||||
ui->uris.atom_eventTransfer,
|
||||
msg);
|
||||
g_signal_handler_disconnect(widget,expose_id);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void build_drmr_ui(DrMrUi* ui) {
|
||||
GtkWidget *drmr_ui_widget;
|
||||
GtkWidget *opts_hbox1, *opts_hbox2,
|
||||
@ -369,6 +392,7 @@ static void build_drmr_ui(DrMrUi* ui) {
|
||||
PangoAttribute *attr;
|
||||
|
||||
drmr_ui_widget = gtk_vbox_new(false,0);
|
||||
expose_id = g_signal_connect (drmr_ui_widget, "expose-event", G_CALLBACK (expose_callback), ui);
|
||||
g_object_set(drmr_ui_widget,"border-width",6,NULL);
|
||||
|
||||
ui->kit_store = gtk_list_store_new(1,G_TYPE_STRING);
|
||||
@ -503,7 +527,6 @@ instantiate(const LV2UI_Descriptor* descriptor,
|
||||
ui->startSamp = 0;
|
||||
#endif
|
||||
|
||||
|
||||
*widget = ui->drmr_widget;
|
||||
|
||||
return ui;
|
||||
@ -548,20 +571,33 @@ port_event(LV2UI_Handle handle,
|
||||
LV2_Atom* atom = (LV2_Atom*)buffer;
|
||||
if (atom->type == ui->uris.atom_resource) {
|
||||
LV2_Atom_Object* obj = (LV2_Atom_Object*)atom;
|
||||
if (obj->body.otype != ui->uris.get_state &&
|
||||
obj->body.otype != ui->uris.ui_msg) {
|
||||
// both state and ui_msg are the same at the moment
|
||||
fprintf(stderr,"Invalid message type to ui\n");
|
||||
return;
|
||||
}
|
||||
const LV2_Atom* path = NULL;
|
||||
lv2_object_get(obj, ui->uris.kit_path, &path, 0);
|
||||
if (!path)
|
||||
fprintf(stderr,"Got UI message without kit_path, ignoring\n");
|
||||
else {
|
||||
char *kitpath = LV2_ATOM_BODY(path);
|
||||
char *realp = realpath(kitpath,NULL);
|
||||
if (!realp) {
|
||||
fprintf(stderr,"Passed a path I can't resolve, bailing out\n");
|
||||
return;
|
||||
}
|
||||
int i;
|
||||
for(i = 0;i < ui->kits->num_kits;i++)
|
||||
if (!strcmp(ui->kits->kits[i].path,kitpath))
|
||||
if (!strcmp(ui->kits->kits[i].path,realp))
|
||||
break;
|
||||
if (i < ui->kits->num_kits) {
|
||||
ui->kitReq = i;
|
||||
g_idle_add(kit_callback,ui);
|
||||
}
|
||||
} else
|
||||
fprintf(stderr,"Couldn't find kit %s\n",realp);
|
||||
free(realp);
|
||||
}
|
||||
} else
|
||||
fprintf(stderr, "Unknown message type.\n");
|
||||
|
Loading…
Reference in New Issue
Block a user