Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

724 lines
22KB

  1. //-----------------------------------------------------------------------------
  2. // Project : VST SDK
  3. //
  4. // Category : Helpers
  5. // Filename : public.sdk/source/vst/vsteditcontroller.cpp
  6. // Created by : Steinberg, 04/2005
  7. // Description : VST Edit Controller Implementation
  8. //
  9. //-----------------------------------------------------------------------------
  10. // LICENSE
  11. // (c) 2021, 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. #include "public.sdk/source/vst/vsteditcontroller.h"
  37. #include "base/source/updatehandler.h"
  38. #include "pluginterfaces/base/ustring.h"
  39. #include <cstdio>
  40. namespace Steinberg {
  41. namespace Vst {
  42. KnobMode EditController::hostKnobMode = kCircularMode;
  43. //------------------------------------------------------------------------
  44. // EditController Implementation
  45. //------------------------------------------------------------------------
  46. EditController::EditController () : componentHandler (nullptr), componentHandler2 (nullptr)
  47. {
  48. }
  49. //------------------------------------------------------------------------
  50. tresult PLUGIN_API EditController::initialize (FUnknown* context)
  51. {
  52. return ComponentBase::initialize (context);
  53. }
  54. //------------------------------------------------------------------------
  55. tresult PLUGIN_API EditController::terminate ()
  56. {
  57. parameters.removeAll ();
  58. if (componentHandler)
  59. {
  60. componentHandler->release ();
  61. componentHandler = nullptr;
  62. }
  63. if (componentHandler2)
  64. {
  65. componentHandler2->release ();
  66. componentHandler2 = nullptr;
  67. }
  68. return ComponentBase::terminate ();
  69. }
  70. //------------------------------------------------------------------------
  71. tresult PLUGIN_API EditController::setComponentState (IBStream* /*state*/)
  72. {
  73. return kNotImplemented;
  74. }
  75. //------------------------------------------------------------------------
  76. tresult PLUGIN_API EditController::setState (IBStream* /*state*/)
  77. {
  78. return kNotImplemented;
  79. }
  80. //------------------------------------------------------------------------
  81. tresult PLUGIN_API EditController::getState (IBStream* /*state*/)
  82. {
  83. return kNotImplemented;
  84. }
  85. //------------------------------------------------------------------------
  86. int32 PLUGIN_API EditController::getParameterCount ()
  87. {
  88. return parameters.getParameterCount ();
  89. }
  90. //------------------------------------------------------------------------
  91. tresult PLUGIN_API EditController::getParameterInfo (int32 paramIndex, ParameterInfo& info)
  92. {
  93. if (Parameter* parameter = parameters.getParameterByIndex (paramIndex))
  94. {
  95. info = parameter->getInfo ();
  96. return kResultTrue;
  97. }
  98. return kResultFalse;
  99. }
  100. //------------------------------------------------------------------------
  101. tresult PLUGIN_API EditController::getParamStringByValue (ParamID tag, ParamValue valueNormalized,
  102. String128 string)
  103. {
  104. if (Parameter* parameter = getParameterObject (tag))
  105. {
  106. parameter->toString (valueNormalized, string);
  107. return kResultTrue;
  108. }
  109. return kResultFalse;
  110. }
  111. //------------------------------------------------------------------------
  112. tresult PLUGIN_API EditController::getParamValueByString (ParamID tag, TChar* string,
  113. ParamValue& valueNormalized)
  114. {
  115. if (Parameter* parameter = getParameterObject (tag))
  116. {
  117. if (parameter->fromString (string, valueNormalized))
  118. {
  119. return kResultTrue;
  120. }
  121. }
  122. return kResultFalse;
  123. }
  124. //------------------------------------------------------------------------
  125. ParamValue PLUGIN_API EditController::normalizedParamToPlain (ParamID tag,
  126. ParamValue valueNormalized)
  127. {
  128. if (Parameter* parameter = getParameterObject (tag))
  129. {
  130. return parameter->toPlain (valueNormalized);
  131. }
  132. return valueNormalized;
  133. }
  134. //------------------------------------------------------------------------
  135. ParamValue PLUGIN_API EditController::plainParamToNormalized (ParamID tag, ParamValue plainValue)
  136. {
  137. if (Parameter* parameter = getParameterObject (tag))
  138. {
  139. return parameter->toNormalized (plainValue);
  140. }
  141. return plainValue;
  142. }
  143. //------------------------------------------------------------------------
  144. ParamValue PLUGIN_API EditController::getParamNormalized (ParamID tag)
  145. {
  146. if (Parameter* parameter = getParameterObject (tag))
  147. {
  148. return parameter->getNormalized ();
  149. }
  150. return 0.;
  151. }
  152. //------------------------------------------------------------------------
  153. tresult PLUGIN_API EditController::setParamNormalized (ParamID tag, ParamValue value)
  154. {
  155. if (Parameter* parameter = getParameterObject (tag))
  156. {
  157. parameter->setNormalized (value);
  158. return kResultTrue;
  159. }
  160. return kResultFalse;
  161. }
  162. //------------------------------------------------------------------------
  163. tresult PLUGIN_API EditController::setComponentHandler (IComponentHandler* newHandler)
  164. {
  165. if (componentHandler == newHandler)
  166. {
  167. return kResultTrue;
  168. }
  169. if (componentHandler)
  170. {
  171. componentHandler->release ();
  172. }
  173. componentHandler = newHandler;
  174. if (componentHandler)
  175. {
  176. componentHandler->addRef ();
  177. }
  178. // try to get the extended version
  179. if (componentHandler2)
  180. {
  181. componentHandler2->release ();
  182. componentHandler2 = nullptr;
  183. }
  184. if (newHandler)
  185. {
  186. newHandler->queryInterface (IComponentHandler2::iid, (void**)&componentHandler2);
  187. }
  188. return kResultTrue;
  189. }
  190. //------------------------------------------------------------------------
  191. tresult EditController::beginEdit (ParamID tag)
  192. {
  193. if (componentHandler)
  194. {
  195. return componentHandler->beginEdit (tag);
  196. }
  197. return kResultFalse;
  198. }
  199. //------------------------------------------------------------------------
  200. tresult EditController::performEdit (ParamID tag, ParamValue valueNormalized)
  201. {
  202. if (componentHandler)
  203. {
  204. return componentHandler->performEdit (tag, valueNormalized);
  205. }
  206. return kResultFalse;
  207. }
  208. //------------------------------------------------------------------------
  209. tresult EditController::endEdit (ParamID tag)
  210. {
  211. if (componentHandler)
  212. {
  213. return componentHandler->endEdit (tag);
  214. }
  215. return kResultFalse;
  216. }
  217. //------------------------------------------------------------------------
  218. tresult EditController::startGroupEdit ()
  219. {
  220. if (componentHandler2)
  221. {
  222. return componentHandler2->startGroupEdit ();
  223. }
  224. return kNotImplemented;
  225. }
  226. //------------------------------------------------------------------------
  227. tresult EditController::finishGroupEdit ()
  228. {
  229. if (componentHandler2)
  230. {
  231. return componentHandler2->finishGroupEdit ();
  232. }
  233. return kNotImplemented;
  234. }
  235. //------------------------------------------------------------------------
  236. tresult EditController::getParameterInfoByTag (ParamID tag, ParameterInfo& info)
  237. {
  238. if (Parameter* parameter = getParameterObject (tag))
  239. {
  240. info = parameter->getInfo ();
  241. return kResultTrue;
  242. }
  243. return kResultFalse;
  244. }
  245. //------------------------------------------------------------------------
  246. tresult EditController::setDirty (TBool state)
  247. {
  248. if (componentHandler2)
  249. {
  250. return componentHandler2->setDirty (state);
  251. }
  252. return kNotImplemented;
  253. }
  254. //------------------------------------------------------------------------
  255. tresult EditController::requestOpenEditor (FIDString name)
  256. {
  257. if (componentHandler2)
  258. {
  259. return componentHandler2->requestOpenEditor (name);
  260. }
  261. return kNotImplemented;
  262. }
  263. #ifndef NO_PLUGUI
  264. //------------------------------------------------------------------------
  265. // EditorView Implementation
  266. //------------------------------------------------------------------------
  267. EditorView::EditorView (EditController* _controller, ViewRect* size)
  268. : CPluginView (size), controller (_controller)
  269. {
  270. if (controller)
  271. {
  272. controller->addRef ();
  273. }
  274. }
  275. //------------------------------------------------------------------------
  276. EditorView::~EditorView ()
  277. {
  278. if (controller)
  279. {
  280. controller->editorDestroyed (this);
  281. controller->release ();
  282. }
  283. }
  284. //------------------------------------------------------------------------
  285. void EditorView::attachedToParent ()
  286. {
  287. if (controller)
  288. {
  289. controller->editorAttached (this);
  290. }
  291. }
  292. //------------------------------------------------------------------------
  293. void EditorView::removedFromParent ()
  294. {
  295. if (controller)
  296. {
  297. controller->editorRemoved (this);
  298. }
  299. }
  300. #endif // NO_PLUGUI
  301. //------------------------------------------------------------------------
  302. // EditControllerEx1 implementation
  303. //------------------------------------------------------------------------
  304. EditControllerEx1::EditControllerEx1 () : selectedUnit (kRootUnitId)
  305. {
  306. UpdateHandler::instance ();
  307. }
  308. //------------------------------------------------------------------------
  309. EditControllerEx1::~EditControllerEx1 ()
  310. {
  311. }
  312. //------------------------------------------------------------------------
  313. tresult PLUGIN_API EditControllerEx1::terminate ()
  314. {
  315. units.clear ();
  316. for (const auto& programList : programLists)
  317. {
  318. if (programList)
  319. programList->removeDependent (this);
  320. }
  321. programLists.clear ();
  322. programIndexMap.clear ();
  323. return EditController::terminate ();
  324. }
  325. //------------------------------------------------------------------------
  326. bool EditControllerEx1::addUnit (Unit* unit)
  327. {
  328. units.emplace_back (unit, false);
  329. return true;
  330. }
  331. //------------------------------------------------------------------------
  332. tresult PLUGIN_API EditControllerEx1::getUnitInfo (int32 unitIndex, UnitInfo& info /*out*/)
  333. {
  334. if (Unit* unit = units.at (unitIndex))
  335. {
  336. info = unit->getInfo ();
  337. return kResultTrue;
  338. }
  339. return kResultFalse;
  340. }
  341. //------------------------------------------------------------------------
  342. tresult EditControllerEx1::notifyUnitSelection ()
  343. {
  344. tresult result = kResultFalse;
  345. FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
  346. if (unitHandler)
  347. result = unitHandler->notifyUnitSelection (selectedUnit);
  348. return result;
  349. }
  350. //------------------------------------------------------------------------
  351. bool EditControllerEx1::addProgramList (ProgramList* list)
  352. {
  353. programIndexMap[list->getID ()] = programLists.size ();
  354. programLists.emplace_back (list, false);
  355. list->addDependent (this);
  356. return true;
  357. }
  358. //------------------------------------------------------------------------
  359. ProgramList* EditControllerEx1::getProgramList (ProgramListID listId) const
  360. {
  361. auto it = programIndexMap.find (listId);
  362. return it == programIndexMap.end () ? nullptr : programLists[it->second];
  363. }
  364. //------------------------------------------------------------------------
  365. tresult EditControllerEx1::notifyProgramListChange (ProgramListID listId, int32 programIndex)
  366. {
  367. tresult result = kResultFalse;
  368. FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
  369. if (unitHandler)
  370. result = unitHandler->notifyProgramListChange (listId, programIndex);
  371. return result;
  372. }
  373. //------------------------------------------------------------------------
  374. int32 PLUGIN_API EditControllerEx1::getProgramListCount ()
  375. {
  376. return static_cast<int32> (programLists.size ());
  377. }
  378. //------------------------------------------------------------------------
  379. tresult PLUGIN_API EditControllerEx1::getProgramListInfo (int32 listIndex,
  380. ProgramListInfo& info /*out*/)
  381. {
  382. if (listIndex < 0 || listIndex >= static_cast<int32> (programLists.size ()))
  383. return kResultFalse;
  384. info = programLists[listIndex]->getInfo ();
  385. return kResultTrue;
  386. }
  387. //------------------------------------------------------------------------
  388. tresult PLUGIN_API EditControllerEx1::getProgramName (ProgramListID listId, int32 programIndex,
  389. String128 name /*out*/)
  390. {
  391. ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
  392. if (it != programIndexMap.end ())
  393. {
  394. return programLists[it->second]->getProgramName (programIndex, name);
  395. }
  396. return kResultFalse;
  397. }
  398. //------------------------------------------------------------------------
  399. tresult EditControllerEx1::setProgramName (ProgramListID listId, int32 programIndex,
  400. const String128 name /*in*/)
  401. {
  402. ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
  403. if (it != programIndexMap.end ())
  404. {
  405. return programLists[it->second]->setProgramName (programIndex, name);
  406. }
  407. return kResultFalse;
  408. }
  409. //------------------------------------------------------------------------
  410. tresult PLUGIN_API EditControllerEx1::getProgramInfo (ProgramListID listId, int32 programIndex,
  411. CString attributeId /*in*/,
  412. String128 attributeValue /*out*/)
  413. {
  414. ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
  415. if (it != programIndexMap.end ())
  416. {
  417. return programLists[it->second]->getProgramInfo (programIndex, attributeId, attributeValue);
  418. }
  419. return kResultFalse;
  420. }
  421. //------------------------------------------------------------------------
  422. tresult PLUGIN_API EditControllerEx1::hasProgramPitchNames (ProgramListID listId,
  423. int32 programIndex)
  424. {
  425. ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
  426. if (it != programIndexMap.end ())
  427. {
  428. return programLists[it->second]->hasPitchNames (programIndex);
  429. }
  430. return kResultFalse;
  431. }
  432. //------------------------------------------------------------------------
  433. tresult PLUGIN_API EditControllerEx1::getProgramPitchName (ProgramListID listId, int32 programIndex,
  434. int16 midiPitch, String128 name /*out*/)
  435. {
  436. ProgramIndexMap::const_iterator it = programIndexMap.find (listId);
  437. if (it != programIndexMap.end ())
  438. {
  439. return programLists[it->second]->getPitchName (programIndex, midiPitch, name);
  440. }
  441. return kResultFalse;
  442. }
  443. //------------------------------------------------------------------------
  444. void PLUGIN_API EditControllerEx1::update (FUnknown* changedUnknown, int32 /*message*/)
  445. {
  446. auto* programList = FCast<ProgramList> (changedUnknown);
  447. if (programList)
  448. {
  449. FUnknownPtr<IUnitHandler> unitHandler (componentHandler);
  450. if (unitHandler)
  451. unitHandler->notifyProgramListChange (programList->getID (), kAllProgramInvalid);
  452. }
  453. }
  454. //------------------------------------------------------------------------
  455. // Unit implementation
  456. //------------------------------------------------------------------------
  457. Unit::Unit ()
  458. {
  459. memset (&info, 0, sizeof (UnitInfo));
  460. }
  461. //------------------------------------------------------------------------
  462. Unit::Unit (const String128 name, UnitID unitId, UnitID parentUnitId, ProgramListID programListId)
  463. {
  464. setName (name);
  465. info.id = unitId;
  466. info.parentUnitId = parentUnitId;
  467. info.programListId = programListId;
  468. }
  469. //------------------------------------------------------------------------
  470. Unit::Unit (const UnitInfo& info) : info (info)
  471. {
  472. }
  473. //------------------------------------------------------------------------
  474. void Unit::setName (const String128 newName)
  475. {
  476. UString128 (newName).copyTo (info.name, 128);
  477. }
  478. //------------------------------------------------------------------------
  479. // ProgramList implementation
  480. //------------------------------------------------------------------------
  481. ProgramList::ProgramList (const String128 name, ProgramListID listId, UnitID unitId)
  482. : unitId (unitId), parameter (nullptr)
  483. {
  484. UString128 (name).copyTo (info.name, 128);
  485. info.id = listId;
  486. info.programCount = 0;
  487. }
  488. //------------------------------------------------------------------------
  489. ProgramList::ProgramList (const ProgramList& programList)
  490. : info (programList.info)
  491. , unitId (programList.unitId)
  492. , programNames (programList.programNames)
  493. , parameter (nullptr)
  494. {
  495. }
  496. //------------------------------------------------------------------------
  497. int32 ProgramList::addProgram (const String128 name)
  498. {
  499. ++info.programCount;
  500. programNames.emplace_back (name);
  501. programInfos.emplace_back ();
  502. return static_cast<int32> (programNames.size ()) - 1;
  503. }
  504. //------------------------------------------------------------------------
  505. bool ProgramList::setProgramInfo (int32 programIndex, CString attributeId, const String128 value)
  506. {
  507. if (programIndex >= 0 && programIndex < static_cast<int32> (programNames.size ()))
  508. {
  509. programInfos.at (programIndex).insert (std::make_pair (attributeId, value));
  510. return true;
  511. }
  512. return false;
  513. }
  514. //------------------------------------------------------------------------
  515. tresult ProgramList::getProgramInfo (int32 programIndex, CString attributeId,
  516. String128 value /*out*/)
  517. {
  518. if (programIndex >= 0 && programIndex < static_cast<int32> (programNames.size ()))
  519. {
  520. StringMap::const_iterator it = programInfos[programIndex].find (attributeId);
  521. if (it != programInfos[programIndex].end ())
  522. {
  523. if (!it->second.isEmpty ())
  524. {
  525. it->second.copyTo16 (value, 0, 128);
  526. return kResultTrue;
  527. }
  528. }
  529. }
  530. return kResultFalse;
  531. }
  532. //------------------------------------------------------------------------
  533. tresult ProgramList::getProgramName (int32 programIndex, String128 name /*out*/)
  534. {
  535. if (programIndex >= 0 && programIndex < static_cast<int32> (programNames.size ()))
  536. {
  537. programNames.at (programIndex).copyTo16 (name, 0, 128);
  538. return kResultTrue;
  539. }
  540. return kResultFalse;
  541. }
  542. //------------------------------------------------------------------------
  543. tresult ProgramList::setProgramName (int32 programIndex, const String128 name /*in*/)
  544. {
  545. if (programIndex >= 0 && programIndex < static_cast<int32> (programNames.size ()))
  546. {
  547. programNames.at (programIndex) = name;
  548. if (parameter)
  549. {
  550. static_cast<StringListParameter*> (parameter)->replaceString (programIndex, name);
  551. }
  552. return kResultTrue;
  553. }
  554. return kResultFalse;
  555. }
  556. //------------------------------------------------------------------------
  557. Parameter* ProgramList::getParameter ()
  558. {
  559. if (parameter == nullptr)
  560. {
  561. auto* listParameter = new StringListParameter (
  562. info.name, info.id, nullptr,
  563. ParameterInfo::kCanAutomate | ParameterInfo::kIsList | ParameterInfo::kIsProgramChange,
  564. unitId);
  565. for (const auto& programName : programNames)
  566. {
  567. listParameter->appendString (programName);
  568. }
  569. parameter = listParameter;
  570. }
  571. return parameter;
  572. }
  573. //------------------------------------------------------------------------
  574. // ProgramListWithPitchNames implementation
  575. //-----------------------------------------------------------------------------
  576. ProgramListWithPitchNames::ProgramListWithPitchNames (const String128 name, ProgramListID listId,
  577. UnitID unitId)
  578. : ProgramList (name, listId, unitId)
  579. {
  580. }
  581. //-----------------------------------------------------------------------------
  582. int32 ProgramListWithPitchNames::addProgram (const String128 name)
  583. {
  584. int32 index = ProgramList::addProgram (name);
  585. if (index >= 0)
  586. pitchNames.emplace_back ();
  587. return index;
  588. }
  589. //-----------------------------------------------------------------------------
  590. bool ProgramListWithPitchNames::setPitchName (int32 programIndex, int16 pitch,
  591. const String128 pitchName)
  592. {
  593. if (programIndex < 0 || programIndex >= getCount ())
  594. return false;
  595. bool nameChanged = true;
  596. std::pair<PitchNameMap::iterator, bool> res =
  597. pitchNames[programIndex].insert (std::make_pair (pitch, pitchName));
  598. if (!res.second)
  599. {
  600. if (res.first->second == pitchName)
  601. nameChanged = false;
  602. else
  603. res.first->second = pitchName;
  604. }
  605. if (nameChanged)
  606. changed ();
  607. return true;
  608. }
  609. //-----------------------------------------------------------------------------
  610. bool ProgramListWithPitchNames::removePitchName (int32 programIndex, int16 pitch)
  611. {
  612. bool result = false;
  613. if (programIndex >= 0 && programIndex < getCount ())
  614. {
  615. result = pitchNames.at (programIndex).erase (pitch) != 0;
  616. }
  617. if (result)
  618. changed ();
  619. return result;
  620. }
  621. //-----------------------------------------------------------------------------
  622. tresult ProgramListWithPitchNames::hasPitchNames (int32 programIndex)
  623. {
  624. if (programIndex >= 0 && programIndex < getCount ())
  625. return (pitchNames.at (programIndex).empty () == true) ? kResultFalse : kResultTrue;
  626. return kResultFalse;
  627. }
  628. //-----------------------------------------------------------------------------
  629. tresult ProgramListWithPitchNames::getPitchName (int32 programIndex, int16 midiPitch,
  630. String128 name /*out*/)
  631. {
  632. if (programIndex >= 0 && programIndex < getCount ())
  633. {
  634. PitchNameMap::const_iterator it = pitchNames[programIndex].find (midiPitch);
  635. if (it != pitchNames[programIndex].end ())
  636. {
  637. it->second.copyTo16 (name, 0, 128);
  638. return kResultTrue;
  639. }
  640. }
  641. return kResultFalse;
  642. }
  643. //------------------------------------------------------------------------
  644. } // namespace Vst
  645. } // namespace Steinberg