mirror of https://github.com/AxioDL/amuse.git
Initial VST FilePresenter implementation
This commit is contained in:
parent
6f538dc19c
commit
e4ae1f1f88
|
@ -0,0 +1,310 @@
|
||||||
|
#include "AudioGroupFilePresenter.hpp"
|
||||||
|
#include "VSTBackend.hpp"
|
||||||
|
|
||||||
|
namespace amuse
|
||||||
|
{
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::loadProj()
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\proj";
|
||||||
|
athena::io::FileReader r(path, 1024 * 32, false);
|
||||||
|
if (r.hasError())
|
||||||
|
return false;
|
||||||
|
std::vector<uint8_t>& ret = m_projData;
|
||||||
|
size_t len = r.length();
|
||||||
|
ret.resize(len);
|
||||||
|
r.readUBytesToBuf(ret.data(), len);
|
||||||
|
return ret.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::loadPool()
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\pool";
|
||||||
|
athena::io::FileReader r(path, 1024 * 32, false);
|
||||||
|
if (r.hasError())
|
||||||
|
return false;
|
||||||
|
std::vector<uint8_t>& ret = m_poolData;
|
||||||
|
size_t len = r.length();
|
||||||
|
ret.resize(len);
|
||||||
|
r.readUBytesToBuf(ret.data(), len);
|
||||||
|
return ret.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::loadSdir()
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\sdir";
|
||||||
|
athena::io::FileReader r(path, 1024 * 32, false);
|
||||||
|
if (r.hasError())
|
||||||
|
return false;
|
||||||
|
std::vector<uint8_t>& ret = m_sdirData;
|
||||||
|
size_t len = r.length();
|
||||||
|
ret.resize(len);
|
||||||
|
r.readUBytesToBuf(ret.data(), len);
|
||||||
|
return ret.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::loadSamp()
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\samp";
|
||||||
|
athena::io::FileReader r(path, 1024 * 32, false);
|
||||||
|
if (r.hasError())
|
||||||
|
return false;
|
||||||
|
std::vector<uint8_t>& ret = m_sampData;
|
||||||
|
size_t len = r.length();
|
||||||
|
ret.resize(len);
|
||||||
|
r.readUBytesToBuf(ret.data(), len);
|
||||||
|
return ret.size() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::loadMeta()
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\meta";
|
||||||
|
athena::io::FileReader r(path, 1024 * 32, false);
|
||||||
|
if (r.hasError())
|
||||||
|
return false;
|
||||||
|
std::experimental::optional<MetaData>& ret = m_metaData;
|
||||||
|
ret.emplace(r);
|
||||||
|
return ret.operator bool();
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioGroupDataCollection::AudioGroupDataCollection(const std::wstring& path, const std::wstring& name)
|
||||||
|
: m_path(path), m_name(name)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::_attemptLoad(AudioGroupFilePresenter& presenter)
|
||||||
|
{
|
||||||
|
if (m_metaData && m_loadedData && m_loadedGroup)
|
||||||
|
return true;
|
||||||
|
if (!loadProj())
|
||||||
|
return false;
|
||||||
|
if (!loadPool())
|
||||||
|
return false;
|
||||||
|
if (!loadSdir())
|
||||||
|
return false;
|
||||||
|
if (!loadSamp())
|
||||||
|
return false;
|
||||||
|
if (!loadMeta())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _indexData(presenter);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioGroupDataCollection::_indexData(AudioGroupFilePresenter& presenter)
|
||||||
|
{
|
||||||
|
amuse::Engine& engine = presenter.getBackend().getAmuseEngine();
|
||||||
|
|
||||||
|
switch (m_metaData->fmt)
|
||||||
|
{
|
||||||
|
case amuse::DataFormat::GCN:
|
||||||
|
default:
|
||||||
|
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
||||||
|
m_poolData.data(), m_poolData.size(),
|
||||||
|
m_sdirData.data(), m_sdirData.size(),
|
||||||
|
m_sampData.data(), m_sampData.size(),
|
||||||
|
amuse::GCNDataTag{});
|
||||||
|
break;
|
||||||
|
case amuse::DataFormat::N64:
|
||||||
|
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
||||||
|
m_poolData.data(), m_poolData.size(),
|
||||||
|
m_sdirData.data(), m_sdirData.size(),
|
||||||
|
m_sampData.data(), m_sampData.size(),
|
||||||
|
m_metaData->absOffs, amuse::N64DataTag{});
|
||||||
|
break;
|
||||||
|
case amuse::DataFormat::PC:
|
||||||
|
m_loadedData.emplace(m_projData.data(), m_projData.size(),
|
||||||
|
m_poolData.data(), m_poolData.size(),
|
||||||
|
m_sdirData.data(), m_sdirData.size(),
|
||||||
|
m_sampData.data(), m_sampData.size(),
|
||||||
|
m_metaData->absOffs, amuse::PCDataTag{});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_loadedGroup = engine.addAudioGroup(*m_loadedData);
|
||||||
|
m_groupTokens.clear();
|
||||||
|
if (m_loadedGroup)
|
||||||
|
{
|
||||||
|
m_groupTokens.reserve(m_loadedGroup->getProj().songGroups().size() +
|
||||||
|
m_loadedGroup->getProj().sfxGroups().size());
|
||||||
|
|
||||||
|
{
|
||||||
|
const auto& songGroups = m_loadedGroup->getProj().songGroups();
|
||||||
|
std::map<int, const amuse::SongGroupIndex*> sortGroups;
|
||||||
|
for (const auto& pair : songGroups)
|
||||||
|
sortGroups[pair.first] = &pair.second;
|
||||||
|
for (const auto& pair : sortGroups)
|
||||||
|
m_groupTokens.emplace_back(pair.first, pair.second);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& sfxGroups = m_loadedGroup->getProj().sfxGroups();
|
||||||
|
std::map<int, const amuse::SFXGroupIndex*> sortGroups;
|
||||||
|
for (const auto& pair : sfxGroups)
|
||||||
|
sortGroups[pair.first] = &pair.second;
|
||||||
|
for (const auto& pair : sortGroups)
|
||||||
|
m_groupTokens.emplace_back(pair.first, pair.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_loadedData && m_loadedGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioGroupCollection::AudioGroupCollection(const std::wstring& path, const std::wstring& name)
|
||||||
|
: m_path(path), m_name(name)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioGroupCollection::addCollection(AudioGroupFilePresenter& presenter,
|
||||||
|
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection)
|
||||||
|
{
|
||||||
|
for (std::pair<std::wstring, amuse::IntrusiveAudioGroupData>& pair : collection)
|
||||||
|
{
|
||||||
|
std::wstring collectionPath = m_path + L'\\' + pair.first;
|
||||||
|
|
||||||
|
amuse::IntrusiveAudioGroupData& dataIn = pair.second;
|
||||||
|
auto search = m_groups.find(pair.first);
|
||||||
|
if (search == m_groups.end())
|
||||||
|
{
|
||||||
|
search = m_groups.emplace(pair.first,
|
||||||
|
std::make_unique<AudioGroupDataCollection>(collectionPath,
|
||||||
|
pair.first)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioGroupDataCollection& dataCollection = *search->second;
|
||||||
|
dataCollection.m_projData.resize(dataIn.getProjSize());
|
||||||
|
memmove(dataCollection.m_projData.data(), dataIn.getProj(), dataIn.getProjSize());
|
||||||
|
|
||||||
|
dataCollection.m_poolData.resize(dataIn.getPoolSize());
|
||||||
|
memmove(dataCollection.m_poolData.data(), dataIn.getPool(), dataIn.getPoolSize());
|
||||||
|
|
||||||
|
dataCollection.m_sdirData.resize(dataIn.getSdirSize());
|
||||||
|
memmove(dataCollection.m_sdirData.data(), dataIn.getSdir(), dataIn.getSdirSize());
|
||||||
|
|
||||||
|
dataCollection.m_sampData.resize(dataIn.getSampSize());
|
||||||
|
memmove(dataCollection.m_sampData.data(), dataIn.getSamp(), dataIn.getSampSize());
|
||||||
|
|
||||||
|
dataCollection.m_metaData.emplace(dataIn.getDataFormat(), dataIn.getAbsoluteProjOffsets(), true);
|
||||||
|
dataCollection._indexData(presenter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioGroupCollection::update(AudioGroupFilePresenter& presenter)
|
||||||
|
{
|
||||||
|
std::wstring path = m_path + L"\\*";
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW d;
|
||||||
|
HANDLE dir = FindFirstFileW(path.c_str(), &d);
|
||||||
|
if (dir == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
std::wstring nameStr(d.cFileName);
|
||||||
|
auto search = m_groups.find(nameStr);
|
||||||
|
if (search == m_groups.end())
|
||||||
|
{
|
||||||
|
search =
|
||||||
|
m_groups.emplace(nameStr,
|
||||||
|
std::make_unique<AudioGroupDataCollection>(m_path + L'\\' + nameStr,
|
||||||
|
nameStr)).first;
|
||||||
|
search->second->_attemptLoad(presenter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(dir, &d));
|
||||||
|
|
||||||
|
FindClose(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioGroupFilePresenter::update()
|
||||||
|
{
|
||||||
|
std::wstring path = m_backend.getUserDir() + L"\\*";
|
||||||
|
std::map<std::wstring, std::unique_ptr<AudioGroupCollection>>& theMap = m_audioGroupCollections;
|
||||||
|
|
||||||
|
WIN32_FIND_DATAW d;
|
||||||
|
HANDLE dir = FindFirstFileW(path.c_str(), &d);
|
||||||
|
if (dir == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!wcscmp(d.cFileName, L".") || !wcscmp(d.cFileName, L".."))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
{
|
||||||
|
std::wstring nameStr(d.cFileName);
|
||||||
|
auto search = theMap.find(nameStr);
|
||||||
|
if (search == theMap.end())
|
||||||
|
{
|
||||||
|
search = theMap.emplace(nameStr,
|
||||||
|
std::make_unique<AudioGroupCollection>(m_backend.getUserDir() + L'\\' + nameStr, nameStr)).first;
|
||||||
|
search->second->update(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (FindNextFileW(dir, &d));
|
||||||
|
|
||||||
|
FindClose(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioGroupFilePresenter::addCollection(const std::wstring& name,
|
||||||
|
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection)
|
||||||
|
{
|
||||||
|
std::wstring path = m_backend.getUserDir() + L'\\' + name;
|
||||||
|
AudioGroupCollection& insert = *m_audioGroupCollections.emplace(name, std::make_unique<AudioGroupCollection>(path, name)).first->second;
|
||||||
|
insert.addCollection(*this, std::move(collection));
|
||||||
|
|
||||||
|
for (std::pair<const std::wstring, std::unique_ptr<AudioGroupDataCollection>>& pair : insert.m_groups)
|
||||||
|
{
|
||||||
|
std::wstring collectionPath = insert.m_path + L'\\' + pair.first;
|
||||||
|
CreateDirectory(collectionPath.c_str(), nullptr);
|
||||||
|
|
||||||
|
FILE* fp = _wfopen((collectionPath + L"\\proj").c_str(), L"wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite(pair.second->m_projData.data(), 1, pair.second->m_projData.size(), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = _wfopen((collectionPath + L"\\pool").c_str(), L"wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite(pair.second->m_poolData.data(), 1, pair.second->m_poolData.size(), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = _wfopen((collectionPath + L"\\sdir").c_str(), L"wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite(pair.second->m_sdirData.data(), 1, pair.second->m_sdirData.size(), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = _wfopen((collectionPath + L"\\samp").c_str(), L"wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite(pair.second->m_sampData.data(), 1, pair.second->m_sampData.size(), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = _wfopen((collectionPath + L"\\meta").c_str(), L"wb");
|
||||||
|
if (fp)
|
||||||
|
{
|
||||||
|
fwrite(&*pair.second->m_metaData, 1, sizeof(*pair.second->m_metaData), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioGroupFilePresenter::populateEditor(VSTEditor& editor)
|
||||||
|
{
|
||||||
|
for (const auto& cgollection : m_audioGroupCollections)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
#ifndef __AMUSE_AUDIOGROUPFILEPRESENTER_HPP__
|
||||||
|
#define __AMUSE_AUDIOGROUPFILEPRESENTER_HPP__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include "optional.hpp"
|
||||||
|
#include <amuse/amuse.hpp>
|
||||||
|
#include <athena/FileReader.hpp>
|
||||||
|
|
||||||
|
namespace amuse
|
||||||
|
{
|
||||||
|
class VSTBackend;
|
||||||
|
class VSTEditor;
|
||||||
|
class AudioGroupFilePresenter;
|
||||||
|
|
||||||
|
struct AudioGroupDataCollection
|
||||||
|
{
|
||||||
|
std::wstring m_path;
|
||||||
|
std::wstring m_name;
|
||||||
|
|
||||||
|
std::vector<uint8_t> m_projData;
|
||||||
|
std::vector<uint8_t> m_poolData;
|
||||||
|
std::vector<uint8_t> m_sdirData;
|
||||||
|
std::vector<uint8_t> m_sampData;
|
||||||
|
|
||||||
|
struct MetaData
|
||||||
|
{
|
||||||
|
amuse::DataFormat fmt;
|
||||||
|
uint32_t absOffs;
|
||||||
|
uint32_t active;
|
||||||
|
MetaData(amuse::DataFormat fmtIn, uint32_t absOffsIn, uint32_t activeIn)
|
||||||
|
: fmt(fmtIn), absOffs(absOffsIn), active(activeIn) {}
|
||||||
|
MetaData(athena::io::FileReader& r)
|
||||||
|
: fmt(amuse::DataFormat(r.readUint32Little())), absOffs(r.readUint32Little()), active(r.readUint32Little()) {}
|
||||||
|
};
|
||||||
|
std::experimental::optional<MetaData> m_metaData;
|
||||||
|
|
||||||
|
std::experimental::optional<amuse::AudioGroupData> m_loadedData;
|
||||||
|
const amuse::AudioGroup* m_loadedGroup;
|
||||||
|
struct GroupToken
|
||||||
|
{
|
||||||
|
int m_groupId;
|
||||||
|
const amuse::SongGroupIndex* m_song = nullptr;
|
||||||
|
const amuse::SFXGroupIndex* m_sfx = nullptr;
|
||||||
|
GroupToken(int id, const amuse::SongGroupIndex* song) : m_groupId(id), m_song(song) {}
|
||||||
|
GroupToken(int id, const amuse::SFXGroupIndex* sfx) : m_groupId(id), m_sfx(sfx) {}
|
||||||
|
};
|
||||||
|
std::vector<GroupToken> m_groupTokens;
|
||||||
|
|
||||||
|
bool loadProj();
|
||||||
|
bool loadPool();
|
||||||
|
bool loadSdir();
|
||||||
|
bool loadSamp();
|
||||||
|
bool loadMeta();
|
||||||
|
|
||||||
|
AudioGroupDataCollection(const std::wstring& path, const std::wstring& name);
|
||||||
|
bool isDataComplete() const {return m_projData.size() && m_poolData.size() && m_sdirData.size() && m_sampData.size() && m_metaData;}
|
||||||
|
bool _attemptLoad(AudioGroupFilePresenter& presenter);
|
||||||
|
bool _indexData(AudioGroupFilePresenter& presenter);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AudioGroupCollection
|
||||||
|
{
|
||||||
|
std::wstring m_path;
|
||||||
|
std::wstring m_name;
|
||||||
|
|
||||||
|
std::map<std::wstring, std::unique_ptr<AudioGroupDataCollection>> m_groups;
|
||||||
|
|
||||||
|
AudioGroupCollection(const std::wstring& path, const std::wstring& name);
|
||||||
|
void addCollection(AudioGroupFilePresenter& presenter,
|
||||||
|
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection);
|
||||||
|
void update(AudioGroupFilePresenter& presenter);
|
||||||
|
|
||||||
|
//void populate
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioGroupFilePresenter
|
||||||
|
{
|
||||||
|
VSTBackend& m_backend;
|
||||||
|
std::map<std::wstring, std::unique_ptr<AudioGroupCollection>> m_audioGroupCollections;
|
||||||
|
public:
|
||||||
|
AudioGroupFilePresenter(VSTBackend& backend) : m_backend(backend) {}
|
||||||
|
void update();
|
||||||
|
void populateEditor(VSTEditor& editor);
|
||||||
|
void addCollection(const std::wstring& name,
|
||||||
|
std::vector<std::pair<std::wstring, amuse::IntrusiveAudioGroupData>>&& collection);
|
||||||
|
VSTBackend& getBackend() {return m_backend;}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __AMUSE_AUDIOGROUPFILEPRESENTER_HPP__
|
|
@ -7,10 +7,12 @@ if (WIN32 AND (EXISTS ${VST3_SDK_ROOT}))
|
||||||
add_library(amuse-vst SHARED
|
add_library(amuse-vst SHARED
|
||||||
VSTBackend.hpp VSTBackend.cpp
|
VSTBackend.hpp VSTBackend.cpp
|
||||||
VSTEditor.hpp VSTEditor.cpp
|
VSTEditor.hpp VSTEditor.cpp
|
||||||
|
AudioGroupFilePresenter.hpp AudioGroupFilePresenter.cpp
|
||||||
${VST2_DIR}/vstplugmain.cpp
|
${VST2_DIR}/vstplugmain.cpp
|
||||||
${VST2_DIR}/audioeffect.cpp
|
${VST2_DIR}/audioeffect.cpp
|
||||||
${VST2_DIR}/audioeffectx.cpp)
|
${VST2_DIR}/audioeffectx.cpp
|
||||||
|
FileOpenDialog.hpp FileOpenDialog.cpp)
|
||||||
target_link_libraries(amuse-vst amuse boo soxr ${ZLIB_LIBRARIES} ${BOO_SYS_LIBS}
|
target_link_libraries(amuse-vst amuse boo soxr ${ZLIB_LIBRARIES} ${BOO_SYS_LIBS}
|
||||||
Msimg32 logvisor athena-core)
|
Msimg32 Shlwapi logvisor athena-core)
|
||||||
set_target_properties(amuse-vst PROPERTIES LINK_FLAGS "/EXPORT:VSTPluginMain")
|
set_target_properties(amuse-vst PROPERTIES LINK_FLAGS "/EXPORT:VSTPluginMain")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -0,0 +1,238 @@
|
||||||
|
#include "FileOpenDialog.hpp"
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h> // For common windows data types and function headers
|
||||||
|
#define STRICT_TYPED_ITEMIDS
|
||||||
|
#include <objbase.h> // For COM headers
|
||||||
|
#include <shobjidl.h> // for IFileDialogEvents and IFileDialogControlEvents
|
||||||
|
#include <shlwapi.h>
|
||||||
|
#include <knownfolders.h> // for KnownFolder APIs/datatypes/function headers
|
||||||
|
#include <propvarutil.h> // for PROPVAR-related functions
|
||||||
|
#include <propkey.h> // for the Property key APIs/datatypes
|
||||||
|
#include <propidl.h> // for the Property System APIs
|
||||||
|
#include <strsafe.h> // for StringCchPrintfW
|
||||||
|
#include <shtypes.h> // for COMDLG_FILTERSPEC
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
#define CONTROL_GROUP 2000
|
||||||
|
#define CONTROL_RADIOBUTTONLIST 2
|
||||||
|
#define CONTROL_RADIOBUTTON1 1
|
||||||
|
#define CONTROL_RADIOBUTTON2 2 // It is OK for this to have the same IDas CONTROL_RADIOBUTTONLIST,
|
||||||
|
// because it is a child control under CONTROL_RADIOBUTTONLIST
|
||||||
|
|
||||||
|
// IDs for the Task Dialog Buttons
|
||||||
|
#define IDC_BASICFILEOPEN 100
|
||||||
|
#define IDC_ADDITEMSTOCUSTOMPLACES 101
|
||||||
|
#define IDC_ADDCUSTOMCONTROLS 102
|
||||||
|
#define IDC_SETDEFAULTVALUESFORPROPERTIES 103
|
||||||
|
#define IDC_WRITEPROPERTIESUSINGHANDLERS 104
|
||||||
|
#define IDC_WRITEPROPERTIESWITHOUTUSINGHANDLERS 105
|
||||||
|
|
||||||
|
HWND ghMainWnd = 0;
|
||||||
|
HINSTANCE ghAppInst = 0;
|
||||||
|
RECT winRect;
|
||||||
|
|
||||||
|
class CDialogEventHandler : public IFileDialogEvents,
|
||||||
|
public IFileDialogControlEvents
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// IUnknown methods
|
||||||
|
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
|
||||||
|
{
|
||||||
|
static const QITAB qit[] = {
|
||||||
|
QITABENT(CDialogEventHandler, IFileDialogEvents),
|
||||||
|
QITABENT(CDialogEventHandler, IFileDialogControlEvents),
|
||||||
|
{ 0 },
|
||||||
|
};
|
||||||
|
return QISearch(this, qit, riid, ppv);
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(ULONG) AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&_cRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
IFACEMETHODIMP_(ULONG) Release()
|
||||||
|
{
|
||||||
|
long cRef = InterlockedDecrement(&_cRef);
|
||||||
|
if (!cRef)
|
||||||
|
delete this;
|
||||||
|
return cRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFileDialogEvents methods
|
||||||
|
IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnTypeChange(IFileDialog *pfd);
|
||||||
|
IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };
|
||||||
|
|
||||||
|
// IFileDialogControlEvents methods
|
||||||
|
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem);
|
||||||
|
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *, DWORD, BOOL) { return S_OK; };
|
||||||
|
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; };
|
||||||
|
|
||||||
|
CDialogEventHandler() : _cRef(1) { };
|
||||||
|
private:
|
||||||
|
~CDialogEventHandler() { };
|
||||||
|
long _cRef;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv);
|
||||||
|
|
||||||
|
std::wstring openDB()
|
||||||
|
{
|
||||||
|
std::wstring ret;
|
||||||
|
|
||||||
|
//Cocreate the file open dialog object
|
||||||
|
IFileDialog *pfd = NULL;
|
||||||
|
|
||||||
|
HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Stuff needed for later
|
||||||
|
const COMDLG_FILTERSPEC rgFExt[] = {{L"Audio Group Archive (*.*)", L"*.*"}};
|
||||||
|
|
||||||
|
//Create event handling
|
||||||
|
IFileDialogEvents *pfde = NULL;
|
||||||
|
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
|
||||||
|
|
||||||
|
if(SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Hook the event handler
|
||||||
|
DWORD dwCookie;
|
||||||
|
|
||||||
|
hr = pfd->Advise(pfde, &dwCookie);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Set options for the dialog
|
||||||
|
DWORD dwFlags;
|
||||||
|
|
||||||
|
//Get options first so we do not override
|
||||||
|
hr = pfd->GetOptions(&dwFlags);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Get shell items only
|
||||||
|
hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Types of files to display (not default)
|
||||||
|
hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Set default file type to display
|
||||||
|
//hr = pfd->SetDefaultExtension(L"sqlite");
|
||||||
|
|
||||||
|
//if (SUCCEEDED(hr))
|
||||||
|
//{
|
||||||
|
//Show dialog
|
||||||
|
hr = pfd->Show(NULL);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Get the result once the user clicks on open
|
||||||
|
IShellItem *result;
|
||||||
|
|
||||||
|
hr = pfd->GetResult(&result);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
//Print out the file name
|
||||||
|
PWSTR fName = NULL;
|
||||||
|
|
||||||
|
hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ret.assign(fName);
|
||||||
|
CoTaskMemFree(fName);
|
||||||
|
}
|
||||||
|
|
||||||
|
result->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd->Unadvise(dwCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfde->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
pfd->Release();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
|
||||||
|
{
|
||||||
|
*ppv = NULL;
|
||||||
|
CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
|
||||||
|
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pDialogEventHandler->QueryInterface(riid, ppv);
|
||||||
|
pDialogEventHandler->Release();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CDialogEventHandler::OnTypeChange(IFileDialog *pfd)
|
||||||
|
{
|
||||||
|
IFileSaveDialog *pfsd;
|
||||||
|
HRESULT hr = pfd->QueryInterface(&pfsd);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
UINT uIndex;
|
||||||
|
hr = pfsd->GetFileTypeIndex(&uIndex); // index of current file-type
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IPropertyDescriptionList *pdl = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
pfsd->Release();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IFileDialogControlEvents
|
||||||
|
// This method gets called when an dialog control item selection happens (radio-button selection. etc).
|
||||||
|
// For sample sake, let's react to this event by changing the dialog title.
|
||||||
|
HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem)
|
||||||
|
{
|
||||||
|
IFileDialog *pfd = NULL;
|
||||||
|
HRESULT hr = pfdc->QueryInterface(&pfd);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (dwIDCtl == CONTROL_RADIOBUTTONLIST)
|
||||||
|
{
|
||||||
|
switch (dwIDItem)
|
||||||
|
{
|
||||||
|
case CONTROL_RADIOBUTTON1:
|
||||||
|
hr = pfd->SetTitle(L"Longhorn Dialog");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CONTROL_RADIOBUTTON2:
|
||||||
|
hr = pfd->SetTitle(L"Vista Dialog");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pfd->Release();
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __AMUSE_FILEOPENDIALOG_HPP__
|
||||||
|
#define __AMUSE_FILEOPENDIALOG_HPP__
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
std::wstring openDB();
|
||||||
|
|
||||||
|
#endif // __AMUSE_FILEOPENDIALOG_HPP__
|
|
@ -1,5 +1,6 @@
|
||||||
#include "VSTBackend.hpp"
|
#include "VSTBackend.hpp"
|
||||||
#include "audiodev/AudioVoiceEngine.hpp"
|
#include "audiodev/AudioVoiceEngine.hpp"
|
||||||
|
#include <Shlobj.h>
|
||||||
#include <logvisor/logvisor.hpp>
|
#include <logvisor/logvisor.hpp>
|
||||||
|
|
||||||
struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
struct VSTVoiceEngine : boo::BaseAudioVoiceEngine
|
||||||
|
@ -141,6 +142,13 @@ VSTBackend::VSTBackend(audioMasterCallback cb)
|
||||||
m_booBackend = std::make_unique<VSTVoiceEngine>();
|
m_booBackend = std::make_unique<VSTVoiceEngine>();
|
||||||
m_voxAlloc.emplace(*m_booBackend);
|
m_voxAlloc.emplace(*m_booBackend);
|
||||||
m_engine.emplace(*m_voxAlloc);
|
m_engine.emplace(*m_voxAlloc);
|
||||||
|
|
||||||
|
WCHAR path[MAX_PATH];
|
||||||
|
if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path)))
|
||||||
|
{
|
||||||
|
m_userDir = std::wstring(path) + L"\\Amuse";
|
||||||
|
CreateDirectory(m_userDir.c_str(), nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VSTBackend::~VSTBackend()
|
VSTBackend::~VSTBackend()
|
||||||
|
|
|
@ -31,6 +31,7 @@ class VSTBackend : public AudioEffectX
|
||||||
std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc;
|
std::experimental::optional<amuse::VSTBackendVoiceAllocator> m_voxAlloc;
|
||||||
std::experimental::optional<amuse::Engine> m_engine;
|
std::experimental::optional<amuse::Engine> m_engine;
|
||||||
size_t m_curFrame = 0;
|
size_t m_curFrame = 0;
|
||||||
|
std::wstring m_userDir;
|
||||||
VSTEditor m_editor;
|
VSTEditor m_editor;
|
||||||
public:
|
public:
|
||||||
VSTBackend(audioMasterCallback cb);
|
VSTBackend(audioMasterCallback cb);
|
||||||
|
@ -48,6 +49,9 @@ public:
|
||||||
VstInt32 getNumMidiInputChannels();
|
VstInt32 getNumMidiInputChannels();
|
||||||
void setSampleRate(float sampleRate);
|
void setSampleRate(float sampleRate);
|
||||||
void setBlockSize(VstInt32 blockSize);
|
void setBlockSize(VstInt32 blockSize);
|
||||||
|
|
||||||
|
amuse::Engine& getAmuseEngine() {return *m_engine;}
|
||||||
|
const std::wstring& getUserDir() const {return m_userDir;}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#include "VSTEditor.hpp"
|
#include "VSTEditor.hpp"
|
||||||
#include "VSTBackend.hpp"
|
#include "VSTBackend.hpp"
|
||||||
|
#include "FileOpenDialog.hpp"
|
||||||
|
#include <Windowsx.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
extern void* hInstance;
|
extern void* hInstance;
|
||||||
static WNDPROC OriginalListViewProc = 0;
|
static WNDPROC OriginalListViewProc = 0;
|
||||||
|
@ -45,6 +48,31 @@ LRESULT CALLBACK VSTEditor::WindowProc(HWND hwnd,
|
||||||
editor.selectPage(itemAct.iItem);
|
editor.selectPage(itemAct.iItem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case TVN_GETDISPINFO:
|
||||||
|
{
|
||||||
|
NMTVDISPINFO& treeDispInfo = *reinterpret_cast<LPNMTVDISPINFO>(lParam);
|
||||||
|
if (treeDispInfo.item.mask & TVIF_CHILDREN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case WM_COMMAND:
|
||||||
|
{
|
||||||
|
switch (HIWORD(wParam))
|
||||||
|
{
|
||||||
|
case BN_CLICKED:
|
||||||
|
{
|
||||||
|
HWND button = HWND(lParam);
|
||||||
|
if (button == editor.m_collectionAdd)
|
||||||
|
editor.addAction();
|
||||||
|
else if (button == editor.m_collectionRemove)
|
||||||
|
editor.removeAction();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
@ -137,34 +165,56 @@ bool VSTEditor::open(void* ptr)
|
||||||
SetWindowLongPtrW(m_rootView, 0, LONG_PTR(this));
|
SetWindowLongPtrW(m_rootView, 0, LONG_PTR(this));
|
||||||
ShowWindow(m_rootView, SW_SHOW);
|
ShowWindow(m_rootView, SW_SHOW);
|
||||||
|
|
||||||
|
TVINSERTSTRUCT treeItem = {};
|
||||||
|
treeItem.hParent = TVI_ROOT;
|
||||||
|
treeItem.hInsertAfter = TVI_LAST;
|
||||||
|
|
||||||
|
treeItem.item.mask = TVIF_CHILDREN | TVIF_TEXT;
|
||||||
|
treeItem.item.cChildren = 1;
|
||||||
|
treeItem.item.pszText = L"Root A";
|
||||||
|
|
||||||
LVCOLUMN column = {};
|
LVCOLUMN column = {};
|
||||||
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
||||||
column.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH;
|
column.fmt = LVCFMT_LEFT | LVCFMT_FIXED_WIDTH;
|
||||||
column.cx = 200;
|
column.cx = 199;
|
||||||
|
|
||||||
LVITEM item = {};
|
LVITEM item = {};
|
||||||
item.mask = LVIF_TEXT | LVIF_GROUPID;
|
item.mask = LVIF_TEXT;
|
||||||
item.pszText = L"Test";
|
item.pszText = L"Test";
|
||||||
item.iGroupId = 1;
|
|
||||||
|
|
||||||
m_collectionTree = CreateWindowW(WC_TREEVIEW,
|
m_collectionTree = CreateWindowW(WC_TREEVIEW,
|
||||||
L"",
|
L"",
|
||||||
WS_CHILD | WS_BORDER | TVS_HASLINES,
|
WS_CHILD | WS_CLIPSIBLINGS | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS,
|
||||||
0, 24,
|
1, 25,
|
||||||
201,
|
199,
|
||||||
m_windowRect.bottom - m_windowRect.top - 24,
|
m_windowRect.bottom - m_windowRect.top - 26,
|
||||||
m_rootView,
|
m_rootView,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr);
|
nullptr);
|
||||||
TreeView_SetBkColor(m_collectionTree, RGB(64,64,64));
|
TreeView_SetBkColor(m_collectionTree, RGB(64,64,64));
|
||||||
|
TreeView_SetTextColor(m_collectionTree, RGB(255,255,255));
|
||||||
|
HTREEITEM rootItemA = TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
treeItem.item.pszText = L"Root B";
|
||||||
|
HTREEITEM rootItemB = TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
treeItem.hParent = rootItemA;
|
||||||
|
treeItem.item.cChildren = 0;
|
||||||
|
treeItem.item.pszText = L"Child A";
|
||||||
|
TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
treeItem.item.pszText = L"Child B";
|
||||||
|
TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
treeItem.hParent = rootItemB;
|
||||||
|
treeItem.item.pszText = L"Child A";
|
||||||
|
TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
|
treeItem.item.pszText = L"Child B";
|
||||||
|
TreeView_InsertItem(m_collectionTree, &treeItem);
|
||||||
ShowWindow(m_collectionTree, SW_SHOW);
|
ShowWindow(m_collectionTree, SW_SHOW);
|
||||||
|
|
||||||
m_collectionHeader = CreateWindowW(WC_HEADER,
|
m_collectionHeader = CreateWindowW(WC_HEADER,
|
||||||
L"",
|
L"",
|
||||||
WS_CHILD,
|
WS_CHILD,
|
||||||
1, 1,
|
1, 1,
|
||||||
200,
|
199,
|
||||||
24,
|
24,
|
||||||
m_rootView,
|
m_rootView,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -174,12 +224,39 @@ bool VSTEditor::open(void* ptr)
|
||||||
OriginalListViewProc = WNDPROC(SetWindowLongPtr(m_collectionHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
|
OriginalListViewProc = WNDPROC(SetWindowLongPtr(m_collectionHeader, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc)));
|
||||||
ShowWindow(m_collectionHeader, SW_SHOW);
|
ShowWindow(m_collectionHeader, SW_SHOW);
|
||||||
|
|
||||||
|
m_collectionAdd = CreateWindowW(WC_BUTTON,
|
||||||
|
L"+",
|
||||||
|
WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON,
|
||||||
|
1, m_windowRect.bottom - m_windowRect.top - 26,
|
||||||
|
25, 24,
|
||||||
|
m_rootView,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
SetWindowFont(m_collectionAdd, GetStockObject(ANSI_FIXED_FONT), FALSE);
|
||||||
|
Button_Enable(m_collectionAdd, TRUE);
|
||||||
|
SetWindowPos(m_collectionAdd, HWND_TOP, 1, m_windowRect.bottom - m_windowRect.top - 26, 25, 24, SWP_SHOWWINDOW);
|
||||||
|
|
||||||
|
m_collectionRemove = CreateWindowW(WC_BUTTON,
|
||||||
|
L"-",
|
||||||
|
WS_CHILD | WS_CLIPSIBLINGS | BS_PUSHBUTTON,
|
||||||
|
26, m_windowRect.bottom - m_windowRect.top - 26,
|
||||||
|
25, 24,
|
||||||
|
m_rootView,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
SetWindowFont(m_collectionRemove, GetStockObject(ANSI_FIXED_FONT), FALSE);
|
||||||
|
Button_Enable(m_collectionRemove, TRUE);
|
||||||
|
SetWindowPos(m_collectionRemove, HWND_TOP, 26, m_windowRect.bottom - m_windowRect.top - 26, 25, 24, SWP_SHOWWINDOW);
|
||||||
|
|
||||||
|
|
||||||
m_groupListView = CreateWindowW(WC_LISTVIEW,
|
m_groupListView = CreateWindowW(WC_LISTVIEW,
|
||||||
L"",
|
L"",
|
||||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||||
200, 0,
|
201, 1,
|
||||||
201,
|
199,
|
||||||
m_windowRect.bottom - m_windowRect.top,
|
m_windowRect.bottom - m_windowRect.top - 2,
|
||||||
m_rootView,
|
m_rootView,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -189,25 +266,32 @@ bool VSTEditor::open(void* ptr)
|
||||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||||
ListView_SetBkColor(m_groupListView, RGB(64,64,64));
|
ListView_SetBkColor(m_groupListView, RGB(64,64,64));
|
||||||
|
ListView_SetTextBkColor(m_groupListView, CLR_NONE);
|
||||||
|
ListView_SetTextColor(m_groupListView, RGB(255,255,255));
|
||||||
ListView_InsertColumn(m_groupListView, 0, &column);
|
ListView_InsertColumn(m_groupListView, 0, &column);
|
||||||
|
ListView_InsertItem(m_groupListView, &item);
|
||||||
ShowWindow(m_groupListView, SW_SHOW);
|
ShowWindow(m_groupListView, SW_SHOW);
|
||||||
|
|
||||||
m_pageListView = CreateWindowW(WC_LISTVIEW,
|
m_pageListView = CreateWindowW(WC_LISTVIEW,
|
||||||
L"",
|
L"",
|
||||||
WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
WS_CHILD | LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER,
|
||||||
400, 0,
|
401, 1,
|
||||||
200,
|
198,
|
||||||
m_windowRect.bottom - m_windowRect.top,
|
m_windowRect.bottom - m_windowRect.top - 2,
|
||||||
m_rootView,
|
m_rootView,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr);
|
nullptr);
|
||||||
column.pszText = L"Page";
|
column.pszText = L"Page";
|
||||||
|
column.cx = 198;
|
||||||
header = ListView_GetHeader(m_pageListView);
|
header = ListView_GetHeader(m_pageListView);
|
||||||
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
SetWindowLongPtrW(header, GWLP_USERDATA, LONG_PTR(column.pszText));
|
||||||
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
SetWindowLongPtr(header, GWLP_WNDPROC, LONG_PTR(ColHeaderWindowProc));
|
||||||
ListView_SetBkColor(m_pageListView, RGB(64,64,64));
|
ListView_SetBkColor(m_pageListView, RGB(64,64,64));
|
||||||
|
ListView_SetTextBkColor(m_pageListView, CLR_NONE);
|
||||||
|
ListView_SetTextColor(m_pageListView, RGB(255,255,255));
|
||||||
ListView_InsertColumn(m_pageListView, 0, &column);
|
ListView_InsertColumn(m_pageListView, 0, &column);
|
||||||
|
ListView_InsertItem(m_pageListView, &item);
|
||||||
ShowWindow(m_pageListView, SW_SHOW);
|
ShowWindow(m_pageListView, SW_SHOW);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -224,6 +308,31 @@ void VSTEditor::update()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VSTEditor::addAction()
|
||||||
|
{
|
||||||
|
VstFileSelect fSelect = {};
|
||||||
|
fSelect.command = kVstFileLoad;
|
||||||
|
fSelect.type = kVstFileType;
|
||||||
|
strcpy(fSelect.title, "Select Audio Group Archive");
|
||||||
|
if (m_backend.openFileSelector(&fSelect))
|
||||||
|
{
|
||||||
|
m_backend.closeFileSelector(&fSelect);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::wstring path = openDB();
|
||||||
|
if (path.size())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VSTEditor::removeAction()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void VSTEditor::selectCollection(int idx)
|
void VSTEditor::selectCollection(int idx)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,16 @@ class VSTBackend;
|
||||||
/** Editor UI class */
|
/** Editor UI class */
|
||||||
class VSTEditor : public AEffEditor
|
class VSTEditor : public AEffEditor
|
||||||
{
|
{
|
||||||
|
friend class AudioGroupFilePresenter;
|
||||||
|
|
||||||
VSTBackend& m_backend;
|
VSTBackend& m_backend;
|
||||||
ERect m_windowRect = {0, 0, 420, 600};
|
ERect m_windowRect = {0, 0, 420, 600};
|
||||||
|
|
||||||
HWND m_rootView;
|
HWND m_rootView;
|
||||||
HWND m_collectionHeader;
|
HWND m_collectionHeader;
|
||||||
HWND m_collectionTree;
|
HWND m_collectionTree;
|
||||||
|
HWND m_collectionAdd;
|
||||||
|
HWND m_collectionRemove;
|
||||||
HWND m_groupListView;
|
HWND m_groupListView;
|
||||||
HWND m_pageListView;
|
HWND m_pageListView;
|
||||||
|
|
||||||
|
@ -43,6 +47,9 @@ public:
|
||||||
void close();
|
void close();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
void addAction();
|
||||||
|
void removeAction();
|
||||||
|
|
||||||
void selectCollection(int idx);
|
void selectCollection(int idx);
|
||||||
void selectGroup(int idx);
|
void selectGroup(int idx);
|
||||||
void selectPage(int idx);
|
void selectPage(int idx);
|
||||||
|
|
Loading…
Reference in New Issue