1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-02-13 02:51:58 +00:00

demo/miracle-wfdctl: handle SIGINT to exit gracefully

This commit is contained in:
Derek Dai 2017-03-25 17:47:51 +08:00
parent a0d0c9bc8c
commit 57c4bbeae5
No known key found for this signature in database
GPG key ID: E109CC97553EF009
5 changed files with 153 additions and 30 deletions

View file

@ -56,9 +56,8 @@ add_custom_command(OUTPUT wfdctl.c
COMMAND ${VALAC} --target-glib=2.50 -H wfdctl.h --use-header -C
--pkg=gio-2.0
--pkg=gdk-3.0
--pkg=posix
--pkg=linux
${CMAKE_CURRENT_SOURCE_DIR}/wfdctl.vala
${CMAKE_CURRENT_SOURCE_DIR}/sigint.vapi
org-freedesktop-networkmanager.vala
org-freedesktop-miracle-wifi.vala
org-freedesktop-miracle-wfd.vala
@ -78,7 +77,9 @@ add_custom_command(OUTPUT wfdctl-res.c
${RES_DIR}/wfdctl-res.xml
WORKING_DIRECTORY ${RES_DIR})
include_directories(${GIO2_INCLUDE_DIRS} ${GDK3_INCLUDE_DIRS})
include_directories(${GIO2_INCLUDE_DIRS}
${GDK3_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR})
# silent C compiler warning about valac generated code, bad practice
set(CMAKE_C_FLAGS "-Wno-unused-label ${CMAKE_C_FLAGS}")
@ -88,6 +89,7 @@ set(CMAKE_C_FLAGS "-Wno-unused-but-set-variable ${CMAKE_C_FLAGS}")
add_executable(miracle-wfdctl wfdctl
wfdctl-res.c
sigint.c
org-freedesktop-networkmanager.c
org-freedesktop-miracle-wifi.c
org-freedesktop-miracle-wfd.c)
@ -96,4 +98,3 @@ target_link_libraries(miracle-wfdctl ${GIO2_LIBRARIES}
${GDK3_LIBRARIES})
install(TARGETS miracle-wfdctl DESTINATION bin)

64
demo/sigint.c Normal file
View file

@ -0,0 +1,64 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* MiracleCast is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* MiracleCast is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/signalfd.h>
#include "sigint.h"
typedef struct _SigintDelegate SigintDelegate;
struct _SigintDelegate
{
SigintHandler handler;
gpointer user_data;
};
static gboolean sigint_on_signal(GIOChannel *c, GIOCondition e, gpointer d)
{
struct signalfd_siginfo siginfo;
g_io_channel_read_chars(c, (gchar *) &siginfo, sizeof(siginfo), NULL, NULL);
SigintDelegate *delegate = d;
(*delegate->handler)(delegate->user_data);
return FALSE;
}
void sigint_add_watch(SigintHandler handler, gpointer user_data)
{
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigprocmask(SIG_BLOCK, &mask, NULL);
SigintDelegate *d = g_malloc(sizeof(SigintDelegate));
*d = (SigintDelegate) {
handler = handler,
user_data = user_data
};
int fd = signalfd(-1, &mask, SFD_CLOEXEC);
GIOChannel *c = g_io_channel_unix_new(fd);
g_io_add_watch_full(c,
G_PRIORITY_DEFAULT,
G_IO_IN | G_IO_ERR | G_IO_HUP,
sigint_on_signal,
d,
g_free);
g_io_channel_set_encoding(c, NULL, NULL);
/*g_io_channel_unref(c);*/
}

29
demo/sigint.h Normal file
View file

@ -0,0 +1,29 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* MiracleCast is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* MiracleCast is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib.h>
#ifndef DISP_SIGFD_H
#define DISP_SIGFD_H
typedef void (*SigintHandler)(gpointer user_data);
void sigint_add_watch(SigintHandler handler, gpointer user_data);
#endif /* DISP_SIGFD_H */

8
demo/sigint.vapi Normal file
View file

@ -0,0 +1,8 @@
[CCode(cheader_filename="sigint.h")]
class Sigint
{
public delegate void Handler();
public static void add_watch(Handler handler);
public static void remove_watch();
}

View file

@ -1,3 +1,22 @@
/*
* MiracleCast - Wifi-Display/Miracast Implementation
*
* Copyright (c) 2013-2014 David Herrmann <dh.herrmann@gmail.com>
*
* MiracleCast is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* MiracleCast is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with MiracleCast; If not, see <http://www.gnu.org/licenses/>.
*/
using Org.Freedesktop.NetworkManager;
using Org.Freedesktop.Miracle.Wifi;
using Org.Freedesktop.Miracle.Wfd;
@ -82,14 +101,13 @@ private class WfdCtl : GLib.Application
string curr_sink_mac;
Gdk.Display display;
Session curr_session;
IOChannel sig_channel;
const GLib.OptionEntry[] option_entries = {
{ "interface", 'i', 0, OptionArg.STRING, ref opt_iface, "name of wireless network interface", "WNIC name" },
{ "wfd-subelems", 'w', 0, OptionArg.STRING, ref opt_wfd_subelems, "device infomation. default: 000600111c4400c8", "device info subelems" },
{ "peer-mac", 'p', 0, OptionArg.STRING, ref opt_peer_mac, "MAC address of target peer", "peer MAC" },
{ "authority", 'x', 0, OptionArg.STRING, ref opt_authority, "authority to capture from display. default: XAUTHORITY environment variable", "display authority" },
{ "display", 'd', 0, OptionArg.STRING, ref opt_display, "display name. default: DISPLAY environment variable", "display name" },
{ "display", 'd', 0, OptionArg.STRING, ref opt_display, "display name. default: DISPLAY environment variable", "display name" },
{ "monitor-num", 'm', 0, OptionArg.INT, ref opt_monitor_num, "monitor number. default: -1, primary monitor", "monitor number" },
{ "audio-device", 'a', 0, OptionArg.STRING, ref opt_audio_device, "pulseaudio device name", "audio device name" },
{ null },
@ -500,10 +518,31 @@ private class WfdCtl : GLib.Application
yield wait_for_session_ending();
yield release_wnic_ownership();
release();
quit();
print("Bye");
}
public void stop_wireless_display()
{
info("tearing down wireless display...");
try {
if(null != curr_session) {
curr_session.teardown();
}
else {
release_wnic_ownership.begin(() => {
quit();
print("Bye");
});
}
}
catch(Error e) {
warning("%s", e.message);
}
}
private bool check_options()
{
if(null == opt_peer_mac) {
@ -575,29 +614,6 @@ private class WfdCtl : GLib.Application
return;
}
/* vala has bug in generatde C code looks like
* sigset_t _tmp2_ = {0};
* sigset_t _tmp3_ = {0};
* sigset_t _tmp4_ = {0};
* sigset_t _tmp5_ = {0};
* sigset_t _tmp6_ = {0};
* sigset_t _tmp7_ = {0};
* sigemptyset (&_tmp3_);
* sigaddset (&_tmp4_, SIGINT);
* sigprocmask (SIG_BLOCK, &_tmp5_, &_tmp6_); */
//Posix.sigset_t mask = {}, oldmask = {};
//Posix.sigemptyset(mask);
//Posix.sigaddset(mask, Posix.SIGINT);
//Posix.sigprocmask(Posix.SIG_BLOCK, mask, oldmask);
//sig_channel = new IOChannel.unix_new(Linux.signalfd(-1, mask));
//sig_channel.add_watch(IOCondition.IN, (s, e) => {
//info("Bye");
//release();
//return false;
//});
hold();
start_wireless_display.begin((o, r) => {
try {
start_wireless_display.end(r);
@ -607,6 +623,8 @@ private class WfdCtl : GLib.Application
release();
}
});
hold();
}
private unowned Device? find_device_by_name(string nic_name)
@ -694,9 +712,12 @@ int main(string[]? argv)
Intl.setlocale();
Environment.set_prgname(Path.get_basename(argv[0]));
Application app = new WfdCtl();
app.set_default();
Sigint.add_watch((app as WfdCtl).stop_wireless_display);
try {
app.register();
}