Merge pull request #214 from Rafostar/libsoup3

libsoup3
This commit is contained in:
Rafał Dzięgiel
2022-02-28 16:58:29 +01:00
committed by GitHub
20 changed files with 51 additions and 462 deletions

View File

@@ -11,7 +11,7 @@ jobs:
name: "Flatpak"
runs-on: ubuntu-latest
container:
image: bilelmoussaoui/flatpak-github-actions:gnome-40
image: bilelmoussaoui/flatpak-github-actions:gnome-41
options: --privileged
strategy:
matrix:

View File

@@ -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);

View File

@@ -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(
configure_file(
input: 'com.github.rafostar.Clapper.in',
output: 'com.github.rafostar.Clapper' + app_postfix,
output: 'com.github.rafostar.Clapper',
configuration: bin_conf,
install: true,
install_dir: bindir,
install_mode: 'rwxr-xr-x'
)
endforeach
)
clapper_symlink_cmd = 'ln -fs @0@ $DESTDIR@1@'.format(
'com.github.rafostar.Clapper',

View File

@@ -32,6 +32,7 @@
"flathub/lib/libdvdnav.json",
"flathub/lib/libass.json",
"flathub/lib/ffmpeg.json",
"testing/libsoup3.json",
"testing/gstreamer.json",
"testing/gtuber.json",
{

View File

@@ -1,7 +1,7 @@
{
"app-id": "com.github.rafostar.Clapper",
"runtime": "org.gnome.Platform",
"runtime-version": "40",
"runtime-version": "41",
"sdk": "org.gnome.Sdk",
"command": "com.github.rafostar.Clapper",
"finish-args": [
@@ -33,6 +33,7 @@
"flathub/lib/libass.json",
"flathub/lib/ffmpeg.json",
"flathub/lib/uchardet.json",
"testing/libsoup3.json",
"flathub/gstreamer-1.0/gstreamer.json",
"flathub/lib/gtk4.json",
"flathub/lib/libadwaita.json",

View File

@@ -0,0 +1,24 @@
{
"name": "libsoup3",
"buildsystem": "meson",
"config-opts": [
"-Dintrospection=enabled",
"-Dvapi=disabled",
"-Dtests=false",
"-Dsysprof=disabled",
"-Dhttp2_tests=disabled",
"-Dpkcs11_tests=disabled"
],
"cleanup": [
"/include",
"/lib/pkgconfig"
],
"sources": [
{
"type": "git",
"url": "https://gitlab.gnome.org/GNOME/libsoup.git",
"tag": "3.0.4",
"commit": "25a728020c4b53b5db4c4c675070e92f947fbd4d"
}
]
}

View File

@@ -24,6 +24,7 @@
%global gtk4_version 4.0.0
%global meson_version 0.50
%global glib2_version 2.56.0
%global soup_version 3.0.0
Name: clapper
Version: 0.4.1
@@ -59,6 +60,7 @@ BuildRequires: gstreamer-plugins-base-devel >= %{gst_version}
BuildRequires: Mesa-libGLESv2-devel
BuildRequires: Mesa-libGLESv3-devel
Requires: libsoup-devel >= %{soup_version}
Requires: gstreamer >= %{gst_version}
Requires: gstreamer-plugins-base >= %{gst_version}
Requires: gstreamer-plugins-good >= %{gst_version}
@@ -80,6 +82,7 @@ BuildRequires: mesa-libGLES-devel
BuildRequires: mesa-libGLU-devel
BuildRequires: mesa-libEGL-devel
Requires: libsoup3-devel
Requires: gstreamer1 >= %{gst_version}
Requires: gstreamer1-plugins-base >= %{gst_version}
Requires: gstreamer1-plugins-good >= %{gst_version}
@@ -129,6 +132,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop
%{_libdir}/%{appname}/
%changelog
* Thu Feb 17 2022 Rafostar <rafostar.github@gmail.com> - 0.4.1-2
- Require libsoup3
* Mon Dec 20 2021 Rafostar <rafostar.github@gmail.com> - 0.4.1-1
- New version

View File

@@ -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();
}
});

View File

@@ -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();
}
});

View File

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

View File

@@ -1,6 +1,6 @@
imports.gi.versions.Gdk = '4.0';
imports.gi.versions.Gtk = '4.0';
imports.gi.versions.Soup = '2.4';
imports.gi.versions.Soup = '3.0';
pkg.initGettext();
pkg.initFormat();

View File

@@ -1,6 +0,0 @@
const { Daemon } = imports.src.daemon;
function main()
{
new Daemon();
}

View File

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

View File

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

View File

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

View File

@@ -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');
}
});

View File

@@ -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');
}
});

View File

@@ -107,7 +107,7 @@ class ClapperWebServer extends Soup.Server
this.remove_handler('/');
}
_onWsConnection(server, connection)
_onWsConnection(server, msg, path, connection)
{
debug('new WebSocket connection');

View File

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

View File

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