tweak appearance of a FaderOption in the option editor(s)
[ardour.git] / libs / ardour / ardour / lv2_state.h
1 /*
2   Copyright (C) 2011 Paul Davis
3   Author: David Robillard
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software
17   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef __ardour_lv2_state_h__
21 #define __ardour_lv2_state_h__
22
23 #include <stdint.h>
24 #include <stdlib.h>
25
26 #include <map>
27 #include <string>
28
29 #include "pbd/error.h"
30
31 #include "ardour/uri_map.h"
32 #include "lv2/lv2plug.in/ns/ext/state/state.h"
33 #include "rdff.h"
34
35 namespace ARDOUR {
36
37 class LV2Plugin;
38
39 struct LV2State {
40         LV2State(const LV2Plugin& plug, URIMap& map) : plugin(plug), uri_map(map) {}
41
42         struct Value {
43                 inline Value(uint32_t k, const void* v, size_t s, uint32_t t, uint32_t f)
44                         : key(k), value(v), size(s), type(t), flags(f)
45                 {}
46
47                 const uint32_t key;
48                 const void*    value;
49                 const size_t   size;
50                 const uint32_t type;
51                 const uint32_t flags;
52         };
53
54         typedef std::map<uint32_t, std::string> URIs;
55         typedef std::map<uint32_t, Value>       Values;
56
57         uint32_t file_id_to_runtime_id(uint32_t file_id) const {
58                 URIs::const_iterator i = uris.find(file_id);
59                 if (i == uris.end()) {
60                         PBD::error << "LV2 state refers to undefined URI ID" << endmsg;
61                         return 0;
62                 }
63                 return uri_map.uri_to_id(NULL, i->second.c_str());
64         }
65
66         int add_uri(uint32_t file_id, const char* str) {
67                 // TODO: check for clashes (invalid file)
68                 uris.insert(std::make_pair(file_id, str));
69                 return 0;
70         }
71
72         int add_value(uint32_t    file_key,
73                       const void* value,
74                       size_t      size,
75                       uint32_t    file_type,
76                       uint32_t    flags) {
77                 const uint32_t key  = file_id_to_runtime_id(file_key);
78                 const uint32_t type = file_id_to_runtime_id(file_type);
79                 if (!key || !type) {
80                         PBD::error << "Invalid file key or type" << endmsg;
81                         return 1;
82                 }
83
84                 Values::const_iterator i = values.find(key);
85                 if (i != values.end()) {
86                         PBD::error << "LV2 state contains duplicate keys" << endmsg;
87                         return 1;
88                 } else {
89                         void* value_copy = malloc(size);
90                         memcpy(value_copy, value, size); // FIXME: leak
91                         values.insert(
92                                 std::make_pair(key,
93                                                Value(key, value_copy, size, type, flags)));
94                         return 0;
95                 }
96         }
97
98         void read(RDFF file) {
99                 RDFFChunk* chunk = (RDFFChunk*)malloc(sizeof(RDFFChunk));
100                 chunk->size = 0;
101                 while (!rdff_read_chunk(file, &chunk)) {
102                         if (rdff_chunk_is_uri(chunk)) {
103                                 RDFFURIChunk* body = (RDFFURIChunk*)chunk->data;
104                                 add_uri(body->id, body->uri);
105                         } else if (rdff_chunk_is_triple(chunk)) {
106                                 RDFFTripleChunk* body = (RDFFTripleChunk*)chunk->data;
107                                 add_value(body->predicate,
108                                           body->object,
109                                           body->object_size,
110                                           body->object_type,
111                                           LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
112                         }
113                 }
114                 free(chunk);
115         }
116
117         void write(RDFF file) {
118                 // Write all referenced URIs to state file
119                 for (URIs::const_iterator i = uris.begin(); i != uris.end(); ++i) {
120                         rdff_write_uri(file,
121                                        i->first,
122                                        i->second.length(),
123                                        i->second.c_str());
124                 }
125
126                 // Write all values to state file
127                 for (Values::const_iterator i = values.begin(); i != values.end(); ++i) {
128                         const uint32_t         key = i->first;
129                         const LV2State::Value& val = i->second;
130                         rdff_write_triple(file,
131                                           0,
132                                           key,
133                                           val.type,
134                                           val.size,
135                                           val.value);
136                 }
137         }
138
139         const LV2Plugin& plugin;
140         URIMap&          uri_map;
141         URIs             uris;
142         Values           values;
143 };
144
145 } // namespace ARDOUR
146
147 #endif /* __ardour_lv2_state_h__ */