mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-29 15:22:11 +02:00
Remove unfinished web application
It used Broadway as an easy "reuse the same code into web application" way for me, but Broadway is not very good for this. This feature should be made using some better dedicated framework for building websites (so it can work better and support different screen sizes). All the WebSocket functionality needed for this will remain (and be documented at a later point when expanded and stable), so if anyone would like to make such remote controlling app, will be free to do so (outside of Clapper code).
This commit is contained in:
@@ -6,4 +6,4 @@ imports.package.init({
|
||||
prefix: '@prefix@',
|
||||
libdir: '@libdir@',
|
||||
});
|
||||
imports.package.run(imports.src.main@ID_POSTFIX@);
|
||||
imports.package.run(imports.src.main);
|
||||
|
@@ -1,25 +1,19 @@
|
||||
clapper_apps = ['', 'Remote', 'Daemon']
|
||||
bin_conf = configuration_data()
|
||||
|
||||
foreach id_postfix : clapper_apps
|
||||
app_postfix = (id_postfix != '') ? '.' + id_postfix : ''
|
||||
bin_conf.set('GJS', find_program('gjs').path())
|
||||
bin_conf.set('PACKAGE_NAME', meson.project_name())
|
||||
bin_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||
bin_conf.set('prefix', get_option('prefix'))
|
||||
bin_conf.set('libdir', libdir)
|
||||
|
||||
bin_conf = configuration_data()
|
||||
bin_conf.set('GJS', find_program('gjs').path())
|
||||
bin_conf.set('PACKAGE_NAME', meson.project_name())
|
||||
bin_conf.set('PACKAGE_VERSION', meson.project_version())
|
||||
bin_conf.set('ID_POSTFIX', id_postfix)
|
||||
bin_conf.set('prefix', get_option('prefix'))
|
||||
bin_conf.set('libdir', libdir)
|
||||
|
||||
configure_file(
|
||||
input: 'com.github.rafostar.Clapper.in',
|
||||
output: 'com.github.rafostar.Clapper' + app_postfix,
|
||||
configuration: bin_conf,
|
||||
install: true,
|
||||
install_dir: bindir,
|
||||
install_mode: 'rwxr-xr-x'
|
||||
)
|
||||
endforeach
|
||||
configure_file(
|
||||
input: 'com.github.rafostar.Clapper.in',
|
||||
output: 'com.github.rafostar.Clapper',
|
||||
configuration: bin_conf,
|
||||
install: true,
|
||||
install_dir: bindir,
|
||||
install_mode: 'rwxr-xr-x'
|
||||
)
|
||||
|
||||
clapper_symlink_cmd = 'ln -fs @0@ $DESTDIR@1@'.format(
|
||||
'com.github.rafostar.Clapper',
|
||||
|
@@ -1,25 +0,0 @@
|
||||
const { GObject } = imports.gi;
|
||||
const { AppBase } = imports.src.appBase;
|
||||
const { HeaderBarRemote } = imports.src.headerbarRemote;
|
||||
const { WidgetRemote } = imports.src.widgetRemote;
|
||||
|
||||
var AppRemote = GObject.registerClass({
|
||||
GTypeName: 'ClapperAppRemote',
|
||||
},
|
||||
class ClapperAppRemote extends AppBase
|
||||
{
|
||||
vfunc_startup()
|
||||
{
|
||||
super.vfunc_startup();
|
||||
|
||||
const window = this.active_window;
|
||||
|
||||
const clapperWidget = new WidgetRemote();
|
||||
window.set_child(clapperWidget);
|
||||
|
||||
const headerBar = new HeaderBarRemote();
|
||||
window.set_titlebar(headerBar);
|
||||
|
||||
window.maximize();
|
||||
}
|
||||
});
|
@@ -1,70 +0,0 @@
|
||||
const { Gio, GLib, GObject } = imports.gi;
|
||||
const Debug = imports.src.debug;
|
||||
|
||||
const { debug } = Debug;
|
||||
|
||||
var Daemon = GObject.registerClass({
|
||||
GTypeName: 'ClapperDaemon',
|
||||
},
|
||||
class ClapperDaemon extends Gio.SubprocessLauncher
|
||||
{
|
||||
_init()
|
||||
{
|
||||
const port = ARGV[0] || 8080;
|
||||
|
||||
/* FIXME: show output when debugging is on */
|
||||
const flags = Gio.SubprocessFlags.STDOUT_SILENCE
|
||||
| Gio.SubprocessFlags.STDERR_SILENCE;
|
||||
|
||||
super._init({ flags });
|
||||
|
||||
this.errMsg = 'exited with error or was forced to close';
|
||||
this.loop = GLib.MainLoop.new(null, false);
|
||||
|
||||
this.broadwayd = this.spawnv(['gtk4-broadwayd', '--port=' + port]);
|
||||
this.broadwayd.wait_async(null, this._onBroadwaydClosed.bind(this));
|
||||
|
||||
this.setenv('GDK_BACKEND', 'broadway', true);
|
||||
|
||||
const remoteApp = this.spawnv(['com.github.rafostar.Clapper.Remote']);
|
||||
remoteApp.wait_async(null, this._onRemoteClosed.bind(this));
|
||||
|
||||
this.loop.run();
|
||||
}
|
||||
|
||||
_checkProcResult(proc, result)
|
||||
{
|
||||
let hadError = false;
|
||||
|
||||
try {
|
||||
hadError = proc.wait_finish(result);
|
||||
}
|
||||
catch(err) {
|
||||
debug(err);
|
||||
}
|
||||
|
||||
return hadError;
|
||||
}
|
||||
|
||||
_onBroadwaydClosed(proc, result)
|
||||
{
|
||||
const hadError = this._checkProcResult(proc, result);
|
||||
|
||||
if(hadError)
|
||||
debug(`broadwayd ${this.errMsg}`);
|
||||
|
||||
this.broadwayd = null;
|
||||
this.loop.quit();
|
||||
}
|
||||
|
||||
_onRemoteClosed(proc, result)
|
||||
{
|
||||
const hadError = this._checkProcResult(proc, result);
|
||||
|
||||
if(hadError)
|
||||
debug(`remote app ${this.errMsg}`);
|
||||
|
||||
if(this.broadwayd)
|
||||
this.broadwayd.force_exit();
|
||||
}
|
||||
});
|
@@ -1,22 +0,0 @@
|
||||
const { GObject } = imports.gi;
|
||||
const { HeaderBarBase } = imports.src.headerbarBase;
|
||||
|
||||
var HeaderBarRemote = GObject.registerClass({
|
||||
GTypeName: 'ClapperHeaderBarRemote',
|
||||
},
|
||||
class ClapperHeaderBarRemote extends HeaderBarBase
|
||||
{
|
||||
_init()
|
||||
{
|
||||
super._init();
|
||||
this.extraButtonsBox.visible = false;
|
||||
}
|
||||
|
||||
_onWindowButtonActivate(action)
|
||||
{
|
||||
if(action === 'toggle-maximized')
|
||||
action = 'toggle_maximized';
|
||||
|
||||
this.root.child.sendWs(action);
|
||||
}
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
const { Daemon } = imports.src.daemon;
|
||||
|
||||
function main()
|
||||
{
|
||||
new Daemon();
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
imports.gi.versions.Gdk = '4.0';
|
||||
imports.gi.versions.Gtk = '4.0';
|
||||
imports.gi.versions.Soup = '2.4';
|
||||
|
||||
pkg.initGettext();
|
||||
|
||||
const Misc = imports.src.misc;
|
||||
Misc.appId += '.Remote';
|
||||
|
||||
const { Gtk, Adw } = imports.gi;
|
||||
const { AppRemote } = imports.src.appRemote;
|
||||
|
||||
function main(argv)
|
||||
{
|
||||
Gtk.init();
|
||||
Adw.init();
|
||||
|
||||
new AppRemote().run(argv);
|
||||
}
|
@@ -3,7 +3,6 @@ const ByteArray = imports.byteArray;
|
||||
const Debug = imports.src.debug;
|
||||
const Misc = imports.src.misc;
|
||||
const { PlaylistWidget } = imports.src.playlist;
|
||||
const { WebApp } = imports.src.webApp;
|
||||
|
||||
const { debug, warn } = Debug;
|
||||
const { settings } = Misc;
|
||||
@@ -43,7 +42,6 @@ class ClapperPlayer extends GstClapper.Clapper
|
||||
this.visualization_enabled = false;
|
||||
|
||||
this.webserver = null;
|
||||
this.webapp = null;
|
||||
this.playlistWidget = new PlaylistWidget();
|
||||
|
||||
this.seekDone = true;
|
||||
@@ -675,7 +673,6 @@ class ClapperPlayer extends GstClapper.Clapper
|
||||
debug(`changed play flags: ${initialFlags} -> ${settingsFlags}`);
|
||||
break;
|
||||
case 'webserver-enabled':
|
||||
case 'webapp-enabled':
|
||||
const webserverEnabled = settings.get_boolean('webserver-enabled');
|
||||
|
||||
if(webserverEnabled) {
|
||||
@@ -690,22 +687,8 @@ class ClapperPlayer extends GstClapper.Clapper
|
||||
this.webserver.passMsgData = this.receiveWs.bind(this);
|
||||
}
|
||||
this.webserver.startListening();
|
||||
|
||||
const webappEnabled = settings.get_boolean('webapp-enabled');
|
||||
|
||||
if(!this.webapp && !webappEnabled)
|
||||
break;
|
||||
|
||||
if(webappEnabled) {
|
||||
if(!this.webapp)
|
||||
this.webapp = new WebApp();
|
||||
|
||||
this.webapp.startDaemonApp(settings.get_int('webapp-port'));
|
||||
}
|
||||
}
|
||||
else if(this.webserver) {
|
||||
/* remote app will close when connection is lost
|
||||
* which will cause the daemon to close too */
|
||||
this.webserver.stopListening();
|
||||
}
|
||||
break;
|
||||
|
@@ -1,51 +0,0 @@
|
||||
const { GObject } = imports.gi;
|
||||
const { WebClient } = imports.src.webClient;
|
||||
|
||||
var ClapperState = {
|
||||
STOPPED: 0,
|
||||
BUFFERING: 1,
|
||||
PAUSED: 2,
|
||||
PLAYING: 3,
|
||||
};
|
||||
|
||||
var PlayerRemote = GObject.registerClass({
|
||||
GTypeName: 'ClapperPlayerRemote',
|
||||
},
|
||||
class ClapperPlayerRemote extends GObject.Object
|
||||
{
|
||||
_init()
|
||||
{
|
||||
super._init();
|
||||
|
||||
this.webclient = new WebClient();
|
||||
}
|
||||
|
||||
set_playlist(playlist)
|
||||
{
|
||||
const uris = [];
|
||||
|
||||
/* We can not send GioFiles via WebSocket */
|
||||
for(let source of playlist)
|
||||
uris.push(this._getSourceUri(source));
|
||||
|
||||
this.webclient.sendMessage({
|
||||
action: 'set_playlist',
|
||||
value: uris
|
||||
});
|
||||
}
|
||||
|
||||
set_subtitles(source)
|
||||
{
|
||||
this.webclient.sendMessage({
|
||||
action: 'set_subtitles',
|
||||
value: this._getSourceUri(source)
|
||||
});
|
||||
}
|
||||
|
||||
_getSourceUri(source)
|
||||
{
|
||||
return (source.get_uri != null)
|
||||
? source.get_uri()
|
||||
: source;
|
||||
}
|
||||
});
|
@@ -1,51 +0,0 @@
|
||||
const { Gio, GObject } = imports.gi;
|
||||
const Debug = imports.src.debug;
|
||||
const Misc = imports.src.misc;
|
||||
|
||||
const { debug } = Debug;
|
||||
|
||||
var WebApp = GObject.registerClass({
|
||||
GTypeName: 'ClapperWebApp',
|
||||
},
|
||||
class ClapperWebApp extends Gio.SubprocessLauncher
|
||||
{
|
||||
_init()
|
||||
{
|
||||
const flags = Gio.SubprocessFlags.STDOUT_SILENCE
|
||||
| Gio.SubprocessFlags.STDERR_SILENCE;
|
||||
|
||||
super._init({ flags });
|
||||
|
||||
this.daemonApp = null;
|
||||
}
|
||||
|
||||
startDaemonApp(port)
|
||||
{
|
||||
if(this.daemonApp)
|
||||
return;
|
||||
|
||||
this.daemonApp = this.spawnv([Misc.appId + '.Daemon', String(port)]);
|
||||
this.daemonApp.wait_async(null, this._onDaemonClosed.bind(this));
|
||||
|
||||
debug('daemon app started');
|
||||
}
|
||||
|
||||
_onDaemonClosed(proc, result)
|
||||
{
|
||||
let hadError;
|
||||
|
||||
try {
|
||||
hadError = proc.wait_finish(result);
|
||||
}
|
||||
catch(err) {
|
||||
debug(err);
|
||||
}
|
||||
|
||||
this.daemonApp = null;
|
||||
|
||||
if(hadError)
|
||||
debug('daemon app exited with error or was forced to close');
|
||||
|
||||
debug('daemon app closed');
|
||||
}
|
||||
});
|
@@ -1,90 +0,0 @@
|
||||
const { Gio, GObject, Soup } = imports.gi;
|
||||
const Debug = imports.src.debug;
|
||||
const Misc = imports.src.misc;
|
||||
const WebHelpers = imports.src.webHelpers;
|
||||
|
||||
const { debug } = Debug;
|
||||
const { settings } = Misc;
|
||||
|
||||
var WebClient = GObject.registerClass({
|
||||
GTypeName: 'ClapperWebClient',
|
||||
},
|
||||
class ClapperWebClient extends Soup.Session
|
||||
{
|
||||
_init(port)
|
||||
{
|
||||
super._init({
|
||||
timeout: 3,
|
||||
use_thread_context: true,
|
||||
});
|
||||
|
||||
this.wsConn = null;
|
||||
|
||||
this.connectWebsocket();
|
||||
}
|
||||
|
||||
connectWebsocket()
|
||||
{
|
||||
if(this.wsConn)
|
||||
return;
|
||||
|
||||
const port = settings.get_int('webserver-port');
|
||||
const message = Soup.Message.new('GET', `ws://127.0.0.1:${port}/websocket`);
|
||||
this.websocket_connect_async(message, null, null, null, this._onWsConnect.bind(this));
|
||||
|
||||
debug('connecting WebSocket to Clapper app');
|
||||
}
|
||||
|
||||
sendMessage(data)
|
||||
{
|
||||
if(
|
||||
!this.wsConn
|
||||
|| this.wsConn.state !== Soup.WebsocketState.OPEN
|
||||
)
|
||||
return;
|
||||
|
||||
this.wsConn.send_text(JSON.stringify(data));
|
||||
}
|
||||
|
||||
passMsgData(action, value)
|
||||
{
|
||||
}
|
||||
|
||||
_onWsConnect(session, result)
|
||||
{
|
||||
let connection = null;
|
||||
|
||||
try {
|
||||
connection = this.websocket_connect_finish(result);
|
||||
}
|
||||
catch(err) {
|
||||
debug(err);
|
||||
}
|
||||
|
||||
if(!connection)
|
||||
return this.passMsgData('close');
|
||||
|
||||
connection.connect('message', this._onWsMessage.bind(this));
|
||||
connection.connect('closed', this._onWsClosed.bind(this));
|
||||
|
||||
this.wsConn = connection;
|
||||
|
||||
debug('successfully connected WebSocket');
|
||||
}
|
||||
|
||||
_onWsMessage(connection, dataType, bytes)
|
||||
{
|
||||
const [success, parsedMsg] = WebHelpers.parseData(dataType, bytes);
|
||||
|
||||
if(success)
|
||||
this.passMsgData(parsedMsg.action, parsedMsg.value);
|
||||
}
|
||||
|
||||
_onWsClosed(connection)
|
||||
{
|
||||
debug('closed WebSocket connection');
|
||||
this.wsConn = null;
|
||||
|
||||
this.passMsgData('close');
|
||||
}
|
||||
});
|
@@ -1,72 +0,0 @@
|
||||
const { GObject, Gtk } = imports.gi;
|
||||
const Buttons = imports.src.buttons;
|
||||
const Misc = imports.src.misc;
|
||||
const { PlayerRemote, ClapperState } = imports.src.playerRemote;
|
||||
|
||||
var WidgetRemote = GObject.registerClass({
|
||||
GTypeName: 'ClapperWidgetRemote',
|
||||
},
|
||||
class ClapperWidgetRemote extends Gtk.Grid
|
||||
{
|
||||
_init(opts)
|
||||
{
|
||||
super._init({
|
||||
halign: Gtk.Align.CENTER,
|
||||
valign: Gtk.Align.CENTER,
|
||||
});
|
||||
|
||||
Misc.loadCustomCss();
|
||||
|
||||
this.player = new PlayerRemote();
|
||||
this.player.webclient.passMsgData = this.receiveWs.bind(this);
|
||||
|
||||
/* FIXME: create better way to add buttons for
|
||||
* remote app without duplicating too much code */
|
||||
this.togglePlayButton = new Buttons.IconToggleButton(
|
||||
'media-playback-start-symbolic',
|
||||
'media-playback-pause-symbolic'
|
||||
);
|
||||
this.togglePlayButton.remove_css_class('flat');
|
||||
this.togglePlayButton.connect(
|
||||
'clicked', () => this.sendWs('toggle_play')
|
||||
);
|
||||
|
||||
this.attach(this.togglePlayButton, 0, 0, 1, 1);
|
||||
}
|
||||
|
||||
sendWs(action, value)
|
||||
{
|
||||
const data = { action };
|
||||
|
||||
/* do not send "null" or "undefined"
|
||||
* for faster network data transfer */
|
||||
if(value != null)
|
||||
data.value = value;
|
||||
|
||||
this.player.webclient.sendMessage(data);
|
||||
}
|
||||
|
||||
receiveWs(action, value)
|
||||
{
|
||||
switch(action) {
|
||||
case 'state_changed':
|
||||
switch(value) {
|
||||
case ClapperState.STOPPED:
|
||||
case ClapperState.PAUSED:
|
||||
this.togglePlayButton.setPrimaryIcon();
|
||||
break;
|
||||
case ClapperState.PLAYING:
|
||||
this.togglePlayButton.setSecondaryIcon();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'close':
|
||||
this.root.run_dispose();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
@@ -177,20 +177,6 @@
|
||||
<property name="spin-adjustment">web_server_adjustment</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ClapperPrefsSwitch">
|
||||
<property name="title" translatable="yes">Run web application in background</property>
|
||||
<property name="subtitle" translatable="yes">Requires GTK compiled with Broadway backend</property>
|
||||
<property name="schema-name">webapp-enabled</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="ClapperPrefsSpin">
|
||||
<property name="title" translatable="yes">Web application port</property>
|
||||
<property name="schema-name">webapp-port</property>
|
||||
<property name="spin-adjustment">web_app_adjustment</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
Reference in New Issue
Block a user