Add state support and startup state polling for the ui
This commit is contained in:
parent
dc2872309c
commit
1715d437e9
105
drmr.c
105
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_Forge_Frame set_frame;
|
||||||
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
LV2_Atom* msg = (LV2_Atom*)lv2_atom_forge_resource
|
||||||
(&drmr->forge, &set_frame, 1, drmr->uris.ui_msg);
|
(&drmr->forge, &set_frame, 1, drmr->uris.ui_msg);
|
||||||
lv2_atom_forge_property_head(&drmr->forge, drmr->uris.kit_path,0);
|
if (drmr->current_path) {
|
||||||
lv2_atom_forge_string(&drmr->forge, kit, strlen(kit));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
lv2_atom_forge_pop(&drmr->forge,&set_frame);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
@ -257,6 +271,10 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
|
|||||||
drmr->curReq = reqPos;
|
drmr->curReq = reqPos;
|
||||||
if (tmp) free(tmp);
|
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");
|
else printf("unrecognized event\n");
|
||||||
@ -272,7 +290,8 @@ static void run(LV2_Handle instance, uint32_t n_samples) {
|
|||||||
if (current_kit_changed) {
|
if (current_kit_changed) {
|
||||||
current_kit_changed = 0;
|
current_kit_changed = 0;
|
||||||
lv2_atom_forge_frame_time(&drmr->forge, 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);
|
lv2_atom_forge_pop(&drmr->forge, &seq_frame);
|
||||||
@ -330,7 +349,85 @@ static void cleanup(LV2_Handle instance) {
|
|||||||
free(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 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;
|
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/ext/atom/util.h"
|
||||||
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
|
#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
|
||||||
#include "lv2/lv2plug.in/ns/ext/urid/urid.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
|
// drumkit scanned from a hydrogen xml file
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -147,6 +148,8 @@ typedef struct {
|
|||||||
LV2_URID kit_path;
|
LV2_URID kit_path;
|
||||||
LV2_URID atom_eventTransfer;
|
LV2_URID atom_eventTransfer;
|
||||||
LV2_URID atom_resource;
|
LV2_URID atom_resource;
|
||||||
|
LV2_URID string_urid;
|
||||||
|
LV2_URID get_state;
|
||||||
} drmr_uris;
|
} drmr_uris;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -190,12 +193,18 @@ void map_drmr_uris(LV2_URID_Map *map,
|
|||||||
uris->midi_event =
|
uris->midi_event =
|
||||||
map->map(map->handle,
|
map->map(map->handle,
|
||||||
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
"http://lv2plug.in/ns/ext/midi#MidiEvent");
|
||||||
|
uris->string_urid =
|
||||||
|
map->map(map->handle,
|
||||||
|
"http://lv2plug.in/ns/ext/atom#String");
|
||||||
uris->ui_msg =
|
uris->ui_msg =
|
||||||
map->map(map->handle,
|
map->map(map->handle,
|
||||||
DRMR_URI "#uimsg");
|
DRMR_URI "#uimsg");
|
||||||
uris->kit_path =
|
uris->kit_path =
|
||||||
map->map(map->handle,
|
map->map(map->handle,
|
||||||
DRMR_URI "#kitpath");
|
DRMR_URI "#kitpath");
|
||||||
|
uris->kit_path =
|
||||||
|
map->map(map->handle,
|
||||||
|
DRMR_URI "#getstate");
|
||||||
uris->atom_eventTransfer =
|
uris->atom_eventTransfer =
|
||||||
map->map(map->handle, LV2_ATOM__eventTransfer);
|
map->map(map->handle, LV2_ATOM__eventTransfer);
|
||||||
uris->atom_resource =
|
uris->atom_resource =
|
||||||
|
1
drmr.ttl
1
drmr.ttl
@ -19,6 +19,7 @@
|
|||||||
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
doap:license <http://usefulinc.com/doap/licenses/gpl> ;
|
||||||
lv2:requiredFeature urid:map ;
|
lv2:requiredFeature urid:map ;
|
||||||
ui:ui <http://github.com/nicklan/drmr#ui> ;
|
ui:ui <http://github.com/nicklan/drmr#ui> ;
|
||||||
|
lv2:extensionData <http://lv2plug.in/ns/ext/state#Interface> ;
|
||||||
lv2:port [
|
lv2:port [
|
||||||
a lv2:InputPort , atom:MessagePort;
|
a lv2:InputPort , atom:MessagePort;
|
||||||
atom:bufferType atom:Sequence ;
|
atom:bufferType atom:Sequence ;
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@ -307,7 +309,7 @@ kits* scan_kits() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
snprintf(buf,BUFSIZ,"%s/%s/",cur_path,ep->d_name);
|
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;
|
node->skit = kit;
|
||||||
struct kit_list * cur_k = scanned_kits;
|
struct kit_list * cur_k = scanned_kits;
|
||||||
if (cur_k) {
|
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.
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
@ -295,6 +296,14 @@ static LV2_Atom* build_path_message(DrMrUi *ui, const char* path) {
|
|||||||
return msg;
|
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) {
|
static void kit_combobox_changed(GtkComboBox* box, gpointer data) {
|
||||||
DrMrUi* ui = (DrMrUi*)data;
|
DrMrUi* ui = (DrMrUi*)data;
|
||||||
gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box));
|
gint new_kit = gtk_combo_box_get_active (GTK_COMBO_BOX(box));
|
||||||
@ -357,6 +366,20 @@ static GtkWidget *create_position_combo(void)
|
|||||||
return combo;
|
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) {
|
static void build_drmr_ui(DrMrUi* ui) {
|
||||||
GtkWidget *drmr_ui_widget;
|
GtkWidget *drmr_ui_widget;
|
||||||
GtkWidget *opts_hbox1, *opts_hbox2,
|
GtkWidget *opts_hbox1, *opts_hbox2,
|
||||||
@ -369,6 +392,7 @@ static void build_drmr_ui(DrMrUi* ui) {
|
|||||||
PangoAttribute *attr;
|
PangoAttribute *attr;
|
||||||
|
|
||||||
drmr_ui_widget = gtk_vbox_new(false,0);
|
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);
|
g_object_set(drmr_ui_widget,"border-width",6,NULL);
|
||||||
|
|
||||||
ui->kit_store = gtk_list_store_new(1,G_TYPE_STRING);
|
ui->kit_store = gtk_list_store_new(1,G_TYPE_STRING);
|
||||||
@ -503,7 +527,6 @@ instantiate(const LV2UI_Descriptor* descriptor,
|
|||||||
ui->startSamp = 0;
|
ui->startSamp = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
*widget = ui->drmr_widget;
|
*widget = ui->drmr_widget;
|
||||||
|
|
||||||
return ui;
|
return ui;
|
||||||
@ -548,20 +571,33 @@ port_event(LV2UI_Handle handle,
|
|||||||
LV2_Atom* atom = (LV2_Atom*)buffer;
|
LV2_Atom* atom = (LV2_Atom*)buffer;
|
||||||
if (atom->type == ui->uris.atom_resource) {
|
if (atom->type == ui->uris.atom_resource) {
|
||||||
LV2_Atom_Object* obj = (LV2_Atom_Object*)atom;
|
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;
|
const LV2_Atom* path = NULL;
|
||||||
lv2_object_get(obj, ui->uris.kit_path, &path, 0);
|
lv2_object_get(obj, ui->uris.kit_path, &path, 0);
|
||||||
if (!path)
|
if (!path)
|
||||||
fprintf(stderr,"Got UI message without kit_path, ignoring\n");
|
fprintf(stderr,"Got UI message without kit_path, ignoring\n");
|
||||||
else {
|
else {
|
||||||
char *kitpath = LV2_ATOM_BODY(path);
|
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;
|
int i;
|
||||||
for(i = 0;i < ui->kits->num_kits;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;
|
break;
|
||||||
if (i < ui->kits->num_kits) {
|
if (i < ui->kits->num_kits) {
|
||||||
ui->kitReq = i;
|
ui->kitReq = i;
|
||||||
g_idle_add(kit_callback,ui);
|
g_idle_add(kit_callback,ui);
|
||||||
}
|
} else
|
||||||
|
fprintf(stderr,"Couldn't find kit %s\n",realp);
|
||||||
|
free(realp);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "Unknown message type.\n");
|
fprintf(stderr, "Unknown message type.\n");
|
||||||
|
Loading…
Reference in New Issue
Block a user