no longer need ffmpeg patch0 which was for Termux
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / shbtnprefs.C
1 /*
2  * CINELERRA
3  * Copyright (C) 2016-2020 William Morrow
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20
21 #include "bcwindowbase.h"
22 #include "bcdisplayinfo.h"
23 #include "bcdialog.h"
24 #include "awindow.h"
25 #include "awindowgui.h"
26 #include "cstrdup.h"
27 #include "indexable.h"
28 #include "language.h"
29 #include "mainerror.h"
30 #include "mainsession.h"
31 #include "mwindow.h"
32 #include "shbtnprefs.h"
33 #include "preferences.h"
34 #include "preferencesthread.h"
35 #include "theme.h"
36
37 #include <sys/wait.h>
38
39 ShBtnRun::ShBtnRun(const char *nm, const char *cmds, int warn)
40  : Thread(0, 0, 1)
41 {
42         argv.set_array_delete();
43         strncpy(name, nm, sizeof(name)-1);
44         name[sizeof(name)-1] = 0;
45         strncpy(commands, cmds, sizeof(commands)-1);
46         commands[sizeof(commands)-1] = 0;
47         this->warn = warn;
48 }
49 ShBtnRun::~ShBtnRun()
50 {
51         argv.remove_all_objects();
52 }
53
54 void ShBtnRun::add_arg(const char *v)
55 {
56         argv.append(cstrdup(v));
57 }
58
59 void ShBtnRun::run()
60 {
61         pid_t pid = vfork();
62         if( pid < 0 ) {
63                 perror("fork");
64                 return;
65         }
66         char msg[BCTEXTLEN];
67         if( !pid ) {
68                 argv.append(0);
69                 execvp(argv[0], &argv[0]);
70                 return;
71         }
72         // warn <0:always, =0:never, >0:on err
73         if( !warn ) return;
74         int stat;  waitpid(pid, &stat, 0);
75         if( !stat ) {
76                 if( warn > 0 ) return;
77                 sprintf(msg, "%s: completed", name);
78         }
79         else
80                 sprintf(msg, "%s: error exit status %d", name, stat);
81         MainError::show_error(msg);
82 }
83
84 ShBtnPref::ShBtnPref(const char *nm, const char *cmds, int warn, int run_script)
85 {
86         strncpy(name, nm, sizeof(name));
87         strncpy(commands, cmds, sizeof(commands));
88         this->warn = warn;
89         this->run_script = run_script;
90 }
91
92 ShBtnPref::~ShBtnPref()
93 {
94 }
95
96 void ShBtnPref::execute(ArrayList<Indexable*> &args)
97 {
98 // thread async+autodelete, no explicit delete
99         ShBtnRun *job = new ShBtnRun(name, commands, warn);
100         job->add_arg("/bin/bash");
101         job->add_arg(commands);
102         int n = args.size();
103         for( int i=0; i<n; ++i ) {
104                 Indexable *idxbl = args[i];
105                 if( !idxbl->is_asset ) continue;
106                 job->add_arg(idxbl->path);
107         }
108         job->start();
109 }
110
111 void ShBtnPref::execute()
112 {
113         ShBtnRun *job = new ShBtnRun(name, commands, warn);
114         job->add_arg("/bin/bash");
115         job->add_arg("-c");
116         job->add_arg(commands);
117         job->start();
118 }
119
120 ShBtnEditDialog::ShBtnEditDialog(PreferencesWindow *pwindow)
121  : BC_DialogThread()
122 {
123         this->pwindow = pwindow;
124 }
125
126 ShBtnEditDialog::~ShBtnEditDialog()
127 {
128         close_window();
129 }
130
131 BC_Window* ShBtnEditDialog::new_gui()
132 {
133         BC_DisplayInfo display_info;
134         int x = display_info.get_abs_cursor_x();
135         int y = display_info.get_abs_cursor_y();
136
137         sb_window = new ShBtnEditWindow(this, x, y);
138         sb_window->create_objects();
139         return sb_window;
140 }
141
142 void ShBtnEditDialog::handle_close_event(int result)
143 {
144         sb_window = 0;
145 }
146
147
148 ShBtnEditWindow::ShBtnEditWindow(ShBtnEditDialog *shbtn_edit, int x, int y)
149  : BC_Window(_(PROGRAM_NAME ": Shell"), x, y,
150                 xS(300), yS(200), xS(300), yS(200), 0, 0, 1)
151 {
152         this->shbtn_edit = shbtn_edit;
153         sb_dialog = 0;
154 // *** CONTEXT_HELP ***
155         context_help_set_keyword("Menu Bar Shell Commands");
156 }
157
158 ShBtnEditWindow::~ShBtnEditWindow()
159 {
160         delete sb_dialog;
161 }
162
163 int ShBtnEditWindow::list_update()
164 {
165         shbtn_items.remove_all_objects();
166         Preferences *preferences = shbtn_edit->pwindow->thread->preferences;
167         for( int i=0; i<preferences->shbtn_prefs.size(); ++i ) {
168                 shbtn_items.append(new ShBtnPrefItem(preferences->shbtn_prefs[i]));
169         }
170         return op_list->update(&shbtn_items, 0, 0, 1);
171 }
172
173 ShBtnAddButton::ShBtnAddButton(ShBtnEditWindow *sb_window, int x, int y)
174  : BC_GenericButton(x, y, _("Add"))
175 {
176         this->sb_window = sb_window;
177 }
178
179 ShBtnAddButton::~ShBtnAddButton()
180 {
181 }
182
183 int ShBtnAddButton::handle_event()
184 {
185
186         Preferences *preferences = sb_window->shbtn_edit->pwindow->thread->preferences;
187         ShBtnPref *pref = new ShBtnPref(_("new"), "", 0, 0);
188         preferences->shbtn_prefs.append(pref);
189         sb_window->list_update();
190         return sb_window->start_edit(pref);
191 }
192
193 ShBtnDelButton::ShBtnDelButton(ShBtnEditWindow *sb_window, int x, int y)
194  : BC_GenericButton(x, y, _("Del"))
195 {
196         this->sb_window = sb_window;
197 }
198
199 ShBtnDelButton::~ShBtnDelButton()
200 {
201 }
202
203 int ShBtnDelButton::handle_event()
204 {
205         ShBtnPrefItem *sp = (ShBtnPrefItem *)sb_window->op_list->get_selection(0,0);
206         if( !sp ) return 0;
207         Preferences *preferences = sb_window->shbtn_edit->pwindow->thread->preferences;
208         preferences->shbtn_prefs.remove(sp->pref);
209         sb_window->list_update();
210         return 1;
211 }
212
213 ShBtnEditButton::ShBtnEditButton(ShBtnEditWindow *sb_window, int x, int y)
214  : BC_GenericButton(x, y, _("Edit"))
215 {
216         this->sb_window = sb_window;
217 }
218
219 ShBtnEditButton::~ShBtnEditButton()
220 {
221 }
222
223 int ShBtnEditButton::handle_event()
224 {
225         ShBtnPrefItem *sp = (ShBtnPrefItem *)sb_window->op_list->get_selection(0,0);
226         if( !sp ) return 0;
227         return sb_window->start_edit(sp->pref);
228 }
229
230 ShBtnTextDialog::ShBtnTextDialog(ShBtnEditWindow *sb_window)
231  : BC_DialogThread()
232 {
233         this->sb_window = sb_window;
234         this->pref = 0;
235 }
236
237 ShBtnTextDialog::~ShBtnTextDialog()
238 {
239         close_window();
240 }
241
242 ShBtnTextWindow::ShBtnTextWindow(ShBtnEditWindow *sb_window, int x, int y)
243  : BC_Window(_(PROGRAM_NAME ": Commands"), x, y,
244                 xS(640), yS(160), xS(640), yS(150), 0, 0, 1)
245 {
246         this->sb_window = sb_window;
247         warn = sb_window->sb_dialog->pref->warn;
248         run_script = sb_window->sb_dialog->pref->run_script;
249 // *** CONTEXT_HELP ***
250         context_help_set_keyword("Menu Bar Shell Commands");
251 }
252
253 ShBtnTextWindow::~ShBtnTextWindow()
254 {
255 }
256
257
258 ShBtnErrWarnItem::ShBtnErrWarnItem(ShBtnErrWarn *popup,
259                 const char *text, int warn)
260  : BC_MenuItem(text)
261 {
262         this->popup = popup;
263         this->warn = warn;
264 }
265
266 int ShBtnErrWarnItem::handle_event()
267 {
268         popup->set_text(get_text());
269         popup->st_window->warn = warn;
270         return 1;
271 }
272
273 ShBtnErrWarn::ShBtnErrWarn(ShBtnTextWindow *st_window, int x, int y)
274  : BC_PopupMenu(x, y, xS(120), st_window->warn < 0 ? _("Always"):
275         !st_window->warn ? _("Never") : _("On Error"))
276 {
277         this->st_window = st_window;
278 }
279 ShBtnErrWarn::~ShBtnErrWarn()
280 {
281 }
282 int ShBtnErrWarn::handle_event()
283 {
284         return 0;
285 }
286
287 void ShBtnErrWarn::create_objects()
288 {
289         add_item(new ShBtnErrWarnItem(this,_("Always"), -1));
290         add_item(new ShBtnErrWarnItem(this,_("Never"), 0));
291         add_item(new ShBtnErrWarnItem(this,_("On Error"), 1));
292 }
293
294
295 ShBtnRunScript::ShBtnRunScript(ShBtnTextWindow *st_window, int x, int y)
296  : BC_CheckBox(x, y, &st_window->run_script, _("run /path/script.sh + argvs"))
297 {
298         this->st_window = st_window;
299 }
300
301 ShBtnRunScript::~ShBtnRunScript()
302 {
303 }
304
305 void ShBtnTextWindow::create_objects()
306 {
307         lock_window("ShBtnTextWindow::create_objects");
308         int x = xS(10), y = yS(10);
309         int x1 = xS(160);
310         BC_Title *title = new BC_Title(x, y, _("Label:"));
311         add_subwindow(title);
312         title = new BC_Title(x1, y, _("Commands:"));
313         add_subwindow(title);
314         y += title->get_h() + yS(8);
315         ShBtnPref *pref = sb_window->sb_dialog->pref;
316         cmd_name = new BC_TextBox(x, y, xS(140), 1, pref->name);
317         add_subwindow(cmd_name);
318         cmd_text = new BC_ScrollTextBox(this, x1, y, get_w()-x1-xS(20), 4, pref->commands);
319         cmd_text->create_objects();
320         y += cmd_text->get_h() + yS(16);
321         add_subwindow(title = new BC_Title(x1,y, _("OnExit Notify:")));
322         x1 += title->get_w() + xS(10);
323         add_subwindow(st_err_warn = new ShBtnErrWarn(this, x1, y));
324         st_err_warn->create_objects();
325         x1 += st_err_warn->get_w() + xS(20);
326         add_subwindow(st_run_script = new ShBtnRunScript(this, x1, y));
327         y = get_h() - ShBtnTextOK::calculate_h() - yS(10);
328         add_subwindow(new ShBtnTextOK(this, x, y));
329         show_window();
330         unlock_window();
331 }
332
333 ShBtnTextOK::ShBtnTextOK(ShBtnTextWindow *st_window, int x, int y)
334  : BC_OKButton(x, y)
335 {
336         this->st_window = st_window;
337 }
338
339 ShBtnTextOK::~ShBtnTextOK()
340 {
341 }
342
343 int ShBtnTextOK::handle_event()
344 {
345         ShBtnPref *pref = st_window->sb_window->sb_dialog->pref;
346         strcpy(pref->name, st_window->cmd_name->get_text());
347         strcpy(pref->commands, st_window->cmd_text->get_text());
348         pref->warn = st_window->warn;
349         pref->run_script = st_window->run_script;
350         return BC_OKButton::handle_event();
351 }
352
353
354 BC_Window *ShBtnTextDialog::new_gui()
355 {
356         BC_DisplayInfo display_info;
357         int x = display_info.get_abs_cursor_x();
358         int y = display_info.get_abs_cursor_y();
359
360         st_window = new ShBtnTextWindow(sb_window, x, y);
361         st_window->create_objects();
362         return st_window;
363 }
364
365 void ShBtnTextDialog::handle_close_event(int result)
366 {
367         if( !result ) {
368                 sb_window->lock_window("ShBtnTextDialog::handle_close_event");
369                 sb_window->list_update();
370                 sb_window->unlock_window();
371         }
372         st_window = 0;
373 }
374
375 int ShBtnTextDialog::start_edit(ShBtnPref *pref)
376 {
377         this->pref = pref;
378         start();
379         return 1;
380 }
381
382 void ShBtnEditWindow::create_objects()
383 {
384         lock_window("ShBtnEditWindow::create_objects");
385         Preferences *preferences = shbtn_edit->pwindow->thread->preferences;
386         for( int i=0; i<preferences->shbtn_prefs.size(); ++i ) {
387                 shbtn_items.append(new ShBtnPrefItem(preferences->shbtn_prefs[i]));
388         }
389         int x = xS(10), y = yS(10);
390         add_subwindow(op_list = new ShBtnPrefList(this, x, y));
391         x = xS(190);
392         add_subwindow(add_button = new ShBtnAddButton(this, x, y));
393         y += add_button->get_h() + yS(8);
394         add_subwindow(del_button = new ShBtnDelButton(this, x, y));
395         y += del_button->get_h() + yS(8);
396         add_subwindow(edit_button = new ShBtnEditButton(this, x, y));
397         add_subwindow(new BC_OKButton(this));
398         show_window();
399         unlock_window();
400 }
401
402 int ShBtnEditWindow::start_edit(ShBtnPref *pref)
403 {
404         if( !sb_dialog )
405                 sb_dialog = new ShBtnTextDialog(this);
406         return sb_dialog->start_edit(pref);
407 }
408
409
410 ShBtnPrefItem::ShBtnPrefItem(ShBtnPref *pref)
411  : BC_ListBoxItem(pref->name)
412 {
413         this->pref = pref;
414 }
415
416 ShBtnPrefItem::~ShBtnPrefItem()
417 {
418 }
419
420 ShBtnPrefList::ShBtnPrefList(ShBtnEditWindow *sb_window, int x, int y)
421  : BC_ListBox(x, y, xS(140), yS(100), LISTBOX_TEXT, &sb_window->shbtn_items, 0, 0)
422 {
423         this->sb_window = sb_window;
424 }
425
426 ShBtnPrefList::~ShBtnPrefList()
427 {
428 }
429
430 int ShBtnPrefList::handle_event()
431 {
432         return 1;
433 }
434
435 MainShBtnItem::MainShBtnItem(MainShBtns *shbtns, ShBtnPref *pref)
436  : BC_MenuItem(pref->name)
437 {
438         this->shbtns = shbtns;
439         this->pref = pref;
440 }
441
442 int MainShBtnItem::handle_event()
443 {
444         MWindow *mwindow = shbtns->mwindow;
445         if( pref->run_script ) {
446                 AWindowGUI *agui = mwindow->awindow->gui;
447                 agui->lock_window("MainShBtnItem::handle_event");
448                 mwindow->awindow->gui->collect_assets();
449                 pref->execute(*mwindow->session->drag_assets);
450                 agui->unlock_window();
451         }
452         else
453                 pref->execute();
454         return 1;
455 }
456
457 MainShBtns::MainShBtns(MWindow *mwindow, int x, int y)
458  : BC_PopupMenu(x, y, 0, "", -1, mwindow->theme->shbtn_data)
459 {
460         this->mwindow = mwindow;
461         set_tooltip(_("shell cmds"));
462 // *** CONTEXT_HELP ***
463         context_help_set_keyword("Menu Bar Shell Commands");
464 }
465
466 int MainShBtns::load(Preferences *preferences)
467 {
468         while( total_items() ) del_item(0);
469         for( int i=0; i<preferences->shbtn_prefs.size(); ++i )
470                 add_item(new MainShBtnItem(this, preferences->shbtn_prefs[i]));
471         return 0;
472 }
473
474 int MainShBtns::handle_event()
475 {
476         return 1;
477 }
478