To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / main / main.cpp @ 312:6394462e0c12

History | View | Annotate | Download (9.21 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 <QScreen>
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
#include "../version.h"
41

    
42
#include <vamp-hostsdk/PluginHostAdapter.h>
43

    
44
static QMutex cleanupMutex;
45
static bool cleanedUp = false;
46

    
47
static void
48
signalHandler(int /* signal */)
49
{
50
    // Avoid this happening more than once across threads
51

    
52
    std::cerr << "signalHandler: cleaning up and exiting" << std::endl;
53
    cleanupMutex.lock();
54
    if (!cleanedUp) {
55
        TempDirectory::getInstance()->cleanup();
56
        cleanedUp = true;
57
    }
58
    cleanupMutex.unlock();
59
    exit(0);
60
}
61

    
62
class VectApplication : public QApplication
63
{
64
public:
65
    VectApplication(int &argc, char **argv) :
66
        QApplication(argc, argv),
67
        m_mainWindow(0) { }
68
    virtual ~VectApplication() { }
69

    
70
    void setMainWindow(MainWindow *mw) { m_mainWindow = mw; }
71
    void releaseMainWindow() { m_mainWindow = 0; }
72

    
73
    virtual void commitData(QSessionManager &manager) {
74
        if (!m_mainWindow) return;
75
        bool mayAskUser = manager.allowsInteraction();
76
        bool success = m_mainWindow->commitData(mayAskUser);
77
        manager.release();
78
        if (!success) manager.cancel();
79
    }
80

    
81
protected:
82
    MainWindow *m_mainWindow;
83
};
84

    
85
static QString
86
getEnvQStr(QString variable)
87
{
88
#ifdef Q_OS_WIN32
89
    std::wstring wvar = variable.toStdWString();
90
    wchar_t *value = _wgetenv(wvar.c_str());
91
    if (!value) return QString();
92
    else return QString::fromStdWString(std::wstring(value));
93
#else
94
    std::string var = variable.toStdString();
95
    return QString::fromUtf8(qgetenv(var.c_str()));
96
#endif
97
}
98

    
99
static void
100
putEnvQStr(QString assignment)
101
{
102
#ifdef Q_OS_WIN32
103
    std::wstring wassignment = assignment.toStdWString();
104
    _wputenv(_wcsdup(wassignment.c_str()));
105
#else
106
    putenv(strdup(assignment.toUtf8().data()));
107
#endif
108
}
109

    
110
static void
111
setupMyVampPath()
112
{
113
    // This based on similar logic from the Tony application
114
    
115
    QString myVampPath = getEnvQStr("SONIC_LINEUP_VAMP_PATH");
116

    
117
#ifdef Q_OS_WIN32
118
    QChar sep(';');
119
#else
120
    QChar sep(':');
121
#endif
122
    
123
    if (myVampPath == "") {
124

    
125
        QString appName = QApplication::applicationName();
126
        QString myDir = QApplication::applicationDirPath();
127
        QString binaryName = QFileInfo(QCoreApplication::arguments().at(0))
128
            .fileName();
129

    
130
#ifdef Q_OS_WIN32
131
        QString programFiles = getEnvQStr("ProgramFiles");
132
        if (programFiles == "") programFiles = "C:\\Program Files";
133
        QString pfPath(programFiles + "\\" + appName);
134
        myVampPath = myDir + sep + pfPath;
135
#else
136
#ifdef Q_OS_MAC
137
        myVampPath = myDir + "/../Resources";
138
#else
139
        if (binaryName != "") {
140
            myVampPath =
141
                myDir + "/../lib/" + binaryName + sep;
142
        }
143
        myVampPath = myVampPath +
144
            myDir + "/../lib/" + appName + sep +
145
            myDir;
146
#endif
147
#endif
148
    }
149

    
150
    SVCERR << "Setting VAMP_PATH to " << myVampPath
151
           << " for Sonic Lineup plugins" << endl;
152

    
153
    QString env = "VAMP_PATH=" + myVampPath;
154

    
155
    // Windows lacks setenv, must use putenv (different arg convention)
156
    putEnvQStr(env);
157
}
158

    
159
int
160
main(int argc, char **argv)
161
{
162
    if (argc == 2 && (QString(argv[1]) == "--version" ||
163
                      QString(argv[1]) == "-v")) {
164
        cerr << VECT_VERSION << endl;
165
        exit(0);
166
    }
167

    
168
    svSystemSpecificInitialisation();
169

    
170
    VectApplication application(argc, argv);
171

    
172
    QApplication::setOrganizationName("sonic-visualiser");
173
    QApplication::setOrganizationDomain("sonicvisualiser.org");
174
    QApplication::setApplicationName("Sonic Lineup");
175

    
176
    setupMyVampPath();
177

    
178
    QStringList args = application.arguments();
179

    
180
    signal(SIGINT,  signalHandler);
181
    signal(SIGTERM, signalHandler);
182

    
183
#ifndef Q_OS_WIN32
184
    signal(SIGHUP,  signalHandler);
185
    signal(SIGQUIT, signalHandler);
186
#endif
187

    
188
    svSystemSpecificInitialisation();
189

    
190
    bool audioOutput = true;
191

    
192
    if (args.contains("--help") || args.contains("-h") || args.contains("-?")) {
193
        std::cerr << QApplication::tr(
194
            "\nSonic Lineup 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 Lineup is designed for comparative\nviewing of multiple recordings of the same music or other related material.\n").arg(argv[0]).toStdString() << std::endl;
195
        exit(2);
196
    }
197

    
198
    if (args.contains("--no-audio")) {
199
        audioOutput = false;
200
    }
201

    
202
    if (args.contains("--first-run")) {
203
        QSettings settings;
204
        settings.clear();
205
    }
206

    
207
    InteractiveFileFinder::getInstance()->setApplicationSessionExtension("vect");
208

    
209
    QSettings settings;
210
    settings.beginGroup("Preferences");
211
    // Running plugins in-process allows us to use the serialise
212
    // option in the MATCH plugin, which cuts down on memory pressure
213
    // and makes things go more smoothly
214
    settings.setValue("run-vamp-plugins-in-process", true);
215
    settings.endGroup();
216

    
217
    QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
218
    QApplication::setAttribute(Qt::AA_DontShowIconsInMenus);
219

    
220
    QIcon icon;
221
    int sizes[] = { 16, 22, 24, 32, 48, 64, 128 };
222
    for (int i = 0; i < (int)(sizeof(sizes)/sizeof(sizes[0])); ++i) {
223
        icon.addFile(QString(":icons/sv-%1x%2.png").arg(sizes[i]).arg(sizes[i]));
224
    }
225
    QApplication::setWindowIcon(icon);
226

    
227
    QString language = QLocale::system().name();
228

    
229
    QTranslator qtTranslator;
230
    QString qtTrName = QString("qt_%1").arg(language);
231
    SVCERR << "Loading " << qtTrName.toStdString() << "..." << endl;
232
    bool success = false;
233
    if (!(success = qtTranslator.load(QLocale(), qtTrName))) {
234
        QString qtDir = getenv("QTDIR");
235
        if (qtDir != "") {
236
            success = qtTranslator.load
237
                (QLocale(), qtTrName, QDir(qtDir).filePath("translations"));
238
        }
239
    }
240
    if (!success) {
241
        SVCERR << "Failed to load Qt translation for locale" << endl;
242
    }
243
    application.installTranslator(&qtTranslator);
244

    
245
    QTranslator svecTranslator;
246
    QString svecTrName = QString("vect_%1").arg(language);
247
    SVCERR << "Loading " << svecTrName << "..." << endl;
248
    if (svecTranslator.load(svecTrName, ":i18n")) {
249
        application.installTranslator(&svecTranslator);
250
    } else {
251
        SVCERR << "Failed to load translation" << endl;
252
    }
253

    
254
    StoreStartupLocale();
255

    
256
    // Make known-plugins query as early as possible
257
    PluginScan::getInstance()->scan();
258
    
259
    // Permit size_t and PropertyName to be used as args in queued signal calls
260
    qRegisterMetaType<PropertyContainer::PropertyName>("PropertyContainer::PropertyName");
261

    
262
    MainWindow::SoundOptions options =
263
        MainWindow::WithAudioInput | MainWindow::WithAudioOutput;
264
    if (!audioOutput) options = 0;
265

    
266
    MainWindow *gui = new MainWindow(options);
267
    application.setMainWindow(gui);
268

    
269
    QScreen *screen = QApplication::primaryScreen();
270
    QRect available = screen->availableGeometry();
271

    
272
    int width = available.width() * 2 / 3;
273
    int height = available.height() / 2;
274
    if (height < 450) height = available.height() * 2 / 3;
275
    if (width > height * 2) width = height * 2;
276

    
277
    settings.beginGroup("MainWindow");
278

    
279
    QSize size = settings.value("size", QSize(width, height)).toSize();
280
    gui->resizeConstrained(size);
281

    
282
    if (settings.contains("position")) {
283
        QRect prevrect(settings.value("position").toPoint(), size);
284
        if (!(available & prevrect).isEmpty()) {
285
            gui->move(prevrect.topLeft());
286
        }
287
    }
288

    
289
    if (settings.value("maximised", false).toBool()) {
290
        gui->setWindowState(Qt::WindowMaximized);
291
    }
292

    
293
    settings.endGroup();
294
    
295
    gui->show();
296

    
297
    SmallSession session;
298
    bool haveSession = false;
299
    
300
    for (QStringList::iterator i = args.begin(); i != args.end(); ++i) {
301

    
302
        if (i == args.begin()) continue;
303
        if (i->startsWith('-')) continue;
304

    
305
        if (session.mainFile == "") {
306
            session.mainFile = *i;
307
        } else {
308
            session.additionalFiles.push_back(*i);
309
        }
310

    
311
        haveSession = true;
312
    }
313

    
314
    if (haveSession) {
315
        gui->openSmallSession(session);
316
    }
317

    
318
    int rv = application.exec();
319

    
320
    cleanupMutex.lock();
321
    TempDirectory::getInstance()->cleanup();
322
    application.releaseMainWindow();
323

    
324
    delete gui;
325

    
326
    cleanupMutex.unlock();
327

    
328
    return rv;
329
}