...
 
Commits (5)
......@@ -28,6 +28,9 @@ vlmc_SOURCES = \
src/Project/RecentProjects.cpp \
src/Renderer/AbstractRenderer.cpp \
src/Renderer/ConsoleRenderer.h \
src/Servers/AbstractLocalServer.cpp \
src/Servers/VLMCLocalBackend.cpp \
src/Servers/VLMCLocalFrontend.cpp \
src/Services/UploaderIODevice.cpp \
src/Settings/Settings.cpp \
src/Settings/SettingValue.cpp \
......@@ -57,6 +60,9 @@ vlmc_SOURCES += \
src/Renderer/ClipRenderer.h \
src/Renderer/AbstractRenderer.h \
src/Renderer/ConsoleRenderer.cpp \
src/Servers/AbstractLocalServer.h \
src/Servers/VLMCLocalBackend.h \
src/Servers/VLMCLocalFrontend.h \
src/Services/UploaderIODevice.h \
src/Services/AbstractSharingService.h \
src/EffectsEngine/EffectHelper.h \
......
......@@ -659,10 +659,42 @@ MainWindow::checkVideoLength()
}
return true;
}
#include <QProcess>
#include <QApplication>
#include "Servers/VLMCLocalFrontend.h"
bool
MainWindow::renderVideoSettings( bool shareOnInternet )
{
QStringList arguments;
arguments << "--server"
<< QString::number( qApp->applicationPid() );
auto myProcess = new QProcess( this );
connect( myProcess, &QProcess::started, this, [this,myProcess]()
{
auto s = new VLMCLocalFrontend( myProcess->processId() );
s->setParent( this );
s->connectTo( QString( "vlmc%1" ).arg( myProcess->processId() ) );
s->getResponse<QString>( QStringLiteral( "test" ), []( QString str ) { vlmcCritical() << str; } );
});
connect( myProcess, &QProcess::readyReadStandardError, this, [this, myProcess]()
{
myProcess->setReadChannel( QProcess::ProcessChannel::StandardError );
char buf[1024];
if ( myProcess->readLine( buf, sizeof( buf ) ) != -1 );
printf( "From %lld: %s", myProcess->processId(), buf );
fflush(stdout);
});
connect( myProcess, &QProcess::readyReadStandardOutput, this, [this, myProcess]()
{
myProcess->setReadChannel( QProcess::ProcessChannel::StandardOutput );
char buf[1024];
if ( myProcess->readLine( buf, sizeof( buf ) ) != -1 );
printf( "From %lld: %s", myProcess->processId(), buf );
fflush(stdout);
});
myProcess->start( qApp->applicationFilePath(), arguments );
RendererSettings settings( shareOnInternet );
if ( settings.exec() == QDialog::Rejected )
......
......@@ -32,6 +32,7 @@
#include "Tools/VlmcDebug.h"
#include "Workflow/Types.h"
#include "Servers/VLMCLocalBackend.h"
#include "Renderer/ConsoleRenderer.h"
#include "Project/Project.h"
#include "Backend/IBackend.h"
......@@ -237,9 +238,44 @@ VLMCCoremain( int argc, char **argv )
return res;
}
int VLMCServerMain( int argc, char **argv )
{
#ifdef HAVE_GUI
QApplication app( argc, argv );
#else
QCoreApplication app( argc, argv );
#endif
Backend::IBackend* backend;
VLMCmainCommon( app, &backend );
QStringList&& args = app.arguments();
const QString* id = nullptr;
// We don't check the first argument, possibly "./vlmc"
args.pop_front();
for ( const auto& arg : args )
{
// Make sure it's not an option
if ( id == nullptr && arg.at( 0 ) != '-' )
id = &arg;
}
if ( id == nullptr )
{
VLMCLocalBackend server( qApp->applicationPid() );
return app.exec();
}
VLMCLocalBackend server( id->toLongLong() );
return app.exec();
}
int
VLMCmain( int argc, char **argv, bool gui )
VLMCmain( int argc, char **argv, bool gui, bool server )
{
if ( server == true )
return VLMCServerMain( argc, argv );
#ifdef HAVE_GUI
if ( gui == true )
return VLMCGuimain( argc, argv );
......
......@@ -37,7 +37,7 @@
#include <unistd.h>
int VLMCmain( int , char**, bool );
int VLMCmain( int , char**, bool, bool );
#if defined(WITH_CRASHHANDLER) && defined(Q_OS_UNIX)
......@@ -105,6 +105,7 @@ main( int argc, char **argv )
#else
bool gui = false;
#endif
bool server = false;
/* Check for command arguments */
for ( int i = 1; i < argc; i++ )
......@@ -125,6 +126,8 @@ main( int argc, char **argv )
else if ( arg == "--no-gui" )
gui = false;
#endif
else if ( arg == "--server" )
server = true;
}
#ifdef WITH_CRASHHANDLER
......@@ -165,5 +168,5 @@ main( int argc, char **argv )
}
#endif
return VLMCmain( argc, argv, gui );
return VLMCmain( argc, argv, gui, server );
}
#include "AbstractLocalServer.h"
#include <QCoreApplication>
static const QString testConnection = "___testConnection";
AbstractLocalServer::AbstractLocalServer()
: AbstractLocalServer( 0 )
{
}
AbstractLocalServer::AbstractLocalServer( qint64 parentId, bool respondFirst )
: m_serverName( QStringLiteral( "vlmc%1" ).arg( qApp->applicationPid() ) )
, m_anotherServer( QStringLiteral( "vlmc%1" ).arg( parentId ) )
, m_willRespondFirst( respondFirst )
, m_server( new QLocalServer )
, m_socket( new QLocalSocket )
{
if ( m_willRespondFirst == true )
connect( m_server.get(), &QLocalServer::newConnection, this, &AbstractLocalServer::respondFirst );
if ( m_server->listen( m_serverName ) == false )
{
vlmcCritical() << "Unable to start the server:" << m_serverName;
return;
}
vlmcDebug() << "Launched with:" << m_serverName;
}
AbstractLocalServer::~AbstractLocalServer()
{
}
void
AbstractLocalServer::connectTo( const QString& anotherServer, std::function<void(bool)> callback )
{
m_socket->abort();
m_anotherServer = anotherServer;
getResponse<bool>( testConnection, callback );
}
void
AbstractLocalServer::respondFirst()
{
vlmcDebug() << "Responding first...";
m_server->disconnect( this );
QByteArray block;
serialize<bool>( block, true );
connect( m_socket.get(), &QLocalSocket::readyRead,
this, &AbstractLocalServer::handleRequest );
m_socketConnected.reset( m_server->nextPendingConnection() );
m_socketConnected->write( block );
m_socketConnected->flush();
m_socket->disconnectFromServer();
m_socket->connectToServer( m_anotherServer );
if ( m_socket->waitForConnected() )
{
vlmcDebug() << m_serverName << "connected to" << m_anotherServer;
}
else
vlmcCritical() << "Failed to connect to" << m_anotherServer;
}
void
AbstractLocalServer::handleRequest()
{
vlmcDebug() << m_serverName << "Handling request...";
m_socket->disconnect( this );
const auto& req = deserialize<QString>();
vlmcDebug() << "Got" << req;
// do something with the request here
QByteArray block;
if ( req == testConnection )
serialize<bool>( block, true );
else
processRequest( req, block );
m_socketConnected->write( block );
m_socketConnected->flush();
// This is technically only called by respondFirst so revert the connection unconditonally
connect( m_server.get(), &QLocalServer::newConnection, this, &AbstractLocalServer::respondFirst );
m_socket->disconnectFromServer();
}
#ifndef ABSTRACTLOCALSERVER_H
#define ABSTRACTLOCALSERVER_H
#include <memory>
#include <QObject>
#include <QDataStream>
#include <QLocalServer>
#include <QLocalSocket>
#include "Tools/VlmcDebug.h"
class AbstractLocalServer : public QObject
{
public:
AbstractLocalServer();
AbstractLocalServer( qint64 parentId, bool respondFirst = true );
virtual ~AbstractLocalServer();
void connectTo( const QString& anotherServer,
std::function<void(bool)> callback = nullptr );
/*
*
* @brief getResponse Call a fucntion in the server and get the its return value
* @param function The name of the function inteded to call
* @param callback The return value of the function
*
*
*/
template <typename Ret>
void getResponse( const QString& request,
std::function<void(Ret)> callback = nullptr )
{
m_socket->disconnect( this );
connect( m_socket.get(), &QLocalSocket::readyRead,
this, [this, request, callback](){ readFirst( request, callback ); } );
while ( m_socket->state() == QLocalSocket::UnconnectedState )
{
m_socket->connectToServer( m_anotherServer );
if ( m_socket->waitForConnected() )
{
vlmcDebug() << m_serverName << "connected to" << m_anotherServer;
break;
}
}
}
protected:
template <typename T>
void serialize( QByteArray& byteArray, const T& data )
{
vlmcDebug() << "Serializing...";
QDataStream out( &byteArray, QIODevice::WriteOnly );
out.setVersion( QDataStream::Qt_5_6 );
out << ( quint32 ) 0;
out << data;
out.device()->seek(0);
out << ( quint32 ) ( byteArray.size() - sizeof( quint32 ) );
}
private:
template <typename T>
T deserialize()
{
vlmcDebug() << "Deserializing...";
QDataStream stream( m_socket.get() );
stream.setVersion( QDataStream::Qt_5_6 );
quint32 blockSize = 0;
if ( m_socket->bytesAvailable() < (int) sizeof( quint32 ) )
{
vlmcCritical() << "Deserialization is failed!";
return T();
}
stream >> blockSize;
if ( m_socket->bytesAvailable() < blockSize || stream.atEnd() )
{
vlmcCritical() << "Deserialization is failed!";
return T();
}
T nextFortune;
stream >> nextFortune;
return nextFortune;
}
void respondFirst();
void handleRequest();
virtual void processRequest( const QString& request, QByteArray& ret ) {}
template <typename Ret>
void readFirst( const QString& request,
std::function<void(Ret)> callback )
{
vlmcDebug() << "Reading first...";
m_socket->disconnect( this );
bool ret = deserialize<bool>();
if ( ret == true )
{
vlmcDebug() << "Deserialization succeeded";
connect( m_socket.get(), &QLocalSocket::readyRead,
this, [this, callback]()
{
vlmcDebug() << "Got data!";
if ( callback )
callback( deserialize<Ret>() );
deleteLater();
m_socket->disconnectFromServer();
} );
QByteArray block;
serialize<QString>( block, request );
m_socketConnected.reset( m_server->nextPendingConnection() );
m_socketConnected->write( block );
m_socketConnected->flush();
}
else
vlmcCritical() << "Couldn't connect" << m_anotherServer << "properly";
}
QString m_serverName;
QString m_anotherServer;
bool m_willRespondFirst;
std::unique_ptr<QLocalServer> m_server;
std::unique_ptr<QLocalSocket> m_socket;
std::unique_ptr<QLocalSocket> m_socketConnected;
};
#endif // ABSTRACTLOCALSERVER_H
#include "VLMCLocalBackend.h"
VLMCLocalBackend::VLMCLocalBackend()
: AbstractLocalServer()
{
}
VLMCLocalBackend::VLMCLocalBackend( qint64 parentId )
: AbstractLocalServer( parentId )
{
}
void
VLMCLocalBackend::processRequest( const QString& request, QByteArray& ret )
{
if ( request == QStringLiteral( "test" ) )
serialize<QString>( ret, QStringLiteral( "Got Something" ) );
}
#ifndef VLMCLOCALBACKEND_H
#define VLMCLOCALBACKEND_H
#include <memory>
#include "AbstractLocalServer.h"
class VLMCLocalBackend : public AbstractLocalServer
{
public:
VLMCLocalBackend();
VLMCLocalBackend( qint64 parentId );
protected:
virtual void processRequest( const QString& request, QByteArray& ret );
};
#endif // VLMCLOCALBACKEND_H
#include "VLMCLocalFrontend.h"
VLMCLocalFrontend::VLMCLocalFrontend()
: AbstractLocalServer()
{
}
VLMCLocalFrontend::VLMCLocalFrontend( qint64 parentId )
: AbstractLocalServer( parentId, false )
{
}
#ifndef VLMCLOCALFRONTEND_H
#define VLMCLOCALFRONTEND_H
#include <memory>
#include "AbstractLocalServer.h"
class VLMCLocalFrontend : public AbstractLocalServer
{
public:
VLMCLocalFrontend();
VLMCLocalFrontend( qint64 parentId );
};
#endif // VLMCLOCALFRONTEND_H