To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / main / main.cpp @ 112:7d82811c490a
History | View | Annotate | Download (8.51 KB)
| 1 |
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
|---|---|
| 2 |
|
| 3 |
/*
|
| 4 |
Vect
|
| 5 |
An experimental audio player for plural recordings of a work
|
| 6 |
Centre for Digital Music, Queen Mary, University of London.
|
| 7 |
This file copyright 2006-2012 Chris Cannam and QMUL.
|
| 8 |
|
| 9 |
This program is free software; you can redistribute it and/or
|
| 10 |
modify it under the terms of the GNU General Public License as
|
| 11 |
published by the Free Software Foundation; either version 2 of the
|
| 12 |
License, or (at your option) any later version. See the file
|
| 13 |
COPYING included with this distribution for more information.
|
| 14 |
*/
|
| 15 |
|
| 16 |
#include "MainWindow.h" |
| 17 |
|
| 18 |
#include "system/System.h" |
| 19 |
#include "system/Init.h" |
| 20 |
#include "base/TempDirectory.h" |
| 21 |
#include "base/PropertyContainer.h" |
| 22 |
#include "base/Preferences.h" |
| 23 |
#include "widgets/TipDialog.h" |
| 24 |
#include "svcore/plugin/PluginScan.h" |
| 25 |
|
| 26 |
#include <QMetaType> |
| 27 |
#include <QApplication> |
| 28 |
#include <QDesktopWidget> |
| 29 |
#include <QMessageBox> |
| 30 |
#include <QTranslator> |
| 31 |
#include <QLocale> |
| 32 |
#include <QSettings> |
| 33 |
#include <QIcon> |
| 34 |
#include <QSessionManager> |
| 35 |
#include <QDir> |
| 36 |
|
| 37 |
#include <iostream> |
| 38 |
#include <signal.h> |
| 39 |
|
| 40 |
static QMutex cleanupMutex;
|
| 41 |
static bool cleanedUp = false; |
| 42 |
|
| 43 |
static void |
| 44 |
signalHandler(int /* signal */) |
| 45 |
{
|
| 46 |
// Avoid this happening more than once across threads
|
| 47 |
|
| 48 |
std::cerr << "signalHandler: cleaning up and exiting" << std::endl;
|
| 49 |
cleanupMutex.lock(); |
| 50 |
if (!cleanedUp) {
|
| 51 |
TempDirectory::getInstance()->cleanup(); |
| 52 |
cleanedUp = true;
|
| 53 |
} |
| 54 |
cleanupMutex.unlock(); |
| 55 |
exit(0);
|
| 56 |
} |
| 57 |
|
| 58 |
class VectApplication : public QApplication |
| 59 |
{
|
| 60 |
public:
|
| 61 |
VectApplication(int &argc, char **argv) : |
| 62 |
QApplication(argc, argv), |
| 63 |
m_mainWindow(0) { }
|
| 64 |
virtual ~VectApplication() { }
|
| 65 |
|
| 66 |
void setMainWindow(MainWindow *mw) { m_mainWindow = mw; }
|
| 67 |
void releaseMainWindow() { m_mainWindow = 0; } |
| 68 |
|
| 69 |
virtual void commitData(QSessionManager &manager) { |
| 70 |
if (!m_mainWindow) return; |
| 71 |
bool mayAskUser = manager.allowsInteraction();
|
| 72 |
bool success = m_mainWindow->commitData(mayAskUser);
|
| 73 |
manager.release(); |
| 74 |
if (!success) manager.cancel();
|
| 75 |
} |
| 76 |
|
| 77 |
protected:
|
| 78 |
MainWindow *m_mainWindow; |
| 79 |
}; |
| 80 |
|
| 81 |
int
|
| 82 |
main(int argc, char **argv) |
| 83 |
{
|
| 84 |
svSystemSpecificInitialisation(); |
| 85 |
|
| 86 |
VectApplication application(argc, argv); |
| 87 |
|
| 88 |
QStringList args = application.arguments(); |
| 89 |
|
| 90 |
signal(SIGINT, signalHandler); |
| 91 |
signal(SIGTERM, signalHandler); |
| 92 |
|
| 93 |
#ifndef Q_OS_WIN32
|
| 94 |
signal(SIGHUP, signalHandler); |
| 95 |
signal(SIGQUIT, signalHandler); |
| 96 |
#endif
|
| 97 |
|
| 98 |
svSystemSpecificInitialisation(); |
| 99 |
|
| 100 |
bool audioOutput = true; |
| 101 |
|
| 102 |
if (args.contains("--help") || args.contains("-h") || args.contains("-?")) { |
| 103 |
std::cerr << QApplication::tr( |
| 104 |
"\nSonic Vector is a comparative viewer for sets of related audio recordings.\n\nUsage:\n\n %1 [--no-audio] [<file1>, <file2>...]\n\n --no-audio: Do not attempt to open an audio output device\n <file1>, <file2>...: Audio files; Sonic Vector is designed for comparative\nviewing of multiple recordings of the same music or other related material.\n").arg(argv[0]).toStdString() << std::endl; |
| 105 |
exit(2);
|
| 106 |
} |
| 107 |
|
| 108 |
if (args.contains("--no-audio")) audioOutput = false; |
| 109 |
|
| 110 |
QApplication::setOrganizationName("sonic-visualiser");
|
| 111 |
QApplication::setOrganizationDomain("sonicvisualiser.org");
|
| 112 |
QApplication::setApplicationName("Sonic Vector");
|
| 113 |
|
| 114 |
QIcon icon; |
| 115 |
int sizes[] = { 16, 22, 24, 32, 48, 64, 128 }; |
| 116 |
for (int i = 0; i < (int)(sizeof(sizes)/sizeof(sizes[0])); ++i) { |
| 117 |
icon.addFile(QString(":icons/sv-%1x%2.png").arg(sizes[i]).arg(sizes[i]));
|
| 118 |
} |
| 119 |
QApplication::setWindowIcon(icon); |
| 120 |
|
| 121 |
QString language = QLocale::system().name(); |
| 122 |
|
| 123 |
QTranslator qtTranslator; |
| 124 |
QString qtTrName = QString("qt_%1").arg(language);
|
| 125 |
std::cerr << "Loading " << qtTrName.toStdString() << "..." << std::endl; |
| 126 |
bool success = false; |
| 127 |
if (!(success = qtTranslator.load(QLocale(), qtTrName))) {
|
| 128 |
QString qtDir = getenv("QTDIR");
|
| 129 |
if (qtDir != "") { |
| 130 |
success = qtTranslator.load |
| 131 |
(QLocale(), qtTrName, QDir(qtDir).filePath("translations"));
|
| 132 |
} |
| 133 |
} |
| 134 |
if (!success) {
|
| 135 |
std::cerr << "Failed to load Qt translation for locale" << std::endl;
|
| 136 |
} |
| 137 |
application.installTranslator(&qtTranslator); |
| 138 |
|
| 139 |
QTranslator svisTranslator, svecTranslator; |
| 140 |
QString svisTrName = QString("sonic-visualiser_%1").arg(language);
|
| 141 |
QString svecTrName = QString("sonic-vector_%1").arg(language);
|
| 142 |
std::cerr << "Loading " << svisTrName.toStdString() << "..." << std::endl; |
| 143 |
svisTranslator.load(QLocale(), svisTrName, ":i18n");
|
| 144 |
std::cerr << "Loading " << svisTrName.toStdString() << "..." << std::endl; |
| 145 |
svecTranslator.load(QLocale(), svecTrName, ":i18n");
|
| 146 |
application.installTranslator(&svisTranslator); |
| 147 |
application.installTranslator(&svecTranslator); |
| 148 |
|
| 149 |
StoreStartupLocale(); |
| 150 |
|
| 151 |
// Make known-plugins query as early as possible
|
| 152 |
PluginScan::getInstance()->scan(); |
| 153 |
|
| 154 |
// Permit size_t and PropertyName to be used as args in queued signal calls
|
| 155 |
qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
|
| 156 |
|
| 157 |
MainWindow *gui = new MainWindow(audioOutput);
|
| 158 |
application.setMainWindow(gui); |
| 159 |
|
| 160 |
QDesktopWidget *desktop = QApplication::desktop(); |
| 161 |
QRect available = desktop->availableGeometry(); |
| 162 |
|
| 163 |
int width = available.width() * 2 / 3; |
| 164 |
int height = available.height() / 2; |
| 165 |
if (height < 450) height = available.height() * 2 / 3; |
| 166 |
if (width > height * 2) width = height * 2; |
| 167 |
|
| 168 |
QSettings settings; |
| 169 |
settings.beginGroup("MainWindow");
|
| 170 |
|
| 171 |
QSize size = settings.value("size", QSize(width, height)).toSize();
|
| 172 |
gui->resizeConstrained(size); |
| 173 |
|
| 174 |
if (settings.contains("position")) { |
| 175 |
QRect prevrect(settings.value("position").toPoint(), size);
|
| 176 |
if (!(available & prevrect).isEmpty()) {
|
| 177 |
gui->move(prevrect.topLeft()); |
| 178 |
} |
| 179 |
} |
| 180 |
|
| 181 |
if (settings.value("maximised", false).toBool()) { |
| 182 |
gui->setWindowState(Qt::WindowMaximized); |
| 183 |
} |
| 184 |
|
| 185 |
settings.endGroup(); |
| 186 |
|
| 187 |
gui->show(); |
| 188 |
|
| 189 |
bool haveSession = false; |
| 190 |
bool haveMainModel = false; |
| 191 |
bool havePriorCommandLineModel = false; |
| 192 |
|
| 193 |
for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
|
| 194 |
|
| 195 |
MainWindow::FileOpenStatus status = MainWindow::FileOpenFailed; |
| 196 |
|
| 197 |
if (i == args.begin()) continue; |
| 198 |
if (i->startsWith('-')) continue; |
| 199 |
|
| 200 |
if (i->startsWith("http:") || i->startsWith("ftp:")) { |
| 201 |
std::cerr << "opening URL: \"" << i->toStdString() << "\"..." << std::endl; |
| 202 |
status = gui->openPath(*i); |
| 203 |
continue;
|
| 204 |
} |
| 205 |
|
| 206 |
QString path = *i; |
| 207 |
|
| 208 |
if (QFileInfo(path).isDir()) {
|
| 209 |
status = gui->openDirOfAudio(path); |
| 210 |
} |
| 211 |
|
| 212 |
if (status != MainWindow::FileOpenSucceeded) {
|
| 213 |
if (path.endsWith("sv")) { |
| 214 |
if (!haveSession) {
|
| 215 |
status = gui->openSessionPath(path); |
| 216 |
if (status == MainWindow::FileOpenSucceeded) {
|
| 217 |
haveSession = true;
|
| 218 |
haveMainModel = true;
|
| 219 |
} |
| 220 |
} else {
|
| 221 |
std::cerr << "WARNING: Ignoring additional session file argument \"" << path.toStdString() << "\"" << std::endl; |
| 222 |
status = MainWindow::FileOpenSucceeded; |
| 223 |
} |
| 224 |
} |
| 225 |
} |
| 226 |
|
| 227 |
if (status != MainWindow::FileOpenSucceeded) {
|
| 228 |
if (!haveMainModel) {
|
| 229 |
status = gui->openPath(path, MainWindow::ReplaceSession); |
| 230 |
if (status == MainWindow::FileOpenSucceeded) {
|
| 231 |
haveMainModel = true;
|
| 232 |
} |
| 233 |
} else {
|
| 234 |
gui->selectMainPane(); |
| 235 |
if (haveSession && !havePriorCommandLineModel) {
|
| 236 |
status = gui->openPath(path, MainWindow::AskUser); |
| 237 |
if (status == MainWindow::FileOpenSucceeded) {
|
| 238 |
havePriorCommandLineModel = true;
|
| 239 |
} |
| 240 |
} else {
|
| 241 |
status = gui->openPath(path, MainWindow::CreateAdditionalModel); |
| 242 |
} |
| 243 |
} |
| 244 |
} |
| 245 |
|
| 246 |
if (status == MainWindow::FileOpenFailed) {
|
| 247 |
QMessageBox::critical |
| 248 |
(gui, QMessageBox::tr("Failed to open file"),
|
| 249 |
QMessageBox::tr("File \"%1\" could not be opened").arg(path));
|
| 250 |
} |
| 251 |
} |
| 252 |
|
| 253 |
int rv = application.exec();
|
| 254 |
// std::cerr << "application.exec() returned " << rv << std::endl;
|
| 255 |
|
| 256 |
cleanupMutex.lock(); |
| 257 |
TempDirectory::getInstance()->cleanup(); |
| 258 |
application.releaseMainWindow(); |
| 259 |
|
| 260 |
delete gui;
|
| 261 |
|
| 262 |
cleanupMutex.unlock(); |
| 263 |
|
| 264 |
return rv;
|
| 265 |
} |