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 @ 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
}