diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt index 7e9ad8d..af3819a 100644 --- a/demo/CMakeLists.txt +++ b/demo/CMakeLists.txt @@ -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) - diff --git a/demo/sigint.c b/demo/sigint.c new file mode 100644 index 0000000..d390765 --- /dev/null +++ b/demo/sigint.c @@ -0,0 +1,64 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * 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 . + */ +#include +#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);*/ +} diff --git a/demo/sigint.h b/demo/sigint.h new file mode 100644 index 0000000..56e6031 --- /dev/null +++ b/demo/sigint.h @@ -0,0 +1,29 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * 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 . + */ + +#include + +#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 */ diff --git a/demo/sigint.vapi b/demo/sigint.vapi new file mode 100644 index 0000000..94bb278 --- /dev/null +++ b/demo/sigint.vapi @@ -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(); +} diff --git a/demo/wfdctl.vala b/demo/wfdctl.vala index d8f5d50..032c215 100644 --- a/demo/wfdctl.vala +++ b/demo/wfdctl.vala @@ -1,3 +1,22 @@ +/* + * MiracleCast - Wifi-Display/Miracast Implementation + * + * Copyright (c) 2013-2014 David Herrmann + * + * 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 . + */ + 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(); }