1 //-----------------------------------------------------------------------------
2 // Project     : VST SDK
3 //
4 // Category    : Helpers
5 // Filename    : public.sdk/source/vst/hosting/hostclasses.cpp
6 // Created by  : Steinberg, 03/05/2008.
7 // Description : VST 3 hostclasses, example implementations for IHostApplication, IAttributeList and IMessage
8 //
9 //-----------------------------------------------------------------------------
10 // LICENSE
11 // (c) 2019, Steinberg Media Technologies GmbH, All Rights Reserved
12 //-----------------------------------------------------------------------------
13 // Redistribution and use in source and binary forms, with or without modification,
14 // are permitted provided that the following conditions are met:
15 //
16 //   * Redistributions of source code must retain the above copyright notice,
17 //     this list of conditions and the following disclaimer.
18 //   * Redistributions in binary form must reproduce the above copyright notice,
19 //     this list of conditions and the following disclaimer in the documentation
20 //     and/or other materials provided with the distribution.
21 //   * Neither the name of the Steinberg Media Technologies nor the names of its
22 //     contributors may be used to endorse or promote products derived from this
23 //     software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
26 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE  OF THIS SOFTWARE, EVEN IF ADVISED
34 // OF THE POSSIBILITY OF SUCH DAMAGE.
35 //-----------------------------------------------------------------------------
36 
37 #include "hostclasses.h"
38 
39 #include <algorithm>
40 
41 namespace Steinberg {
42 namespace Vst {
43 
44 //-----------------------------------------------------------------------------
HostApplication()45 HostApplication::HostApplication ()
46 {
47 	FUNKNOWN_CTOR
48 
49 	mPlugInterfaceSupport = owned (NEW PlugInterfaceSupport);
50 }
51 
52 //-----------------------------------------------------------------------------
getName(String128 name)53 tresult PLUGIN_API HostApplication::getName (String128 name)
54 {
55 	String str ("My VST3 HostApplication");
56 	str.copyTo16 (name, 0, 127);
57 	return kResultTrue;
58 }
59 
60 //-----------------------------------------------------------------------------
createInstance(TUID cid,TUID _iid,void ** obj)61 tresult PLUGIN_API HostApplication::createInstance (TUID cid, TUID _iid, void** obj)
62 {
63 	FUID classID (FUID::fromTUID (cid));
64 	FUID interfaceID (FUID::fromTUID (_iid));
65 	if (classID == IMessage::iid && interfaceID == IMessage::iid)
66 	{
67 		*obj = new HostMessage;
68 		return kResultTrue;
69 	}
70 	else if (classID == IAttributeList::iid && interfaceID == IAttributeList::iid)
71 	{
72 		*obj = new HostAttributeList;
73 		return kResultTrue;
74 	}
75 	*obj = nullptr;
76 	return kResultFalse;
77 }
78 
79 //-----------------------------------------------------------------------------
queryInterface(const char * _iid,void ** obj)80 tresult PLUGIN_API HostApplication::queryInterface (const char* _iid, void** obj)
81 {
82 	QUERY_INTERFACE (_iid, obj, FUnknown::iid, IHostApplication)
83 	QUERY_INTERFACE (_iid, obj, IHostApplication::iid, IHostApplication)
84 
85 	if (mPlugInterfaceSupport && mPlugInterfaceSupport->queryInterface (iid, obj) == kResultTrue)
86 		return kResultOk;
87 
88 	*obj = nullptr;
89 	return kResultFalse;
90 }
91 
92 //-----------------------------------------------------------------------------
addRef()93 uint32 PLUGIN_API HostApplication::addRef ()
94 {
95 	return 1;
96 }
97 
98 //-----------------------------------------------------------------------------
release()99 uint32 PLUGIN_API HostApplication::release ()
100 {
101 	return 1;
102 }
103 
104 //-----------------------------------------------------------------------------
105 //-----------------------------------------------------------------------------
106 //-----------------------------------------------------------------------------
IMPLEMENT_FUNKNOWN_METHODS(HostMessage,IMessage,IMessage::iid)107 IMPLEMENT_FUNKNOWN_METHODS (HostMessage, IMessage, IMessage::iid)
108 //-----------------------------------------------------------------------------
109 HostMessage::HostMessage () : messageId (nullptr), attributeList (nullptr)
110 {
111 	FUNKNOWN_CTOR
112 }
113 
114 //-----------------------------------------------------------------------------
~HostMessage()115 HostMessage::~HostMessage ()
116 {
117 	setMessageID (nullptr);
118 	if (attributeList)
119 		attributeList->release ();
120 	FUNKNOWN_DTOR
121 }
122 
123 //-----------------------------------------------------------------------------
getMessageID()124 const char* PLUGIN_API HostMessage::getMessageID ()
125 {
126 	return messageId;
127 }
128 
129 //-----------------------------------------------------------------------------
setMessageID(const char * mid)130 void PLUGIN_API HostMessage::setMessageID (const char* mid)
131 {
132 	if (messageId)
133 		delete[] messageId;
134 	messageId = nullptr;
135 	if (mid)
136 	{
137 		size_t len = strlen (mid) + 1;
138 		messageId = new char[len];
139 		strcpy (messageId, mid);
140 	}
141 }
142 
143 //-----------------------------------------------------------------------------
getAttributes()144 IAttributeList* PLUGIN_API HostMessage::getAttributes ()
145 {
146 	if (!attributeList)
147 		attributeList = new HostAttributeList;
148 	return attributeList;
149 }
150 
151 //-----------------------------------------------------------------------------
152 //-----------------------------------------------------------------------------
153 //-----------------------------------------------------------------------------
154 class HostAttribute
155 {
156 public:
157 	enum Type
158 	{
159 		kInteger,
160 		kFloat,
161 		kString,
162 		kBinary
163 	};
164 
HostAttribute(int64 value)165 	HostAttribute (int64 value) : size (0), type (kInteger) { v.intValue = value; }
HostAttribute(double value)166 	HostAttribute (double value) : size (0), type (kFloat) { v.floatValue = value; }
HostAttribute(const TChar * value,uint32 size)167 	HostAttribute (const TChar* value, uint32 size) : size (size), type (kString)
168 	{
169 		v.stringValue = new TChar[size];
170 		memcpy (v.stringValue, value, size * sizeof (TChar));
171 	}
HostAttribute(const void * value,uint32 size)172 	HostAttribute (const void* value, uint32 size) : size (size), type (kBinary)
173 	{
174 		v.binaryValue = new char[size];
175 		memcpy (v.binaryValue, value, size);
176 	}
~HostAttribute()177 	~HostAttribute ()
178 	{
179 		if (size)
180 			delete[] v.binaryValue;
181 	}
182 
intValue() const183 	int64 intValue () const { return v.intValue; }
floatValue() const184 	double floatValue () const { return v.floatValue; }
stringValue(uint32 & stringSize)185 	const TChar* stringValue (uint32& stringSize)
186 	{
187 		stringSize = size;
188 		return v.stringValue;
189 	}
binaryValue(uint32 & binarySize)190 	const void* binaryValue (uint32& binarySize)
191 	{
192 		binarySize = size;
193 		return v.binaryValue;
194 	}
195 
getType() const196 	Type getType () const { return type; }
197 
198 protected:
199 	union v
200 	{
201 		int64 intValue;
202 		double floatValue;
203 		TChar* stringValue;
204 		char* binaryValue;
205 	} v;
206 	uint32 size;
207 	Type type;
208 };
209 
210 using mapIterator = std::map<String, HostAttribute*>::iterator;
211 
212 //-----------------------------------------------------------------------------
213 //-----------------------------------------------------------------------------
214 //-----------------------------------------------------------------------------
IMPLEMENT_FUNKNOWN_METHODS(HostAttributeList,IAttributeList,IAttributeList::iid)215 IMPLEMENT_FUNKNOWN_METHODS (HostAttributeList, IAttributeList, IAttributeList::iid)
216 //-----------------------------------------------------------------------------
217 HostAttributeList::HostAttributeList ()
218 {
219 	FUNKNOWN_CTOR
220 }
221 
222 //-----------------------------------------------------------------------------
~HostAttributeList()223 HostAttributeList::~HostAttributeList ()
224 {
225 	std::map<String, HostAttribute*>::reverse_iterator it = list.rbegin ();
226 	while (it != list.rend ())
227 	{
228 		delete it->second;
229 		it++;
230 	}
231 	FUNKNOWN_DTOR
232 }
233 
234 //-----------------------------------------------------------------------------
removeAttrID(AttrID aid)235 void HostAttributeList::removeAttrID (AttrID aid)
236 {
237 	mapIterator it = list.find (aid);
238 	if (it != list.end ())
239 	{
240 		delete it->second;
241 		list.erase (it);
242 	}
243 }
244 
245 //-----------------------------------------------------------------------------
setInt(AttrID aid,int64 value)246 tresult PLUGIN_API HostAttributeList::setInt (AttrID aid, int64 value)
247 {
248 	removeAttrID (aid);
249 	list[aid] = new HostAttribute (value);
250 	return kResultTrue;
251 }
252 
253 //-----------------------------------------------------------------------------
getInt(AttrID aid,int64 & value)254 tresult PLUGIN_API HostAttributeList::getInt (AttrID aid, int64& value)
255 {
256 	mapIterator it = list.find (aid);
257 	if (it != list.end () && it->second)
258 	{
259 		value = it->second->intValue ();
260 		return kResultTrue;
261 	}
262 	return kResultFalse;
263 }
264 
265 //-----------------------------------------------------------------------------
setFloat(AttrID aid,double value)266 tresult PLUGIN_API HostAttributeList::setFloat (AttrID aid, double value)
267 {
268 	removeAttrID (aid);
269 	list[aid] = new HostAttribute (value);
270 	return kResultTrue;
271 }
272 
273 //-----------------------------------------------------------------------------
getFloat(AttrID aid,double & value)274 tresult PLUGIN_API HostAttributeList::getFloat (AttrID aid, double& value)
275 {
276 	mapIterator it = list.find (aid);
277 	if (it != list.end () && it->second)
278 	{
279 		value = it->second->floatValue ();
280 		return kResultTrue;
281 	}
282 	return kResultFalse;
283 }
284 
285 //-----------------------------------------------------------------------------
setString(AttrID aid,const TChar * string)286 tresult PLUGIN_API HostAttributeList::setString (AttrID aid, const TChar* string)
287 {
288 	removeAttrID (aid);
289 	list[aid] = new HostAttribute (string, String (const_cast<TChar*> (string)).length ());
290 	return kResultTrue;
291 }
292 
293 //-----------------------------------------------------------------------------
getString(AttrID aid,TChar * string,uint32 size)294 tresult PLUGIN_API HostAttributeList::getString (AttrID aid, TChar* string, uint32 size)
295 {
296 	mapIterator it = list.find (aid);
297 	if (it != list.end () && it->second)
298 	{
299 		uint32 stringSize = 0;
300 		const TChar* _string = it->second->stringValue (stringSize);
301 		memcpy (string, _string, std::min<uint32> (stringSize, size) * sizeof (TChar));
302 		return kResultTrue;
303 	}
304 	return kResultFalse;
305 }
306 
307 //-----------------------------------------------------------------------------
setBinary(AttrID aid,const void * data,uint32 size)308 tresult PLUGIN_API HostAttributeList::setBinary (AttrID aid, const void* data, uint32 size)
309 {
310 	removeAttrID (aid);
311 	list[aid] = new HostAttribute (data, size);
312 	return kResultTrue;
313 }
314 
315 //-----------------------------------------------------------------------------
getBinary(AttrID aid,const void * & data,uint32 & size)316 tresult PLUGIN_API HostAttributeList::getBinary (AttrID aid, const void*& data, uint32& size)
317 {
318 	mapIterator it = list.find (aid);
319 	if (it != list.end () && it->second)
320 	{
321 		data = it->second->binaryValue (size);
322 		return kResultTrue;
323 	}
324 	size = 0;
325 	return kResultFalse;
326 }
327 }
328 } // namespace
329