Mema
Memory Matrix — multi-channel audio matrix monitor and router
Loading...
Searching...
No Matches
Main.cpp
Go to the documentation of this file.
1/* Copyright (c) 2024-2025, Christian Ahrens
2 *
3 * This file is part of Mema <https://github.com/ChristianAhrens/Mema>
4 *
5 * This library is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU Lesser General Public License version 3.0 as published
7 * by the Free Software Foundation.
8 *
9 * This library is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12 * details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this library; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19#include <JuceHeader.h>
20
21#include "MainComponent.h"
22
23#include <CustomLookAndFeel.h>
24
25 //==============================================================================
26class MainApplication : public juce::JUCEApplication
27{
28public:
29 //==============================================================================
31
32 const String getApplicationName() override { return ProjectInfo::projectName; }
33 const String getApplicationVersion() override { return ProjectInfo::versionString; }
34 bool moreThanOneInstanceAllowed() override { return true; }
35
36 //==============================================================================
37 void initialise(const String& commandLine) override
38 {
39 m_mainWindow.reset(std::make_unique<MainWindow>(getApplicationName(), commandLine).release());
40
41#if JUCE_MAC
42 // Ignore SIGPIPE globally, to prevent occasional unexpected app
43 // termination when Mema.Mo instances disconnect while sending by
44 // writing to socket is ongoing
45 signal(SIGPIPE, SIG_IGN);
46#endif
47
48 // a single instance of tooltip window is required and used by JUCE everywhere a tooltip is required.
49 m_toolTipWindowInstance = std::make_unique<TooltipWindow>();
50 }
51
52 void shutdown() override
53 {
54 m_mainWindow.reset();
55 }
56
57 //==============================================================================
58 void systemRequestedQuit() override
59 {
60 // This is called when the app is being asked to quit: you can ignore this
61 // request and let the app carry on running, or call quit() to allow the app to close.
62 quit();
63 }
64
65 void anotherInstanceStarted(const juce::String& commandLine) override
66 {
67 ignoreUnused(commandLine);
68 }
69
70 //==============================================================================
71 /*
72 This class implements the desktop window that contains an instance of
73 our MainComponent class.
74 */
75 class MainWindow : public juce::DocumentWindow, juce::DarkModeSettingListener
76 {
77 public:
78 MainWindow(const juce::String& name, const juce::String& commandLine) : juce::DocumentWindow(name,
79 juce::Desktop::getInstance().getDefaultLookAndFeel()
80 .findColour(juce::ResizableWindow::backgroundColourId),
81 juce::DocumentWindow::allButtons)
82 {
83 ignoreUnused(commandLine);
84
85 setUsingNativeTitleBar(true);
86 auto mainComponent = std::make_unique<MainComponent>();
87 mainComponent->onPaletteStyleChange = [=](int paletteStyle, bool followLocalStyle) {
88 m_followLocalStyle = followLocalStyle;
89 applyPaletteStyle(static_cast<JUCEAppBasics::CustomLookAndFeel::PaletteStyle>(paletteStyle));
90 };
91 mainComponent->onSetFullscreenWindow = [=](bool fullscreenWindow) { setFullscreenWindow(fullscreenWindow); };
92 setContentOwned(mainComponent.release(), true);
93
94#if JUCE_IOS || JUCE_ANDROID
95 setFullScreen(true);
96 juce::Desktop::getInstance().setScreenSaverEnabled(false);
97#elif JUCE_LINUX
98 juce::Desktop::getInstance().setKioskModeComponent(getTopLevelComponent(), false);
99#else
100 setResizable(true, true);
101 centreWithSize(getWidth(), getHeight());
102#endif
103
104 setVisible(true);
105
106 juce::Desktop::getInstance().addDarkModeSettingListener(this);
107 darkModeSettingChanged(); // initially trigger correct colourscheme
108
109 // use the settings menu item call infrastructure to activate dark mode per default
110 if (auto mc = dynamic_cast<MainComponent*>(getContentComponent()))
111 mc->applySettingsOption(MainComponent::MemaMoSettingsOption::LookAndFeel_Dark);
112
113 JUCEAppBasics::AppConfigurationBase::getInstance()->triggerWatcherUpdate();
114 }
115
116 void closeButtonPressed() override
117 {
118 juce::JUCEApplication::getInstance()->systemRequestedQuit();
119 }
120
122 {
123 if (!m_followLocalStyle)
124 return;
125
126 if (juce::Desktop::getInstance().isDarkModeActive())
127 {
128 // go dark
129 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PS_Dark);
130 }
131 else
132 {
133 // go light
134 applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PS_Light);
135 }
136
137 lookAndFeelChanged();
138 }
139
140 void applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PaletteStyle paletteStyle)
141 {
142 m_lookAndFeel = std::make_unique<JUCEAppBasics::CustomLookAndFeel>(paletteStyle);
143 juce::Desktop::getInstance().setDefaultLookAndFeel(m_lookAndFeel.get());
144 }
145
146 void setFullscreenWindow(bool fullscreenWindow)
147 {
148#if JUCE_WINDOWS
149 if (fullscreenWindow)
150 juce::Desktop::getInstance().setKioskModeComponent(getTopLevelComponent(), false);
151 else
152 juce::Desktop::getInstance().setKioskModeComponent(nullptr, false);
153#elif JUCE_MAC
154 if (auto* topLevel = getTopLevelComponent())
155 {
156 if (auto* peer = topLevel->getPeer())
157 {
158 peer->setFullScreen(fullscreenWindow);
159 return;
160 }
161 }
162 jassertfalse;
163#endif
164 }
165
166 private:
167 std::unique_ptr<juce::LookAndFeel> m_lookAndFeel;
168 bool m_followLocalStyle = true;
169
170 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainWindow)
171 };
172
173private:
174 std::unique_ptr<MainWindow> m_mainWindow;
175 std::unique_ptr<juce::TooltipWindow> m_toolTipWindowInstance;
176};
177
178//==============================================================================
179// This macro generates the main() routine that launches the app.
180START_JUCE_APPLICATION(MainApplication)
void closeButtonPressed() override
Definition Main.cpp:116
void setFullscreenWindow(bool fullscreenWindow)
Definition Main.cpp:146
void applyPaletteStyle(JUCEAppBasics::CustomLookAndFeel::PaletteStyle paletteStyle)
Definition Main.cpp:140
MainWindow(const juce::String &name, const juce::String &commandLine)
Definition Main.cpp:78
void darkModeSettingChanged() override
Definition Main.cpp:121
const String getApplicationVersion() override
Definition Main.cpp:33
void initialise(const String &commandLine) override
Definition Main.cpp:37
void shutdown() override
Definition Main.cpp:52
bool moreThanOneInstanceAllowed() override
Definition Main.cpp:34
void systemRequestedQuit() override
Definition Main.cpp:58
void anotherInstanceStarted(const juce::String &commandLine) override
Definition Main.cpp:65
const String getApplicationName() override
Definition Main.cpp:32
Top-level application component for Mema.Mo (MenubarMatrixMonitor).