1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4
5 #include "../../application.h"
6 #include "../../../include/iappdelegate.h"
7 #include "../../../include/iapplication.h"
8 #include "../../../../lib/vstkeycode.h"
9 #include "../../../../lib/platform/linux/x11frame.h"
10 #include "../../../../lib/platform/common/fileresourceinputstream.h"
11 #include "gdkcommondirectories.h"
12 #include "gdkpreference.h"
13 #include "gdkwindow.h"
14 #include "gdkrunloop.h"
15 #include <gtkmm.h>
16 #include <libgen.h>
17 #include <unordered_map>
18
19 //------------------------------------------------------------------------
20 namespace std {
21
22 //------------------------------------------------------------------------
23 template<>
24 struct hash<VstKeyCode>
25 {
operator ()std::hash26 std::size_t operator() (const VstKeyCode& k) const
27 {
28 return ((hash<int32_t> () (k.character) ^ (hash<unsigned char> () (k.modifier) << 1)) >>
29 1) ^
30 (hash<unsigned char> () (k.virt) << 1);
31 }
32 };
33
34 //------------------------------------------------------------------------
35 } // std
36
37 //------------------------------------------------------------------------
operator ==(const VstKeyCode & k1,const VstKeyCode & k2)38 bool operator== (const VstKeyCode& k1, const VstKeyCode& k2)
39 {
40 return k1.virt == k2.virt && k1.modifier == k2.modifier && k1.character == k2.character;
41 }
42
43 //------------------------------------------------------------------------
44 namespace VSTGUI {
45 void* soHandle = nullptr;
46
47 namespace Standalone {
48 namespace Platform {
49 namespace GDK {
50
51 using namespace VSTGUI::Standalone::Detail;
52
53 //------------------------------------------------------------------------
54 Glib::RefPtr<Gtk::Application> app;
55
56 //------------------------------------------------------------------------
gtkApp()57 Glib::RefPtr<Gtk::Application> gtkApp ()
58 {
59 return app;
60 }
61
62 //------------------------------------------------------------------------
63 class Application
64 {
65 public:
66 bool init (int argc, char* argv[]);
67 int run ();
68
69 void quit ();
70
71 private:
72 void doCommandUpdate ();
73 void handleCommand (const CommandWithKey& command);
74
75 CommonDirectories commonDirectories;
76 Preference prefs;
77
78 bool isInitialized{false};
79 };
80
81 //------------------------------------------------------------------------
init(int argc,char * argv[])82 bool Application::init (int argc, char* argv[])
83 {
84 const auto& appInfo = IApplication::instance ().getDelegate ().getInfo ();
85 app = Gtk::Application::create (argc, argv, appInfo.uri.data ());
86 Glib::set_application_name (appInfo.name.getString ());
87
88 IApplication::CommandLineArguments cmdArgs;
89 for (auto i = 0; i < argc; ++i)
90 cmdArgs.push_back (argv[i]);
91
92 app->signal_startup ().connect ([cmdArgs = std::move (cmdArgs), this]() mutable {
93 char result[PATH_MAX];
94 ssize_t count = readlink ("/proc/self/exe", result, PATH_MAX);
95 if (count == -1)
96 exit (-1);
97 std::string execPath = dirname (result);
98 VSTGUI::X11::Frame::createResourceInputStreamFunc =
99 [execPath](const CResourceDescription& desc) {
100 if (desc.type == CResourceDescription::kIntegerType)
101 return IPlatformResourceInputStream::Ptr ();
102 std::string path (execPath);
103 path += "/Resources/";
104 path += desc.u.name;
105 return FileResourceInputStream::create (path);
106 };
107
108 PlatformCallbacks callbacks;
109 callbacks.quit = [this]() { quit (); };
110 callbacks.onCommandUpdate = [this]() { doCommandUpdate (); };
111 callbacks.showAlert = [](const AlertBoxConfig& config) { return AlertResult::Error; };
112 callbacks.showAlertForWindow = [](const AlertBoxForWindowConfig& config) {
113 if (config.callback)
114 config.callback (AlertResult::Error);
115 };
116
117 auto appAccess = Detail::getApplicationPlatformAccess ();
118 vstgui_assert (appAccess);
119 IPlatformApplication::OpenFilesList openFilesList;
120 /* TODO: fill openFilesList */
121 appAccess->init ({prefs, commonDirectories, std::move (cmdArgs), std::move (callbacks),
122 std::move (openFilesList)});
123 isInitialized = true;
124 doCommandUpdate ();
125 });
126 return true;
127 }
128
129 //------------------------------------------------------------------------
run()130 int Application::run ()
131 {
132 return app->run ();
133 }
134
135 //------------------------------------------------------------------------
quit()136 void Application::quit ()
137 {
138 app->quit ();
139 }
140
141 //------------------------------------------------------------------------
handleCommand(const CommandWithKey & command)142 void Application::handleCommand (const CommandWithKey& command) {}
143
144 //------------------------------------------------------------------------
doCommandUpdate()145 void Application::doCommandUpdate ()
146 {
147 if (!isInitialized)
148 return;
149 auto mainMenu = Gio::Menu::create ();
150 auto commandList = Detail::getApplicationPlatformAccess ()->getCommandList ();
151 for (auto& e : commandList)
152 {
153 auto subMenu = Gio::Menu::create ();
154 for (auto& command : e.second)
155 {
156 if (command.name == CommandName::MenuSeparator)
157 {
158 continue;
159 }
160 auto actionName = command.group.getString () + "." + command.name.getString ();
161 std::replace (actionName.begin (), actionName.end (), ' ', '_');
162 auto item = Gio::MenuItem::create (command.name.getString (), actionName);
163 if (command.defaultKey)
164 {
165 std::string accelKey ("<Primary>");
166 accelKey += command.defaultKey;
167 // TODO: map virtual characters
168 item->set_attribute_value ("accel",
169 Glib::Variant<Glib::ustring>::create (accelKey));
170 }
171 subMenu->append_item (item);
172
173 if (!app->has_action (actionName))
174 {
175 if (auto action = app->add_action (actionName,
176 [this, command]() { handleCommand (command); }))
177 {
178 }
179 }
180 }
181 mainMenu->append_submenu (e.first.getString (), subMenu);
182 }
183 app->set_menubar (mainMenu);
184 }
185
186 //------------------------------------------------------------------------
187 } // GDK
188 } // Platform
189 } // Standalone
190 } // VSTGUI
191
192 //------------------------------------------------------------------------
main(int argc,char * argv[])193 int main (int argc, char* argv[])
194 {
195 VSTGUI::Standalone::Platform::GDK::Application app;
196 if (app.init (argc, argv))
197 return app.run ();
198 return -1;
199 }