1 /*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2020 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21
22 #include "NsmHandler.h"
23
24
25 namespace nsmhandler {
26
27
28 /****************************************************************
29 ** class NsmWatchDog
30 **
31 ** Watch for incomming messages from NSM server in a extra timeout thread
32 **
33 */
34
NsmWatchDog()35 NsmWatchDog::NsmWatchDog()
36 :_execute(false) {
37 }
38
~NsmWatchDog()39 NsmWatchDog::~NsmWatchDog() {
40 if( _execute.load(std::memory_order_acquire) ) {
41 stop();
42 };
43 }
44
stop()45 void NsmWatchDog::stop() {
46 _execute.store(false, std::memory_order_release);
47 if (_thd.joinable()) {
48 _thd.join();
49 }
50 }
51
start(int interval,std::function<void (void)> func)52 void NsmWatchDog::start(int interval, std::function<void(void)> func) {
53 if( _execute.load(std::memory_order_acquire) ) {
54 stop();
55 };
56 _execute.store(true, std::memory_order_release);
57 _thd = std::thread([this, interval, func]() {
58 while (_execute.load(std::memory_order_acquire)) {
59 func();
60 std::this_thread::sleep_for(
61 std::chrono::milliseconds(interval));
62 }
63 });
64 }
65
is_running() const66 bool NsmWatchDog::is_running() const noexcept {
67 return ( _execute.load(std::memory_order_acquire) &&
68 _thd.joinable() );
69 }
70
71
72 /****************************************************************
73 ** class NsmHandler
74 **
75 ** Check if NSM server response, if so, connect the handlers
76 ** and signal the UI thread to set up the variables
77 */
78
NsmHandler(NsmSignalHandler * nsmsig_)79 NsmHandler::NsmHandler(NsmSignalHandler *nsmsig_)
80 : poll(),
81 nsmsig(nsmsig_),
82 nsm(0),
83 wait_id(true),
84 optional_gui(false) {
85
86 nsmsig->signal_trigger_nsm_gui_is_shown().connect(
87 sigc::mem_fun(this, &NsmHandler::_on_nsm_is_shown));
88
89 nsmsig->signal_trigger_nsm_gui_is_hidden().connect(
90 sigc::mem_fun(this, &NsmHandler::_on_nsm_is_hidden));
91 }
92
~NsmHandler()93 NsmHandler::~NsmHandler() {
94 if (nsm) {
95 nsm_free(nsm);
96 nsm = 0;
97 }
98 }
99
check_nsm(const char * name,char * argv[])100 bool NsmHandler::check_nsm(const char *name, char *argv[]) {
101
102 const char *nsm_url = getenv( "NSM_URL" );
103
104 if (nsm_url) {
105 nsm = nsm_new();
106 nsm_set_open_callback( nsm, nsm_open, static_cast<void*>(this));
107 nsm_set_save_callback( nsm, nsm_save, static_cast<void*>(this));
108 nsm_set_show_callback( nsm, nsm_show, static_cast<void*>(this));
109 nsm_set_hide_callback( nsm, nsm_hide, static_cast<void*>(this));
110 if ( 0 == nsm_init( nsm, nsm_url)) {
111 nsm_send_announce( nsm, name, ":optional-gui:", argv[0]);
112 int wait_count = 0;
113 while(wait_id) {
114 nsm_check_wait(nsm,500);
115 wait_count +=1;
116 if (wait_count > 200) {
117 fprintf (stderr, "\n NSM didn't response, exiting ...\n");
118 exit (1);
119 }
120 }
121 return true;
122 } else {
123 nsm_free(nsm);
124 nsm = 0;
125 }
126 }
127 return false;
128 }
129
_poll_nsm(void * arg)130 void NsmHandler::_poll_nsm(void* arg) {
131 NsmHandler *nsmh = static_cast<NsmHandler*>(arg);
132 nsm_check_nowait(nsmh->nsm);
133 }
134
_nsm_start_poll()135 void NsmHandler::_nsm_start_poll() {
136 poll.start(200, std::bind(_poll_nsm,this));
137 }
138
_nsm_open(const char * name,const char * display_name,const char * client_id,char ** out_msg)139 int NsmHandler::_nsm_open (const char *name, const char *display_name,
140 const char *client_id, char **out_msg ) {
141
142 if (strstr(nsm_get_session_manager_features(nsm), ":optional-gui:")) {
143 optional_gui = true;
144 }
145 nsmsig->trigger_nsm_gui_open(name, client_id, optional_gui);
146 wait_id = false;
147
148 _nsm_start_poll();
149
150 return ERR_OK;
151 }
152
_nsm_save(char ** out_msg)153 int NsmHandler::_nsm_save ( char **out_msg) {
154 nsmsig->trigger_nsm_save_gui();
155 return ERR_OK;
156 }
157
_nsm_show()158 void NsmHandler::_nsm_show () {
159 nsmsig->trigger_nsm_show_gui();
160 }
161
_nsm_hide()162 void NsmHandler::_nsm_hide () {
163 nsmsig->trigger_nsm_hide_gui();
164 }
165
_on_nsm_is_shown()166 void NsmHandler::_on_nsm_is_shown () {
167 nsm_send_is_shown(nsm);
168 }
169
_on_nsm_is_hidden()170 void NsmHandler::_on_nsm_is_hidden () {
171 nsm_send_is_hidden(nsm);
172 }
173
174 //static
nsm_open(const char * name,const char * display_name,const char * client_id,char ** out_msg,void * userdata)175 int NsmHandler::nsm_open (const char *name, const char *display_name,
176 const char *client_id, char **out_msg, void *userdata ) {
177 NsmHandler * nsmhandler = static_cast<NsmHandler*>(userdata);
178 return nsmhandler->_nsm_open (name, display_name, client_id, out_msg);
179 }
180
181 //static
nsm_save(char ** out_msg,void * userdata)182 int NsmHandler::nsm_save ( char **out_msg, void *userdata ) {
183 NsmHandler * nsmhandler = static_cast<NsmHandler*>(userdata);
184 return nsmhandler->_nsm_save(out_msg);
185 }
186
187 //static
nsm_show(void * userdata)188 void NsmHandler::nsm_show (void *userdata ) {
189 NsmHandler * nsmhandler = static_cast<NsmHandler*>(userdata);
190 return nsmhandler->_nsm_show();
191 }
192
193 //static
nsm_hide(void * userdata)194 void NsmHandler::nsm_hide (void *userdata ) {
195 NsmHandler * nsmhandler = static_cast<NsmHandler*>(userdata);
196 return nsmhandler->_nsm_hide();
197 }
198
199 } // namespace nsmhandler
200
201