scide: avoid recursive calls to Main::instance
[supercollider.git] / editors / sc-ide / core / sc_process.hpp
blob48ef94eadded79bb361ec25af96046adeaafe0c3
1 /*
2 SuperCollider Qt IDE
3 Copyright (c) 2012 Jakob Leben & Tim Blechmann
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifndef SCIDE_SC_PROCESS_HPP_INCLUDED
22 #define SCIDE_SC_PROCESS_HPP_INCLUDED
24 #include "sc_introspection.hpp"
25 #include "settings/manager.hpp"
27 #include <QAction>
28 #include <QProcess>
29 #include <QtNetwork/QLocalSocket>
30 #include <QtNetwork/QLocalServer>
31 #include <QByteArray>
32 #include <QUuid>
33 #include <QThread>
34 #include <QDebug>
36 namespace ScIDE {
38 class Main;
39 class ScIntrospectionParser;
41 class SCProcess:
42 public QProcess
44 Q_OBJECT
46 public:
47 SCProcess( Main *, class ScResponder * responder, Settings::Manager * );
49 enum SCProcessActionRole {
50 StartSCLang = 0,
51 RecompileClassLibrary,
52 StopSCLang,
53 RestartSCLang,
54 RunMain,
55 StopMain,
57 SCProcessActionCount
60 const ScLanguage::Introspection & introspection() { return mIntrospection; }
62 void sendRequest( const QString &id, const QString &command, const QString &data )
64 QString cmd = QString("ScIDE.request(\"%1\",'%2',\"%3\")")
65 .arg(id)
66 .arg(command)
67 .arg(data);
69 evaluateCode(cmd, true);
72 void setActiveDocument(class Document *);
73 QAction *action(SCProcessActionRole role)
75 return mActions[role];
78 Q_SIGNALS:
79 void scPost(QString const &);
80 void statusMessage(const QString &);
81 void response(const QString & id, const QString & data);
83 public slots:
84 void recompileClassLibrary (void);
85 void runMain(void) { evaluateCode("thisProcess.run", false); }
86 void stopMain(void) { evaluateCode("thisProcess.stop", false); }
87 void startLanguage (void);
88 void stopLanguage (void);
89 void restartLanguage (void);
90 void onReadyRead(void);
91 void evaluateCode(QString const & commandString, bool silent = false);
93 void swapIntrospection (ScLanguage::Introspection *newIntrospection)
95 // LATER: use c++11/std::move
96 mIntrospection = *newIntrospection;
97 delete newIntrospection;
100 private slots:
101 void onNewIpcConnection()
103 mIpcSocket = mIpcServer->nextPendingConnection();
104 connect(mIpcSocket, SIGNAL(disconnected()), mIpcSocket, SLOT(deleteLater()));
105 connect(mIpcSocket, SIGNAL(readyRead()), this, SLOT(onIpcData()));
108 void onIpcData();
110 private:
111 void onSclangStart();
113 void prepareActions(Settings::Manager * settings);
115 QAction * mActions[SCProcessActionCount];
117 ScLanguage::Introspection mIntrospection;
118 ScIntrospectionParser *mIntrospectionParser;
120 QLocalServer *mIpcServer;
121 QLocalSocket *mIpcSocket;
122 QString mIpcServerName;
123 QByteArray mIpcData;
126 class ScRequest : public QObject
128 Q_OBJECT
129 public:
130 ScRequest( SCProcess *sc, QObject * parent = 0 ):
131 QObject(parent),
132 mSc(sc)
134 connect(mSc, SIGNAL(response(QString,QString)),
135 this, SLOT(onResponse(QString,QString)));
138 void send( const QString & command, const QString & data )
140 mId = QUuid::createUuid();
141 mCommand = command;
142 mSc->sendRequest(mId.toString(), command, data);
145 void cancel()
147 mId = QUuid();
150 signals:
151 void response( const QString & command, const QString & data );
153 private slots:
154 void onResponse( const QString & responseId, const QString & responseData )
156 if (responseId == mId.toString()) {
157 emit response(mCommand, responseData);
161 private:
162 QString mCommand;
163 QUuid mId;
164 SCProcess *mSc;
167 class ScResponder : public QObject
169 Q_OBJECT
171 public:
172 ScResponder( QObject * parent = 0):
173 QObject(parent)
176 Q_SIGNALS:
177 void serverRunningChanged( bool serverRunning, const QString & hostName, int port );
178 void newIntrospectionData( const QString & yaml );
180 private Q_SLOTS:
181 void onResponse( const QString & selector, const QString & data );
183 private:
184 void handleOpenFile( const QString & data ) const;
185 void handleServerRunningChanged( const QString & data );
188 class ScIntrospectionParserWorker : public QObject
190 Q_OBJECT
191 signals:
192 void done( ScLanguage::Introspection * output );
193 private slots:
194 void process( const QString & input )
196 try {
197 ScLanguage::Introspection *introspection = new ScLanguage::Introspection (input);
198 emit done(introspection);
199 } catch (std::exception & e) {
200 // LATER: show message in status bar
201 qDebug() << e.what();
204 void quit()
206 thread()->quit();
210 class ScIntrospectionParser : public QThread
212 Q_OBJECT
213 public:
214 ScIntrospectionParser( ScResponder * responder, QObject * parent = 0 ):
215 QThread(parent)
217 connect(responder, SIGNAL(newIntrospectionData(QString)),
218 &mWorker, SLOT(process(QString)), Qt::QueuedConnection);
219 connect(&mWorker, SIGNAL(done(ScLanguage::Introspection*)),
220 this, SIGNAL(done(ScLanguage::Introspection*)), Qt::QueuedConnection);
221 mWorker.moveToThread(this);
223 ~ScIntrospectionParser()
225 QMetaObject::invokeMethod(&mWorker, "quit");
226 wait();
229 signals:
230 void done( ScLanguage::Introspection * );
232 private:
233 ScIntrospectionParserWorker mWorker;
238 #endif