1 // FLTK callback functions for butt
2 //
3 // Copyright 2007-2018 by Daniel Noethen.
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or (at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 #include <sys/types.h>
16 #include <sys/stat.h>
17
18 #include <errno.h>
19 #include <unistd.h>
20 #include <signal.h>
21 #include <time.h>
22 #include <pthread.h>
23
24 #ifdef WIN32
25 #define usleep(us) Sleep(us/1000)
26 #else
27 #include <sys/wait.h>
28 #endif
29
30 #include <FL/fl_ask.H>
31 #include <FL/Fl_Color_Chooser.H>
32 #include <samplerate.h>
33
34 #include "gettext.h"
35 #include "config.h"
36
37 #include "FL/Fl_My_Native_File_Chooser.H"
38 //#include <FL/Fl_Native_File_Chooser.H>
39 //#define Fl_My_Native_File_Chooser Fl_Native_File_Chooser
40
41 #include "cfg.h"
42 #include "butt.h"
43 #include "port_audio.h"
44 #include "timer.h"
45 #include "shoutcast.h"
46 #include "icecast.h"
47 #include "lame_encode.h"
48 #include "opus_encode.h"
49 #include "fl_callbacks.h"
50 #include "strfuncs.h"
51 #include "flgui.h"
52 #include "util.h"
53 #include "fl_timer_funcs.h"
54 #include "fl_funcs.h"
55 #include "update.h"
56
57
58 flgui *fl_g;
59 int display_info = STREAM_TIME;
60
61 pthread_t pt_connect;
62
63 int ask_user = 0;
connect_thread(void * data)64 void *connect_thread(void *data)
65 {
66 int ret;
67 int (*xc_connect)() = NULL;
68
69
70 if (cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
71 xc_connect = &sc_connect;
72 else //(cfg.srv[cfg.selected_srv]->type == ICECAST)
73 xc_connect = &ic_connect;
74
75 //try to connect as long as xc_connect returns non-zero and try_to_connect == 1
76 while ( ((ret = xc_connect()) != IC_OK) && (try_to_connect == 1) ) //xc_connect returns 0 when connected
77 {
78 // Stop connecting in case of a fatal error
79 if (ret == IC_ABORT)
80 {
81 fl_g->lcd->clear();
82 fl_g->lcd->print((const uchar*)_("idle"), strlen(_("idle")));
83 break;
84 }
85 if (ret == IC_ASK)
86 {
87 ask_user = 1;
88 while (ask_user_get_has_clicked() != 1)
89 usleep(100000); // 100ms
90
91 if (ask_user_get_answer() == IC_ABORT)
92 {
93 fl_g->lcd->clear();
94 fl_g->lcd->print((const uchar*)_("idle"), strlen(_("idle")));
95 ask_user_reset();
96 break;
97 }
98 ask_user_reset();
99 }
100
101 usleep(100000); // 100ms
102 }
103
104 //Connection established, we are not trying to connect anymore
105 try_to_connect = 0;
106
107 return NULL;
108 }
109
110 // Print "Connecting..." on the LCD as long as we are trying to connect
print_connecting_timeout(void *)111 void print_connecting_timeout(void *)
112 {
113 static int dummy = 0;
114
115 if (try_to_connect == 1)
116 {
117 if(dummy == 0)
118 {
119 print_lcd(_("connecting"), strlen(_("connecting")), 0, 1);
120 dummy++;
121 }
122 else if(dummy <= 3)
123 {
124 print_lcd(".", 1, 0, 0);
125 dummy++;
126 }
127 else if(dummy > 3)
128 {
129 dummy = 0;
130 }
131 else
132 dummy++;
133
134 Fl::repeat_timeout(0.25, &print_connecting_timeout);
135 }
136 else
137 {
138 dummy = 0;
139 }
140 }
141
button_connect_cb(void)142 void button_connect_cb(void)
143 {
144
145 char text_buf[256];
146
147 if(connected)
148 return;
149
150 if(try_to_connect)
151 return;
152
153 if(cfg.main.num_of_srv < 1)
154 {
155 print_info(_("Error: No server entry found.\nPlease add a server in the settings-window."), 1);
156 return;
157 }
158
159 if(!strcmp(cfg.audio.codec, "ogg") && (cfg.audio.bitrate < 48))
160 {
161 print_info(_("Error: ogg vorbis encoder doesn't support bitrates\n"
162 "lower than 48kbit"),1);
163 return;
164 }
165
166 if(cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
167 {
168 if( (!strcmp(cfg.audio.codec, "ogg")) || (!strcmp(cfg.audio.codec, "opus")) )
169 {
170 snprintf(text_buf, sizeof(text_buf), _("Warning: %s is not supported by every ShoutCast version"), cfg.audio.codec);
171 print_info(text_buf, 1);
172 }
173 if(!strcmp(cfg.audio.codec, "flac"))
174 {
175 print_info(_("Error: FLAC is not supported by ShoutCast"), 1);
176 return;
177 }
178 }
179
180
181 if(cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
182 snprintf(text_buf, sizeof(text_buf), _("Connecting to %s:%u (%u) ..."),
183 cfg.srv[cfg.selected_srv]->addr,
184 cfg.srv[cfg.selected_srv]->port+1,
185 cfg.srv[cfg.selected_srv]->port);
186 else
187 snprintf(text_buf, sizeof(text_buf), _("Connecting to %s:%u ..."),
188 cfg.srv[cfg.selected_srv]->addr,
189 cfg.srv[cfg.selected_srv]->port);
190
191 print_info(text_buf, 0);
192
193
194 //Clear libsamplerate state
195 snd_reset_samplerate_conv(SND_STREAM);
196
197 try_to_connect = 1;
198 pthread_create(&pt_connect, NULL, connect_thread, NULL);
199 Fl::add_timeout(0, &print_connecting_timeout);
200 while(try_to_connect)
201 {
202 if (ask_user == 1)
203 {
204 ask_user_ask();
205 ask_user = 0;
206 }
207
208 usleep(10000); //10 ms
209 Fl::wait(0); //update gui and parse user events
210 }
211
212 Fl::add_timeout(0.25, &cmd_timer);
213
214 if(!connected)
215 return;
216
217
218 //we have to make sure that the first audio data
219 //the server sees are the ogg headers
220 if(!strcmp(cfg.audio.codec, "ogg"))
221 vorbis_enc_write_header(&vorbis_stream);
222
223 if(!strcmp(cfg.audio.codec, "opus"))
224 opus_enc_write_header(&opus_stream);
225
226 // Reset the internal flac frame counter to zero to
227 // make sure that the header is sent to the server upon next connect
228 if(!strcmp(cfg.audio.codec, "flac"))
229 flac_enc_reinit(&flac_stream);
230
231
232
233 char bitrate_str[32];
234 if (strcmp(cfg.audio.codec, "flac") == 0)
235 snprintf(bitrate_str, sizeof(bitrate_str), "-");
236 else
237 snprintf(bitrate_str, sizeof(bitrate_str), "%dkbps", cfg.audio.bitrate);
238
239
240 print_info(_("Connection established"), 0);
241 snprintf(text_buf, sizeof(text_buf),
242 "Settings:\n"
243 "Type:\t\t%s\n"
244 "Codec:\t\t%s\n"
245 "Bitrate:\t%s\n"
246 "Samplerate:\t%dHz\n",
247 cfg.srv[cfg.selected_srv]->type == SHOUTCAST ? "ShoutCast" : "IceCast",
248 cfg.audio.codec,
249 bitrate_str,
250 strcmp(cfg.audio.codec, "opus") == 0 ? 48000 : cfg.audio.samplerate
251 );
252
253
254 if(cfg.srv[cfg.selected_srv]->type == ICECAST)
255 snprintf(text_buf+strlen(text_buf), sizeof(text_buf)-strlen(text_buf),
256 "Mountpoint:\t%s\n"
257 "User:\t\t%s\n"
258 "SSL/TLS:\t%s\n",
259 cfg.srv[cfg.selected_srv]->mount,
260 cfg.srv[cfg.selected_srv]->usr,
261 cfg.srv[cfg.selected_srv]->tls == 0 ? _("no") : _("yes")
262 );
263
264 print_info(text_buf, 0);
265
266 if (!cfg.main.song_update && !cfg.main.app_update)
267 update_song(1);
268
269 //the user may not change the audio device while streaming
270 fl_g->choice_cfg_dev->deactivate();
271 //the sames applies to the codecs
272 fl_g->choice_cfg_codec->deactivate();
273 // and the mono to stereo conversion
274 fl_g->check_cfg_mono_to_stereo->deactivate();
275
276
277 //Changing any audio settings while streaming does not work with
278 //ogg/vorbis & ogg/opus :(
279 if((!strcmp(cfg.audio.codec, "ogg")) || (!strcmp(cfg.audio.codec, "opus")))
280 {
281 fl_g->choice_cfg_bitrate->deactivate();
282 fl_g->choice_cfg_samplerate->deactivate();
283 fl_g->choice_cfg_channel->deactivate();
284 }
285
286 //Changing the sample rate while streaming does not work with aac
287 if(!strcmp(cfg.audio.codec, "aac"))
288 {
289 fl_g->choice_cfg_samplerate->deactivate();
290 }
291
292 pa_new_frames = 0;
293
294 //Just in case the record routine started a check_time timeout
295 //already
296 Fl::remove_timeout(&display_info_timer);
297
298 Fl::add_timeout(0.1, &display_info_timer);
299 Fl::add_timeout(0.1, &is_connected_timer);
300
301 if(cfg.main.song_update)
302 {
303 static int reset = 1;
304 Fl::remove_timeout(&songfile_timer);
305 Fl::add_timeout(0.5, &songfile_timer, &reset);
306 }
307
308 if(cfg.main.app_update)
309 {
310 static int reset = 1;
311 current_track_app = getCurrentTrackFunctionFromId(cfg.main.app_update_service);
312 Fl::remove_timeout(&app_timer);
313 Fl::add_timeout(0.5, &app_timer, &reset);
314 }
315
316 if(cfg.main.silence_threshold > 0)
317 Fl::add_timeout(1, &stream_silence_timer);
318
319
320 snd_start_stream();
321
322 if(cfg.rec.start_rec && !recording)
323 {
324 button_record_cb();
325 timer_init(&rec_timer, 1);
326 }
327
328 snprintf(text_buf, sizeof(text_buf), _("Connected to: %s"), cfg.srv[cfg.selected_srv]->name);
329 fl_g->window_main->label(text_buf);
330
331 display_info = STREAM_TIME;
332 }
333
button_cfg_cb(void)334 void button_cfg_cb(void)
335 {
336
337 if(fl_g->window_cfg->shown())
338 {
339 fl_g->window_cfg->hide();
340 Fl::remove_timeout(&cfg_win_pos_timer);
341 }
342 else
343 {
344
345 /*
346 * This is a bit stupid. Well, its Win32...
347 * We need to place the cfg window a bit more to the right, otherwise
348 * the main and the cfg window would overlap
349 */
350
351 #ifdef WIN32
352 fl_g->window_cfg->position(fl_g->window_main->x() +
353 fl_g->window_main->w()+0,
354 fl_g->window_main->y());
355 #else
356 fl_g->window_cfg->position(fl_g->window_main->x() +
357 fl_g->window_main->w(),
358 fl_g->window_main->y());
359 #endif
360 fl_g->window_cfg->show();
361 fill_cfg_widgets();
362
363 if(cfg.gui.attach)
364 Fl::add_timeout(0.1, &cfg_win_pos_timer);
365 }
366 }
367
368 // add server
button_add_srv_add_cb(void)369 void button_add_srv_add_cb(void)
370 {
371 int i;
372
373 //error checking
374 if((fl_g->radio_add_srv_icecast->value()) && (strlen(fl_g->input_add_srv_mount->value()) == 0))
375 {
376 fl_alert(_("No mountpoint specified\nSetting mountpoint to \"stream\""));
377 fl_g->input_add_srv_mount->value("stream");
378 }
379 if((fl_g->radio_add_srv_icecast->value()) && (strlen(fl_g->input_add_srv_usr->value()) == 0))
380 {
381 fl_alert(_("No user specified\nSetting user to \"source\""));
382 fl_g->input_add_srv_usr->value("source");
383 }
384 if(strlen(fl_g->input_add_srv_name->value()) == 0)
385 {
386 fl_alert(_("No name specified"));
387 return;
388 }
389 if(cfg.main.srv_ent != NULL)
390 {
391 if(strlen(fl_g->input_add_srv_name->value()) + strlen(cfg.main.srv_ent) > 1000)
392 {
393 fl_alert(_("The number of characters of all your server names exeeds 1000\n"
394 "Please reduce the number of characters of each server name"));
395 return;
396 }
397 }
398 if(strpbrk(fl_g->input_add_srv_name->value(), ";\\/\n\r") != NULL)
399 {
400 fl_alert(_("No newline characters and ;/\\ are allowed in the name field"));
401 return;
402 }
403 if(strlen(fl_g->input_add_srv_addr->value()) == 0)
404 {
405 fl_alert(_("No address specified"));
406 return;
407 }
408 if(strlen(fl_g->input_add_srv_pwd->value()) == 0)
409 {
410 fl_alert(_("No password specified"));
411 return;
412 }
413 if(strlen(fl_g->input_add_srv_port->value()) == 0)
414 {
415 fl_alert(_("No port specified"));
416 return;
417 }
418 else if((atoi(fl_g->input_add_srv_port->value()) > 65535) ||
419 (atoi(fl_g->input_add_srv_port->value()) < 1) )
420 {
421 fl_alert(_("Invalid port number\nThe port number must be between 1 and 65535"));
422 return;
423
424 }
425
426 //check if the name already exists
427 for(i = 0; i < cfg.main.num_of_srv; i++)
428 {
429 if(!strcmp(fl_g->input_add_srv_name->value(), cfg.srv[i]->name))
430 {
431 fl_alert(_("Server name already exist!"));
432 return;
433 }
434 }
435
436 i = cfg.main.num_of_srv;
437 cfg.main.num_of_srv++;
438
439 cfg.srv = (server_t**)realloc(cfg.srv, cfg.main.num_of_srv * sizeof(server_t*));
440 cfg.srv[i] = (server_t*)malloc(sizeof(server_t));
441
442 cfg.srv[i]->name = (char*)malloc(strlen(fl_g->input_add_srv_name->value())+1);
443 strcpy(cfg.srv[i]->name, fl_g->input_add_srv_name->value());
444
445 cfg.srv[i]->addr = (char*)malloc(strlen(fl_g->input_add_srv_addr->value())+1);
446 strcpy(cfg.srv[i]->addr, fl_g->input_add_srv_addr->value());
447
448 cfg.srv[i]->cert_hash = NULL;
449
450 //strip leading http:// from addr
451 if(strstr(cfg.srv[i]->addr, "http://"))
452 cfg.srv[i]->addr += strlen("http://");
453 if(strstr(cfg.srv[i]->addr, "https://"))
454 cfg.srv[i]->addr += strlen("https://");
455
456 cfg.srv[i]->pwd = (char*)malloc(strlen(fl_g->input_add_srv_pwd->value())+1);
457 strcpy(cfg.srv[i]->pwd, fl_g->input_add_srv_pwd->value());
458
459 cfg.srv[i]->port = atoi(fl_g->input_add_srv_port->value());
460
461 if(fl_g->radio_add_srv_icecast->value())
462 {
463 cfg.srv[i]->mount = (char*)malloc(strlen(fl_g->input_add_srv_mount->value())+1);
464 strcpy(cfg.srv[i]->mount, fl_g->input_add_srv_mount->value());
465
466 cfg.srv[i]->usr = (char*)malloc(strlen(fl_g->input_add_srv_usr->value())+1);
467 strcpy(cfg.srv[i]->usr, fl_g->input_add_srv_usr->value());
468
469 cfg.srv[i]->type = ICECAST;
470 }
471 else
472 {
473 cfg.srv[i]->mount = NULL;
474 cfg.srv[i]->usr = NULL;
475 cfg.srv[i]->type = SHOUTCAST;
476 }
477
478 cfg.srv[i]->tls = fl_g->check_add_srv_tls->value();
479
480 if(cfg.main.num_of_srv > 1)
481 {
482 cfg.main.srv_ent = (char*)realloc(cfg.main.srv_ent,
483 strlen(cfg.main.srv_ent) +
484 strlen(cfg.srv[i]->name) +2);
485 sprintf(cfg.main.srv_ent, "%s;%s", cfg.main.srv_ent, cfg.srv[i]->name);
486 }
487 else
488 {
489 cfg.main.srv_ent = (char*)malloc(strlen(cfg.srv[i]->name) +1);
490 sprintf(cfg.main.srv_ent, "%s", cfg.srv[i]->name);
491 }
492
493 cfg.main.srv = (char*)realloc(cfg.main.srv, strlen(cfg.srv[i]->name)+1);
494
495 strcpy(cfg.main.srv, cfg.srv[i]->name);
496
497 //reset the input fields and hide the window
498 fl_g->input_add_srv_name->value("");
499 fl_g->input_add_srv_addr->value("");
500 fl_g->input_add_srv_port->value("");
501 fl_g->input_add_srv_pwd->value("");
502 fl_g->input_add_srv_mount->value("");
503 fl_g->input_add_srv_usr->value("");
504 fl_g->window_add_srv->hide();
505 fl_g->check_add_srv_tls->value(0);
506
507 fl_g->choice_cfg_act_srv->add(cfg.srv[i]->name);
508 fl_g->choice_cfg_act_srv->redraw();
509
510 //Activate del and edit buttons
511 fl_g->button_cfg_edit_srv->activate();
512 fl_g->button_cfg_del_srv->activate();
513
514 fl_g->choice_cfg_act_srv->activate();
515
516 // make added server the active server
517 fl_g->choice_cfg_act_srv->value(i);
518 choice_cfg_act_srv_cb();
519
520 }
521
button_cfg_del_srv_cb(void)522 void button_cfg_del_srv_cb(void)
523 {
524 int i;
525 int diff;
526
527 if(cfg.main.num_of_srv == 0)
528 return;
529
530 diff = cfg.main.num_of_srv-1 - cfg.selected_srv;
531
532 for(i = 0; i < diff; i++)
533 {
534 memcpy(cfg.srv[cfg.selected_srv+i], cfg.srv[cfg.selected_srv+i+1],
535 sizeof(server_t));
536 }
537
538 free(cfg.srv[cfg.main.num_of_srv-1]);
539
540 cfg.main.num_of_srv--;
541
542 //rearrange the string that contains all server names
543 memset(cfg.main.srv_ent, 0, strlen(cfg.main.srv_ent));
544 for(i = 0; i < (int)cfg.main.num_of_srv; i++)
545 {
546 strcat(cfg.main.srv_ent, cfg.srv[i]->name);
547
548 //the last entry doesn't have a trailing seperator ";"
549 if(i < (int)cfg.main.num_of_srv-1)
550 strcat(cfg.main.srv_ent, ";");
551
552 }
553
554 fl_g->choice_cfg_act_srv->remove(cfg.selected_srv);
555 fl_g->choice_cfg_act_srv->redraw(); //Yes we need this :-(
556
557 if(cfg.main.num_of_srv == 0)
558 {
559 fl_g->button_cfg_edit_srv->deactivate();
560 fl_g->button_cfg_del_srv->deactivate();
561 fl_g->choice_cfg_act_srv->deactivate();
562 }
563
564 if(cfg.selected_srv > 0)
565 cfg.selected_srv--;
566 else
567 cfg.selected_srv = 0;
568
569 if(cfg.main.num_of_srv > 0)
570 {
571 fl_g->choice_cfg_act_srv->value(cfg.selected_srv);
572 choice_cfg_act_srv_cb();
573 }
574 }
575
button_cfg_del_icy_cb(void)576 void button_cfg_del_icy_cb(void)
577 {
578 int i;
579 int diff;
580
581 if(cfg.main.num_of_icy == 0)
582 return;
583
584 diff = cfg.main.num_of_icy-1 - cfg.selected_icy;
585
586 for(i = 0; i < diff; i++)
587 {
588 memcpy(cfg.icy[cfg.selected_icy+i], cfg.icy[cfg.selected_icy+i+1],
589 sizeof(icy_t));
590 }
591
592 free(cfg.icy[cfg.main.num_of_icy-1]);
593
594 cfg.main.num_of_icy--;
595
596 //rearrange the string that contains all ICY names
597 memset(cfg.main.icy_ent, 0, strlen(cfg.main.icy_ent));
598 for(i = 0; i < (int)cfg.main.num_of_icy; i++)
599 {
600 strcat(cfg.main.icy_ent, cfg.icy[i]->name);
601
602 //the last entry doesn't have a trailing seperator ";"
603 if(i < (int)cfg.main.num_of_icy-1)
604 strcat(cfg.main.icy_ent, ";");
605 }
606
607
608 fl_g->choice_cfg_act_icy->remove(cfg.selected_icy);
609 fl_g->choice_cfg_act_icy->redraw();
610
611 if(cfg.main.num_of_icy == 0)
612 {
613 fl_g->button_cfg_edit_icy->deactivate();
614 fl_g->button_cfg_del_icy->deactivate();
615 fl_g->choice_cfg_act_icy->deactivate();
616 }
617
618 if(cfg.selected_icy > 0)
619 cfg.selected_icy--;
620 else
621 cfg.selected_icy = 0;
622
623 if(cfg.main.num_of_icy > 0)
624 {
625 fl_g->choice_cfg_act_icy->value(cfg.selected_icy);
626 choice_cfg_act_icy_cb();
627 }
628 }
629
button_disconnect_cb(void)630 void button_disconnect_cb(void)
631 {
632
633 if(!connected && recording)
634 stop_recording(true); // true = ask user if recording shall be stopped
635
636 if(connected && recording && cfg.rec.stop_rec)
637 stop_recording(false); // false = do not ask user
638
639 if(!recording)
640 {
641 fl_g->lcd->clear();
642 fl_g->lcd->print((const uchar*)_("idle"), strlen(_("idle")));
643 }
644
645 // We are not trying to connect anymore
646 try_to_connect = 0;
647
648 if(cfg.main.signal_threshold > 0)
649 Fl::add_timeout(1, &stream_signal_timer);
650
651 if(!connected)
652 return;
653
654
655 fl_g->choice_cfg_dev->activate();
656 fl_g->choice_cfg_codec->activate();
657 fl_g->choice_cfg_bitrate->activate();
658 fl_g->choice_cfg_samplerate->activate();
659 fl_g->choice_cfg_channel->activate();
660 fl_g->check_cfg_mono_to_stereo->activate();
661
662
663 if(!recording)
664 Fl::remove_timeout(&display_info_timer);
665 else
666 display_info = REC_TIME;
667
668 Fl::remove_timeout(&songfile_timer);
669 Fl::remove_timeout(&app_timer);
670
671 if(connected)
672 {
673 Fl::remove_timeout(&is_connected_timer);
674 Fl::remove_timeout(&stream_silence_timer);
675 snd_stop_stream();
676
677 if(cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
678 sc_disconnect();
679 else
680 ic_disconnect();
681
682 fl_g->window_main->label(PACKAGE_STRING);
683 }
684 else
685 print_info("Connecting canceled\n", 0);
686
687 }
688
stop_recording(bool ask)689 bool stop_recording(bool ask)
690 {
691 if(!recording)
692 return false;
693
694 if(ask == true)
695 {
696 int rc = 0;
697 rc = fl_choice(_("stop recording?"), _("No"), _("Yes"), NULL);
698 if(rc == 0)//if NO pressed
699 return false;
700 }
701
702 Fl::remove_timeout(&split_recording_timer);
703 Fl::remove_timeout(&record_silence_timer);
704 snd_stop_rec();
705
706 // Let the user change record settings after stopping the recording
707 fl_g->choice_rec_codec->activate();
708 fl_g->choice_rec_bitrate->activate();
709
710 if(!connected)
711 {
712 fl_g->choice_cfg_channel->activate();
713 fl_g->choice_cfg_dev->activate();
714 fl_g->choice_cfg_samplerate->activate();
715
716 fl_g->lcd->clear();
717 fl_g->lcd->print((const uchar*)_("idle"), strlen(_("idle")));
718 Fl::remove_timeout(&display_info_timer);
719 }
720 else
721 display_info = STREAM_TIME;
722
723 if (cfg.rec.signal_threshold > 0)
724 Fl::add_timeout(1, &record_signal_timer);
725
726 return true;
727 }
728
button_record_cb(void)729 void button_record_cb(void)
730 {
731 int i;
732 int rc = 0;
733 int cancel = 0;
734 static int with_repeat = 1;
735 char mode[3];
736 char i_str[12];
737 bool index = 0;
738 char *path_with_placeholder = NULL;
739 char *path_for_index_loop = NULL;
740 char *path_for_index_loop_fmt = NULL;
741 char *path_without_split_time = NULL;
742 FILE *fd;
743
744 struct tm *local_time;
745
746 const time_t t = time(NULL);
747
748 if(recording)
749 {
750 stop_recording(true);
751 return;
752 }
753
754 if(strlen(cfg.rec.filename) == 0)
755 {
756 fl_alert(_("No recording filename specified"));
757 return;
758 }
759
760
761 cfg.rec.path = (char*) malloc((strlen(cfg.rec.folder) +
762 strlen(cfg.rec.filename)) * sizeof(char) + 10);
763
764 strcpy(cfg.rec.path, cfg.rec.folder);
765 strcat(cfg.rec.path, cfg.rec.filename);
766
767 cfg.rec.path_fmt = strdup(cfg.rec.path);
768
769 //expand string like file_%d_%m_%y to file_05_11_2014
770 expand_string(&cfg.rec.path);
771
772 //check if there is an index marker in the filename
773 if(strstr(cfg.rec.filename, "%i"))
774 {
775 index = 1;
776
777 path_with_placeholder = strdup(cfg.rec.path);
778 path_for_index_loop = strdup(cfg.rec.path);
779 path_for_index_loop_fmt = strdup(cfg.rec.path_fmt);
780
781 strrpl(&cfg.rec.path, (char*)"%i", (char*)"1", MODE_ALL);
782 strrpl(&cfg.rec.path_fmt, (char*)"%i", (char*)"1", MODE_ALL);
783 }
784 path_without_split_time = strdup(cfg.rec.path);
785
786
787 //check if the file already exists
788 if((fd = fl_fopen(cfg.rec.path, "rb")) != NULL)
789 {
790 fclose(fd);
791
792 if(index)
793 {
794 //increment the index until we find a filename that doesn't exist yet
795 for(i = 2; /*inf*/; i++) // index_loop
796 {
797 free(cfg.rec.path);
798 free(cfg.rec.path_fmt);
799 cfg.rec.path = strdup(path_for_index_loop);
800 cfg.rec.path_fmt = strdup(path_for_index_loop_fmt);
801 snprintf(i_str, sizeof(i_str), "%d", i);
802 strrpl(&cfg.rec.path, (char*)"%i", i_str, MODE_ALL);
803 strrpl(&cfg.rec.path_fmt, (char*)"%i", i_str, MODE_ALL);
804
805 path_without_split_time = strdup(path_with_placeholder);
806 strrpl(&path_without_split_time, (char*)"%i", i_str, MODE_ALL);
807
808 if((fd = fl_fopen(cfg.rec.path, "rb")) == NULL)
809 break;
810
811 fclose(fd);
812
813 if (i == 0x7FFFFFFF) // 2^31-1
814 {
815 free(path_for_index_loop);
816 free(path_for_index_loop_fmt);
817 free(path_without_split_time);
818 if (path_with_placeholder != NULL)
819 free(path_with_placeholder);
820
821 print_info(_("Could not find a valid filename"), 0);
822 return;
823 }
824
825 }
826 free(path_for_index_loop);
827 free(path_for_index_loop_fmt);
828 strcpy(mode, "wb");
829 }
830 else
831 {
832 rc = fl_choice(_("%s already exists!"),
833 _("cancel"), _("overwrite"), _("append"), cfg.rec.path);
834 switch(rc)
835 {
836 case 0: //cancel pressed
837 cancel = 1;
838 break;
839 case 1: //overwrite pressed
840 strcpy(mode, "wb");
841 break;
842 case 2: //append pressed
843 strcpy(mode, "ab");
844 }
845 }
846 }
847 else //selected file doesn't exist yet
848 {
849 strcpy(mode, "wb");
850 if (path_for_index_loop != NULL)
851 free(path_for_index_loop);
852 if (path_for_index_loop_fmt != NULL)
853 free(path_for_index_loop_fmt);
854 }
855 if (path_with_placeholder != NULL)
856 free(path_with_placeholder);
857
858
859 if(cancel == 1)
860 {
861 if (path_without_split_time != NULL)
862 free(path_without_split_time);
863 return;
864 }
865
866 if((cfg.rec.fd = fl_fopen(cfg.rec.path, mode)) == NULL)
867 {
868 fl_alert(_("Could not open:\n%s"), cfg.rec.path);
869 if (path_without_split_time != NULL)
870 free(path_without_split_time);
871 return;
872 }
873
874 record = 1;
875 timer_init(&rec_timer, 1);
876
877
878 //Clear libsamplerate state
879 snd_reset_samplerate_conv(SND_REC);
880
881 // Allow the flac codec to access the file pointed to by cfg.rec.fd
882 if (!strcmp(cfg.rec.codec, "flac"))
883 {
884 flac_enc_init(&flac_rec);
885 flac_enc_init_FILE(&flac_rec, cfg.rec.fd);
886 }
887
888 // User may not change any record related audio settings while recording
889 fl_g->choice_rec_codec->deactivate();
890 fl_g->choice_rec_bitrate->deactivate();
891 fl_g->choice_cfg_channel->deactivate();
892 fl_g->choice_cfg_dev->deactivate();
893 fl_g->choice_cfg_samplerate->deactivate();
894
895 //create the recording thread
896 snd_start_rec();
897
898 if (cfg.rec.split_time > 0)
899 {
900 free(cfg.rec.path);
901 cfg.rec.path = strdup(path_without_split_time);
902
903 local_time = localtime(&t);
904
905 // Make sure that the 60 minutes boundary is not violated in case
906 // sync_to_hour == 1
907 if((cfg.rec.sync_to_hour == 1) && ((local_time->tm_min + cfg.rec.split_time) > 60))
908 Fl::add_timeout(60*(60 - local_time->tm_min), &split_recording_timer, &with_repeat);
909 else
910 Fl::add_timeout(60*cfg.rec.split_time, &split_recording_timer, &with_repeat);
911
912 }
913
914 if (cfg.rec.silence_threshold > 0)
915 Fl::add_timeout(1, &record_silence_timer);
916
917 Fl::remove_timeout(&record_signal_timer);
918
919
920 if(!connected)
921 {
922 display_info = REC_TIME;
923 Fl::add_timeout(0.1, &display_info_timer);
924 }
925 if (path_without_split_time != NULL)
926 free(path_without_split_time);
927 }
928
button_info_cb()929 void button_info_cb() //changed "Info" text to "More"
930 {
931 if (!fl_g->info_visible)
932 {
933 // Show info output...
934 fl_g->window_main->resize(fl_g->window_main->x(),
935 fl_g->window_main->y(),
936 fl_g->window_main->w(),
937 fl_g->info_output->y() + 185);
938 fl_g->info_output->show();
939 fl_g->button_info->label(_("Hide log"));
940 fl_g->info_visible = 1;
941 }
942 else
943 {
944 // Hide info output...
945 fl_g->window_main->resize(fl_g->window_main->x(),
946 fl_g->window_main->y(),
947 fl_g->window_main->w(),
948 fl_g->info_output->y() - 30);
949 fl_g->info_output->hide();
950 fl_g->button_info->label(_("Show log"));
951 fl_g->info_visible = 0;
952 }
953 }
954
choice_cfg_act_srv_cb(void)955 void choice_cfg_act_srv_cb(void)
956 {
957 cfg.selected_srv = fl_g->choice_cfg_act_srv->value();
958
959 cfg.main.srv = (char*)realloc(cfg.main.srv,
960 strlen(cfg.srv[cfg.selected_srv]->name)+1);
961
962 strcpy(cfg.main.srv, cfg.srv[cfg.selected_srv]->name);
963
964 }
965
choice_cfg_act_icy_cb(void)966 void choice_cfg_act_icy_cb(void)
967 {
968 cfg.selected_icy = fl_g->choice_cfg_act_icy->value();
969
970 cfg.main.icy = (char*)realloc(cfg.main.icy,
971 strlen(cfg.icy[cfg.selected_icy]->name)+1);
972
973 strcpy(cfg.main.icy, cfg.icy[cfg.selected_icy]->name);
974 }
975
button_cfg_add_srv_cb(void)976 void button_cfg_add_srv_cb(void)
977 {
978 fl_g->window_add_srv->label(_("Add Server"));
979 fl_g->radio_add_srv_shoutcast->setonly();
980 fl_g->input_add_srv_mount->deactivate();
981 fl_g->input_add_srv_usr->deactivate();
982
983 fl_g->check_add_srv_tls->deactivate();
984 fl_g->frame_add_srv_tls->deactivate();
985 fl_g->button_add_srv_revoke_cert->deactivate();
986
987 fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT);
988 fl_g->input_add_srv_pwd->redraw();
989 fl_g->button_cfg_show_pw->label(_("Show"));
990
991 fl_g->button_add_srv_save->hide();
992 fl_g->button_add_srv_add->show();
993
994 fl_g->window_add_srv->position(fl_g->window_cfg->x(), fl_g->window_cfg->y());
995 fl_g->input_add_srv_name->take_focus();
996 fl_g->window_add_srv->show();
997 }
998
button_cfg_edit_srv_cb(void)999 void button_cfg_edit_srv_cb(void)
1000 {
1001
1002 char dummy[10];
1003 int srv;
1004
1005 if(cfg.main.num_of_srv < 1)
1006 return;
1007
1008 fl_g->window_add_srv->label(_("Edit Server"));
1009
1010 srv = fl_g->choice_cfg_act_srv->value();
1011
1012 fl_g->input_add_srv_name->value(cfg.srv[srv]->name);
1013 fl_g->input_add_srv_addr->value(cfg.srv[srv]->addr);
1014
1015 snprintf(dummy, 6, "%u", cfg.srv[srv]->port);
1016 fl_g->input_add_srv_port->value(dummy);
1017 fl_g->input_add_srv_pwd->value(cfg.srv[srv]->pwd);
1018
1019 fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT);
1020 fl_g->input_add_srv_pwd->redraw();
1021 fl_g->button_cfg_show_pw->label(_("Show"));
1022
1023
1024 if(cfg.srv[srv]->type == SHOUTCAST)
1025 {
1026 fl_g->input_add_srv_mount->value("");
1027 fl_g->input_add_srv_mount->deactivate();
1028 fl_g->input_add_srv_usr->value("");
1029 fl_g->input_add_srv_usr->deactivate();
1030 fl_g->check_add_srv_tls->deactivate();
1031 fl_g->frame_add_srv_tls->deactivate();
1032 fl_g->button_add_srv_revoke_cert->deactivate();
1033 fl_g->radio_add_srv_shoutcast->setonly();
1034 }
1035 else //if(cfg.srv[srv]->type == ICECAST)
1036 {
1037 fl_g->input_add_srv_mount->value(cfg.srv[srv]->mount);
1038 fl_g->input_add_srv_mount->activate();
1039 fl_g->input_add_srv_usr->value(cfg.srv[srv]->usr);
1040 fl_g->input_add_srv_usr->activate();
1041 fl_g->radio_add_srv_icecast->setonly();
1042 #ifdef HAVE_LIBSSL
1043 fl_g->check_add_srv_tls->activate();
1044 fl_g->frame_add_srv_tls->activate();
1045 #else
1046 fl_g->check_add_srv_tls->deactivate();
1047 fl_g->frame_add_srv_tls->deactivate();
1048 #endif
1049
1050 if ( (cfg.srv[srv]->cert_hash != NULL) && (strlen(cfg.srv[srv]->cert_hash) == 64) )
1051 fl_g->button_add_srv_revoke_cert->activate();
1052 else
1053 fl_g->button_add_srv_revoke_cert->deactivate();
1054 }
1055
1056 fl_g->check_add_srv_tls->value(cfg.srv[srv]->tls);
1057
1058 fl_g->input_add_srv_name->take_focus();
1059
1060 fl_g->button_add_srv_add->hide();
1061 fl_g->button_add_srv_save->show();
1062
1063 fl_g->window_add_srv->position(fl_g->window_cfg->x(), fl_g->window_cfg->y());
1064 fl_g->window_add_srv->show();
1065 }
1066
1067
button_cfg_add_icy_cb(void)1068 void button_cfg_add_icy_cb(void)
1069 {
1070 fl_g->window_add_icy->label(_("Add Server Infos"));
1071
1072 fl_g->button_add_icy_save->hide();
1073 fl_g->button_add_icy_add->show();
1074 fl_g->window_add_icy->position(fl_g->window_cfg->x(), fl_g->window_cfg->y());
1075
1076 //give the "name" input field the input focus
1077 fl_g->input_add_icy_name->take_focus();
1078
1079 fl_g->window_add_icy->show();
1080 }
1081
1082
update_song(int called_from_connect_cb)1083 void update_song(int called_from_connect_cb)
1084 {
1085 static int is_updating = 0;
1086
1087 int prefix_len = 0;
1088 int suffix_len = 0;
1089 char text_buf[512];
1090 char song_buf[512];
1091 song_buf[0] = '\0';
1092
1093 int (*xc_update_song)(char *song_name) = NULL;
1094
1095
1096 if(!connected || cfg.main.song == NULL)
1097 return;
1098
1099
1100 // Make sure this function is not executed from different places at the same time
1101 if (is_updating == 1)
1102 return;
1103
1104 is_updating = 1;
1105
1106
1107 if (cfg.main.song_prefix != NULL)
1108 {
1109 prefix_len = strlen(cfg.main.song_prefix);
1110 strncat(song_buf, cfg.main.song_prefix, sizeof(song_buf)-1);
1111 }
1112
1113 strncat(song_buf, cfg.main.song, sizeof(song_buf)-1 - prefix_len);
1114
1115 if (cfg.main.song_suffix != NULL)
1116 {
1117 suffix_len = strlen(cfg.main.song_suffix);
1118 strncat(song_buf, cfg.main.song_suffix, sizeof(song_buf)-1 - prefix_len - suffix_len);
1119 }
1120
1121
1122 if (!strcmp(cfg.audio.codec, "flac"))
1123 {
1124 if (called_from_connect_cb == 0)
1125 flac_update_song_title(&flac_stream, song_buf);
1126 else
1127 flac_set_initial_song_title(&flac_stream, song_buf);
1128 }
1129
1130 if (cfg.srv[cfg.selected_srv]->type == SHOUTCAST)
1131 xc_update_song = &sc_update_song;
1132 else //if(cfg.srv[cfg.selected_srv]->type == ICECAST)
1133 xc_update_song = &ic_update_song;
1134
1135 if (xc_update_song(song_buf) == 0)
1136 {
1137 snprintf(text_buf, sizeof(text_buf),
1138 _("Updated songname to:\n%s\n"),
1139 song_buf);
1140
1141 print_info(text_buf, 0);
1142 }
1143 else
1144 print_info(_("Updating songname failed"), 1);
1145
1146 is_updating = 0;
1147
1148 }
1149
button_cfg_song_go_cb(void)1150 void button_cfg_song_go_cb(void)
1151 {
1152 cfg.main.song = (char*)realloc(cfg.main.song, strlen(fl_g->input_cfg_song->value())+1);
1153 strcpy(cfg.main.song, fl_g->input_cfg_song->value());
1154
1155 update_song(0);
1156
1157 // Set focus on the song input field and mark the whole text
1158 fl_g->input_cfg_song->take_focus();
1159 fl_g->input_cfg_song->position(0);
1160 fl_g->input_cfg_song->mark(fl_g->input_cfg_song->maximum_size());
1161 }
1162
input_cfg_song_cb(void)1163 void input_cfg_song_cb(void)
1164 {
1165 if (strlen(fl_g->input_cfg_song->value()) == 0)
1166 {
1167 if (cfg.main.song != NULL)
1168 free(cfg.main.song);
1169
1170 cfg.main.song = NULL;
1171 }
1172 }
1173
input_cfg_song_prefix_cb(void)1174 void input_cfg_song_prefix_cb(void)
1175 {
1176 if (strlen(fl_g->input_cfg_song_prefix->value()) == 0)
1177 {
1178 if (cfg.main.song_prefix != NULL)
1179 free(cfg.main.song_prefix);
1180
1181 cfg.main.song_prefix = NULL;
1182 }
1183 else
1184 {
1185 cfg.main.song_prefix = (char*)realloc(cfg.main.song_prefix, strlen(fl_g->input_cfg_song_prefix->value())+1);
1186 strcpy(cfg.main.song_prefix, fl_g->input_cfg_song_prefix->value());
1187 }
1188 }
input_cfg_song_suffix_cb(void)1189 void input_cfg_song_suffix_cb(void)
1190 {
1191 if (strlen(fl_g->input_cfg_song_suffix->value()) == 0)
1192 {
1193 if (cfg.main.song_suffix != NULL)
1194 free(cfg.main.song_suffix);
1195
1196 cfg.main.song_suffix = NULL;
1197 }
1198 else
1199 {
1200 cfg.main.song_suffix = (char*)realloc(cfg.main.song_suffix, strlen(fl_g->input_cfg_song_suffix->value())+1);
1201 strcpy(cfg.main.song_suffix, fl_g->input_cfg_song_suffix->value());
1202 }
1203 }
1204
input_cfg_buffer_cb(bool print_message)1205 void input_cfg_buffer_cb(bool print_message)
1206 {
1207 int ms;
1208 char text_buf[256];
1209
1210 ms = fl_g->input_cfg_buffer->value();
1211
1212 if(ms < 1)
1213 return;
1214
1215 cfg.audio.buffer_ms = ms;
1216 snd_reinit();
1217
1218 if(print_message)
1219 {
1220 snprintf(text_buf, sizeof(text_buf),
1221 _("Audio buffer has been set to %d ms"), ms);
1222 print_info(text_buf, 0);
1223 }
1224 }
1225
choice_cfg_resample_mode_cb(void)1226 void choice_cfg_resample_mode_cb(void)
1227 {
1228 cfg.audio.resample_mode = fl_g->choice_cfg_resample_mode->value();
1229 snd_reinit();
1230 switch(cfg.audio.resample_mode)
1231 {
1232 case SRC_SINC_BEST_QUALITY:
1233 print_info("Changed resample quality to SINC_BEST_QUALITY", 0);
1234 break;
1235 case SRC_SINC_MEDIUM_QUALITY:
1236 print_info("Changed resample quality to SINC_MEDIUM_QUALITY", 0);
1237 break;
1238 case SRC_SINC_FASTEST:
1239 print_info("Changed resample quality to SINC_FASTEST", 0);
1240 break;
1241 case SRC_ZERO_ORDER_HOLD:
1242 print_info("Changed resample quality to ZERO_ORDER_HOLD", 0);
1243 break;
1244 case SRC_LINEAR:
1245 print_info("Changed resample quality to LINEAR", 0);
1246 break;
1247 default:
1248 break;
1249 }
1250
1251 }
1252
radio_add_srv_shoutcast_cb(void)1253 void radio_add_srv_shoutcast_cb(void)
1254 {
1255 fl_g->input_add_srv_mount->deactivate();
1256 fl_g->input_add_srv_usr->deactivate();
1257 fl_g->check_add_srv_tls->deactivate();
1258 fl_g->frame_add_srv_tls->deactivate();
1259 }
1260
radio_add_srv_icecast_cb(void)1261 void radio_add_srv_icecast_cb(void)
1262 {
1263 fl_g->input_add_srv_mount->activate();
1264 fl_g->input_add_srv_usr->activate();
1265
1266 fl_g->input_add_srv_mount->value("stream");
1267 fl_g->input_add_srv_usr->value("source");
1268
1269 #ifdef HAVE_LIBSSL
1270 fl_g->check_add_srv_tls->activate();
1271 fl_g->frame_add_srv_tls->activate();
1272 #else
1273 fl_g->check_add_srv_tls->deactivate();
1274 fl_g->frame_add_srv_tls->deactivate();
1275 #endif
1276
1277 }
1278
button_add_srv_show_pwd_cb(void)1279 void button_add_srv_show_pwd_cb(void)
1280 {
1281 if(fl_g->input_add_srv_pwd->input_type() == FL_SECRET_INPUT)
1282 {
1283 fl_g->input_add_srv_pwd->input_type(FL_NORMAL_INPUT);
1284 fl_g->input_add_srv_pwd->redraw();
1285 fl_g->button_cfg_show_pw->label(_("Hide"));
1286 }
1287 else
1288 {
1289 fl_g->input_add_srv_pwd->input_type(FL_SECRET_INPUT);
1290 fl_g->input_add_srv_pwd->redraw();
1291 fl_g->button_cfg_show_pw->label(_("Show"));
1292 }
1293 }
1294
button_add_srv_revoke_cert_cb(void)1295 void button_add_srv_revoke_cert_cb(void)
1296 {
1297 int srv;
1298 srv = fl_g->choice_cfg_act_srv->value();
1299
1300 if (cfg.srv[srv]->cert_hash != NULL)
1301 {
1302 free(cfg.srv[srv]->cert_hash);
1303 cfg.srv[srv]->cert_hash = NULL;
1304 fl_g->button_add_srv_revoke_cert->deactivate();
1305 }
1306 else
1307 {
1308 fl_alert(_("Could not revoke trust for certificate"));
1309 }
1310 }
1311
1312 // edit server
button_add_srv_save_cb(void)1313 void button_add_srv_save_cb(void)
1314 {
1315 int i;
1316
1317 if(cfg.main.num_of_srv < 1)
1318 return;
1319
1320 int srv_num = fl_g->choice_cfg_act_srv->value();
1321 int len = 0;
1322
1323 //error checking
1324 if((fl_g->radio_add_srv_icecast->value()) && (strlen(fl_g->input_add_srv_mount->value()) == 0))
1325 {
1326 fl_alert(_("No mountpoint specified\nSetting mountpoint to \"stream\""));
1327 fl_g->input_add_srv_mount->value("stream");
1328 }
1329 if((fl_g->radio_add_srv_icecast->value()) && (strlen(fl_g->input_add_srv_usr->value()) == 0))
1330 {
1331 fl_alert(_("No user specified\nSetting user to \"source\""));
1332 fl_g->input_add_srv_usr->value("source");
1333 }
1334 if(strlen(fl_g->input_add_srv_name->value()) == 0)
1335 {
1336 fl_alert(_("No name specified"));
1337 return;
1338 }
1339 if(cfg.main.srv_ent != NULL)
1340 {
1341 if(strlen(fl_g->input_add_srv_name->value()) + strlen(cfg.main.srv_ent) > 1000)
1342 {
1343 fl_alert(_("The number of characters of all your server names exeeds 1000\n"
1344 "Please reduce the number of characters of each server name"));
1345 return;
1346 }
1347 }
1348 if(strpbrk(fl_g->input_add_srv_name->value(), ";\\/\n\r") != NULL)
1349 {
1350 fl_alert(_("No newline characters and ;/\\ are allowed in the name field"));
1351 return;
1352 }
1353 if(strlen(fl_g->input_add_srv_addr->value()) == 0)
1354 {
1355 fl_alert(_("No address specified"));
1356 return;
1357 }
1358 if(strlen(fl_g->input_add_srv_pwd->value()) == 0)
1359 {
1360 fl_alert(_("No password specified"));
1361 return;
1362 }
1363 if(strlen(fl_g->input_add_srv_port->value()) == 0)
1364 {
1365 fl_alert(_("No port specified"));
1366 return;
1367 }
1368 else if(( atoi(fl_g->input_add_srv_port->value()) > 65535) ||
1369 (atoi(fl_g->input_add_srv_port->value()) < 1) )
1370 {
1371 fl_alert(_("Invalid port number\nThe port number must be between 1 and 65535"));
1372 return;
1373 }
1374
1375 //check if the name already exists
1376 for(i = 0; i < cfg.main.num_of_srv; i++)
1377 {
1378 if(i == srv_num) //don't check name against it self
1379 continue;
1380 if(!strcmp(fl_g->input_add_srv_name->value(), cfg.srv[i]->name))
1381 {
1382 fl_alert(_("Server name already exist!"));
1383 return;
1384 }
1385 }
1386
1387
1388 //update current server name
1389 cfg.srv[srv_num]->name =
1390 (char*) realloc(cfg.srv[srv_num]->name,
1391 sizeof(char) * strlen(fl_g->input_add_srv_name->value())+1);
1392
1393 strcpy(cfg.srv[srv_num]->name, fl_g->input_add_srv_name->value());
1394
1395 //rewrite the string that contains all server names
1396 //first get the needed memory space
1397 for(int i = 0; i < cfg.main.num_of_srv; i++)
1398 len += strlen(cfg.srv[i]->name) + 1;
1399 //allocate enough memory
1400 cfg.main.srv_ent = (char*) realloc(cfg.main.srv_ent, sizeof(char)*len +1);
1401
1402 memset(cfg.main.srv_ent, 0, len);
1403 //now append the server strings
1404 for(int i = 0; i < cfg.main.num_of_srv; i++)
1405 {
1406 strcat(cfg.main.srv_ent, cfg.srv[i]->name);
1407 if(i < cfg.main.num_of_srv-1)
1408 strcat(cfg.main.srv_ent, ";");
1409 }
1410
1411 //update current server address
1412 cfg.srv[srv_num]->addr =
1413 (char*) realloc(cfg.srv[srv_num]->addr,
1414 sizeof(char) * strlen(fl_g->input_add_srv_addr->value())+1);
1415
1416 strcpy(cfg.srv[srv_num]->addr, fl_g->input_add_srv_addr->value());
1417
1418 //strip leading http:// from addr
1419 if(strstr(cfg.srv[srv_num]->addr, "http://"))
1420 cfg.srv[srv_num]->addr += strlen("http://");
1421 if(strstr(cfg.srv[srv_num]->addr, "https://"))
1422 cfg.srv[srv_num]->addr += strlen("https://");
1423
1424 //update current server port
1425 cfg.srv[srv_num]->port = (unsigned int)atoi(fl_g->input_add_srv_port->value());
1426
1427 //update current server password
1428 cfg.srv[srv_num]->pwd =
1429 (char*) realloc(cfg.srv[srv_num]->pwd,
1430 strlen(fl_g->input_add_srv_pwd->value())+1);
1431
1432 strcpy(cfg.srv[srv_num]->pwd, fl_g->input_add_srv_pwd->value());
1433
1434 //update current server type
1435 if(fl_g->radio_add_srv_shoutcast->value())
1436 cfg.srv[srv_num]->type = SHOUTCAST;
1437 if(fl_g->radio_add_srv_icecast->value())
1438 cfg.srv[srv_num]->type = ICECAST;
1439
1440 //update current server mountpoint and user
1441 if(cfg.srv[srv_num]->type == ICECAST)
1442 {
1443 cfg.srv[srv_num]->mount =
1444 (char*) realloc(cfg.srv[srv_num]->mount,
1445 sizeof(char) * strlen(fl_g->input_add_srv_mount->value())+1);
1446 strcpy(cfg.srv[srv_num]->mount, fl_g->input_add_srv_mount->value());
1447
1448 cfg.srv[srv_num]->usr =
1449 (char*) realloc(cfg.srv[srv_num]->usr,
1450 sizeof(char) * strlen(fl_g->input_add_srv_usr->value())+1);
1451 strcpy(cfg.srv[srv_num]->usr, fl_g->input_add_srv_usr->value());
1452
1453 }
1454
1455 cfg.srv[srv_num]->tls = fl_g->check_add_srv_tls->value();
1456
1457 fl_g->choice_cfg_act_srv->replace(srv_num, cfg.srv[srv_num]->name);
1458 fl_g->choice_cfg_act_srv->redraw();
1459
1460 //reset the input fields and hide the window
1461 fl_g->input_add_srv_name->value("");
1462 fl_g->input_add_srv_addr->value("");
1463 fl_g->input_add_srv_port->value("");
1464 fl_g->input_add_srv_pwd->value("");
1465 fl_g->input_add_srv_mount->value("");
1466 fl_g->input_add_srv_usr->value("");
1467 fl_g->check_add_srv_tls->value(0);
1468
1469 fl_g->window_add_srv->hide();
1470
1471 choice_cfg_act_srv_cb();
1472 }
1473
button_add_icy_save_cb(void)1474 void button_add_icy_save_cb(void)
1475 {
1476 int i;
1477
1478 if(cfg.main.num_of_icy < 1)
1479 return;
1480
1481 int icy_num = fl_g->choice_cfg_act_icy->value();
1482 int len = 0;
1483
1484 if(strlen(fl_g->input_add_icy_name->value()) == 0)
1485 {
1486 fl_alert(_("No name specified"));
1487 return;
1488 }
1489 if(cfg.main.icy_ent != NULL)
1490 {
1491 if(strlen(fl_g->input_add_icy_name->value()) + strlen(cfg.main.icy_ent) > 1000)
1492 {
1493 fl_alert(_("The number of characters of all your icy names exeeds 1000\n"
1494 "Please reduce the count of characters of each icy name"));
1495 return;
1496 }
1497 }
1498 if(strpbrk(fl_g->input_add_icy_name->value(), ";\\/\n\r") != NULL)
1499 {
1500 fl_alert(_("No newline characters and ;/\\ are allowed in the name field"));
1501 return;
1502 }
1503
1504 //check if the name already exists
1505 for(i = 0; i < cfg.main.num_of_icy; i++)
1506 {
1507 if(i == icy_num) //don't check name against it self
1508 continue;
1509 if(!strcmp(fl_g->input_add_icy_name->value(), cfg.icy[i]->name))
1510 {
1511 fl_alert(_("Icy name already exist!"));
1512 return;
1513 }
1514 }
1515
1516 //update current icy name
1517 cfg.icy[icy_num]->name =
1518 (char*) realloc(cfg.icy[icy_num]->name,
1519 sizeof(char) * strlen(fl_g->input_add_icy_name->value())+1);
1520
1521 strcpy(cfg.icy[icy_num]->name, fl_g->input_add_icy_name->value());
1522
1523 //rewrite the string that contains all server names
1524 //first get the needed memory space
1525 for(int i = 0; i < cfg.main.num_of_icy; i++)
1526 len += strlen(cfg.icy[i]->name) + 1;
1527 //reserve enough memory
1528 cfg.main.icy_ent = (char*) realloc(cfg.main.icy_ent, sizeof(char)*len +1);
1529
1530 memset(cfg.main.icy_ent, 0, len);
1531 //now append the server strings
1532 for(int i = 0; i < cfg.main.num_of_icy; i++)
1533 {
1534 strcat(cfg.main.icy_ent, cfg.icy[i]->name);
1535 if(i < cfg.main.num_of_icy-1)
1536 strcat(cfg.main.icy_ent, ";");
1537 }
1538
1539 cfg.icy[icy_num]->desc =
1540 (char*)realloc(cfg.icy[icy_num]->desc,
1541 strlen(fl_g->input_add_icy_desc->value())+1 );
1542 strcpy(cfg.icy[icy_num]->desc, fl_g->input_add_icy_desc->value());
1543
1544 cfg.icy[icy_num]->genre =
1545 (char*)realloc(cfg.icy[icy_num]->genre,
1546 strlen(fl_g->input_add_icy_genre->value())+1 );
1547 strcpy(cfg.icy[icy_num]->genre, fl_g->input_add_icy_genre->value());
1548
1549 cfg.icy[icy_num]->url =
1550 (char*)realloc(cfg.icy[icy_num]->url,
1551 strlen(fl_g->input_add_icy_url->value())+1 );
1552 strcpy(cfg.icy[icy_num]->url, fl_g->input_add_icy_url->value());
1553
1554 cfg.icy[icy_num]->icq =
1555 (char*)realloc(cfg.icy[icy_num]->icq,
1556 strlen(fl_g->input_add_icy_icq->value())+1 );
1557 strcpy(cfg.icy[icy_num]->icq, fl_g->input_add_icy_icq->value());
1558
1559 cfg.icy[icy_num]->irc =
1560 (char*)realloc(cfg.icy[icy_num]->irc,
1561 strlen(fl_g->input_add_icy_irc->value())+1 );
1562 strcpy(cfg.icy[icy_num]->irc, fl_g->input_add_icy_irc->value());
1563
1564 cfg.icy[icy_num]->aim =
1565 (char*)realloc(cfg.icy[icy_num]->aim,
1566 strlen(fl_g->input_add_icy_aim->value())+1 );
1567 strcpy(cfg.icy[icy_num]->aim, fl_g->input_add_icy_aim->value());
1568
1569 sprintf(cfg.icy[icy_num]->pub, "%d", fl_g->check_add_icy_pub->value());
1570
1571 fl_g->input_add_icy_name->value("");
1572 fl_g->input_add_icy_desc->value("");
1573 fl_g->input_add_icy_url->value("");
1574 fl_g->input_add_icy_genre->value("");
1575 fl_g->input_add_icy_irc->value("");
1576 fl_g->input_add_icy_icq->value("");
1577 fl_g->input_add_icy_aim->value("");
1578 fl_g->check_add_icy_pub->value(0);
1579
1580 fl_g->window_add_icy->hide();
1581
1582
1583 fl_g->choice_cfg_act_icy->replace(icy_num, cfg.icy[icy_num]->name);
1584 fl_g->choice_cfg_act_icy->redraw();
1585 choice_cfg_act_icy_cb();
1586 }
1587
1588 /*
1589 void choice_cfg_edit_srv_cb(void)
1590 {
1591 char dummy[10];
1592 int server = fl_g->choice_cfg_edit_srv->value();
1593
1594 fl_g->input_cfg_addr->value(cfg.srv[server]->addr);
1595
1596 snprintf(dummy, 6, "%u", cfg.srv[server]->port);
1597 fl_g->input_cfg_port->value(dummy);
1598 fl_g->input_cfg_passwd->value(cfg.srv[server]->pwd);
1599
1600 if(cfg.srv[server]->type == SHOUTCAST)
1601 {
1602 fl_g->input_cfg_mount->value("");
1603 fl_g->input_cfg_mount->deactivate();
1604 fl_g->radio_cfg_shoutcast->value(1);
1605 fl_g->radio_cfg_icecast->value(0);
1606 }
1607 else //if(cfg.srv[server]->type == ICECAST)
1608 {
1609 fl_g->input_cfg_mount->value(cfg.srv[server]->mount);
1610 fl_g->input_cfg_mount->activate();
1611 fl_g->radio_cfg_icecast->value(1);
1612 fl_g->radio_cfg_shoutcast->value(0);
1613 }
1614 }
1615 */
1616
choice_cfg_bitrate_cb(void)1617 void choice_cfg_bitrate_cb(void)
1618 {
1619 int rc;
1620 int old_br;
1621 int sel_br;
1622 int br_list[] = { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,
1623 112, 128, 160, 192, 224, 256, 320 };
1624 char text_buf[256];
1625
1626 old_br = cfg.audio.bitrate;
1627 for(int i = 0; i < 14; i++)
1628 if(br_list[i] == cfg.audio.bitrate)
1629 old_br = i;
1630
1631 sel_br = fl_g->choice_cfg_bitrate->value();
1632 cfg.audio.bitrate = br_list[sel_br];
1633 lame_stream.bitrate = br_list[sel_br];
1634 vorbis_stream.bitrate = br_list[sel_br];
1635 #ifdef HAVE_LIBFDK_AAC
1636 aac_stream.bitrate = br_list[sel_br];
1637 #endif
1638 opus_stream.bitrate = br_list[sel_br]*1000;
1639
1640
1641 if(fl_g->choice_cfg_codec->value() == CHOICE_MP3)
1642 {
1643 rc = lame_enc_reinit(&lame_stream);
1644 if(rc != 0)
1645 {
1646 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1647 fl_g->choice_cfg_bitrate->value(old_br);
1648 fl_g->choice_cfg_bitrate->redraw();
1649 cfg.audio.bitrate = br_list[old_br];
1650 lame_stream.bitrate = br_list[old_br];
1651 lame_enc_reinit(&lame_stream);
1652 print_info(_("The previous values have been set\n"), 1);
1653 return;
1654 }
1655 }
1656 if(fl_g->choice_cfg_codec->value() == CHOICE_OGG)
1657 {
1658 rc = vorbis_enc_reinit(&vorbis_stream);
1659 if(rc != 0)
1660 {
1661 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1662 cfg.audio.bitrate = br_list[old_br];
1663 vorbis_stream.bitrate = br_list[old_br];
1664 fl_g->choice_cfg_bitrate->value(old_br);
1665 fl_g->choice_cfg_bitrate->redraw();
1666 vorbis_enc_reinit(&vorbis_stream);
1667 print_info(_("The previous values have been set\n"), 1);
1668 return;
1669 }
1670 }
1671
1672 if(fl_g->choice_cfg_codec->value() == CHOICE_OPUS)
1673 {
1674 rc = opus_enc_reinit(&opus_stream);
1675 if(rc != 0)
1676 {
1677 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1678 cfg.audio.bitrate = br_list[old_br];
1679 opus_stream.bitrate = br_list[old_br]*1000;
1680 fl_g->choice_cfg_bitrate->value(old_br);
1681 fl_g->choice_cfg_bitrate->redraw();
1682 opus_enc_reinit(&opus_stream);
1683 print_info(_("The previous values have been set\n"), 1);
1684 return;
1685 }
1686 }
1687
1688 #ifdef HAVE_LIBFDK_AAC
1689 if(fl_g->choice_cfg_codec->value() == CHOICE_AAC)
1690 {
1691 rc = aac_enc_reinit(&aac_stream);
1692 if(rc != 0)
1693 {
1694 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1695 cfg.audio.bitrate = br_list[old_br];
1696 aac_stream.bitrate = br_list[old_br];
1697 fl_g->choice_cfg_bitrate->value(old_br);
1698 fl_g->choice_cfg_bitrate->redraw();
1699 aac_enc_reinit(&aac_stream);
1700 print_info(_("The previous values have been set\n"), 1);
1701 return;
1702 }
1703 }
1704 #endif
1705
1706
1707 snprintf(text_buf, sizeof(text_buf), _("Stream bitrate set to: %dk"), cfg.audio.bitrate);
1708 print_info(text_buf, 0);
1709 }
1710
choice_rec_bitrate_cb(void)1711 void choice_rec_bitrate_cb(void)
1712 {
1713 int rc;
1714 int old_br;
1715 int sel_br;
1716 int br_list[] = { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,
1717 112, 128, 160, 192, 224, 256, 320 };
1718 char text_buf[256];
1719
1720 old_br = cfg.rec.bitrate;
1721 for(int i = 0; i < 14; i++)
1722 if(br_list[i] == cfg.rec.bitrate)
1723 old_br = i;
1724
1725
1726 sel_br = fl_g->choice_rec_bitrate->value();
1727 cfg.rec.bitrate = br_list[sel_br];
1728 lame_rec.bitrate = br_list[sel_br];
1729 vorbis_rec.bitrate = br_list[sel_br];
1730 opus_rec.bitrate = br_list[sel_br]*1000;
1731 #ifdef HAVE_LIBFDK_AAC
1732 aac_rec.bitrate = br_list[sel_br];
1733 #endif
1734
1735
1736 if(fl_g->choice_rec_codec->value() == CHOICE_MP3)
1737 {
1738 rc = lame_enc_reinit(&lame_rec);
1739 if(rc != 0)
1740 {
1741 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1742 cfg.rec.bitrate = br_list[old_br];
1743 fl_g->choice_rec_bitrate->value(old_br);
1744 fl_g->choice_rec_bitrate->redraw();
1745 lame_rec.bitrate = br_list[old_br];
1746 lame_enc_reinit(&lame_rec);
1747 print_info(_("The previous values have been set"), 1);
1748 return;
1749 }
1750 }
1751 if(fl_g->choice_rec_codec->value() == CHOICE_OGG)
1752 {
1753 rc = vorbis_enc_reinit(&vorbis_rec);
1754 if(rc != 0)
1755 {
1756 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1757 cfg.rec.bitrate = br_list[old_br];
1758 vorbis_rec.bitrate = br_list[old_br];
1759 fl_g->choice_rec_bitrate->value(old_br);
1760 fl_g->choice_rec_bitrate->redraw();
1761 vorbis_enc_reinit(&vorbis_rec);
1762 print_info(_("The previous values have been set"), 1);
1763 return;
1764 }
1765 }
1766
1767 if(fl_g->choice_rec_codec->value() == CHOICE_OPUS)
1768 {
1769 rc = opus_enc_reinit(&opus_rec);
1770 if(rc != 0)
1771 {
1772 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1773 cfg.rec.bitrate = br_list[old_br];
1774 opus_rec.bitrate = br_list[old_br]*1000;
1775 fl_g->choice_rec_bitrate->value(old_br);
1776 fl_g->choice_rec_bitrate->redraw();
1777 opus_enc_reinit(&opus_rec);
1778 print_info(_("The previous values have been set"), 1);
1779 return;
1780 }
1781 }
1782
1783 #ifdef HAVE_LIBFDK_AAC
1784 if(fl_g->choice_rec_codec->value() == CHOICE_AAC)
1785 {
1786 rc = aac_enc_reinit(&aac_rec);
1787 if(rc != 0)
1788 {
1789 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1790 cfg.rec.bitrate = br_list[old_br];
1791 aac_rec.bitrate = br_list[old_br];
1792 fl_g->choice_rec_bitrate->value(old_br);
1793 fl_g->choice_rec_bitrate->redraw();
1794 aac_enc_reinit(&aac_rec);
1795 print_info(_("The previous values have been set"), 1);
1796 return;
1797 }
1798 }
1799 #endif
1800
1801 snprintf(text_buf, sizeof(text_buf), _("Record bitrate set to: %dk"), cfg.rec.bitrate);
1802 print_info(text_buf, 0);
1803 }
1804
choice_cfg_samplerate_cb()1805 void choice_cfg_samplerate_cb()
1806 {
1807 int rc;
1808 int old_sr;
1809 int sel_sr;
1810 int *sr_list;
1811 char text_buf[256];
1812
1813 sr_list = cfg.audio.pcm_list[cfg.audio.dev_num]->sr_list;
1814
1815 old_sr = cfg.audio.samplerate;
1816
1817 for(int i = 0; i < 9; i++)
1818 if(sr_list[i] == cfg.audio.samplerate)
1819 old_sr = i;
1820
1821 sel_sr = fl_g->choice_cfg_samplerate->value();
1822
1823
1824 cfg.audio.samplerate = sr_list[sel_sr];
1825
1826 // Reinit streaming codecs
1827 lame_stream.samplerate = sr_list[sel_sr];
1828 vorbis_stream.samplerate = sr_list[sel_sr];
1829 opus_stream.samplerate = sr_list[sel_sr];
1830 #ifdef HAVE_LIBFDK_AAC
1831 aac_stream.samplerate = sr_list[sel_sr];
1832 #endif
1833 flac_stream.samplerate = sr_list[sel_sr];
1834
1835
1836 if(fl_g->choice_cfg_codec->value() == CHOICE_MP3)
1837 {
1838 rc = lame_enc_reinit(&lame_stream);
1839 if(rc != 0)
1840 {
1841 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1842 fl_g->choice_cfg_samplerate->value(old_sr);
1843 fl_g->choice_cfg_samplerate->redraw();
1844 cfg.audio.samplerate = sr_list[old_sr];
1845 lame_stream.samplerate = sr_list[old_sr];
1846 lame_enc_reinit(&lame_stream);
1847 print_info(_("The previous values have been set"), 1);
1848 return;
1849 }
1850 }
1851 if(fl_g->choice_cfg_codec->value() == CHOICE_OGG)
1852 {
1853 rc = vorbis_enc_reinit(&vorbis_stream);
1854 if(rc != 0)
1855 {
1856 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1857 cfg.audio.samplerate = sr_list[old_sr];
1858 vorbis_stream.samplerate = sr_list[old_sr];
1859 fl_g->choice_cfg_samplerate->value(old_sr);
1860 fl_g->choice_cfg_samplerate->redraw();
1861 vorbis_enc_reinit(&vorbis_stream);
1862 print_info(_("The previous values have been set"), 1);
1863 return;
1864 }
1865 }
1866
1867 if(fl_g->choice_cfg_codec->value() == CHOICE_OPUS)
1868 {
1869 rc = opus_enc_reinit(&opus_stream);
1870 if(rc != 0)
1871 {
1872 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1873 cfg.audio.samplerate = sr_list[old_sr];
1874 opus_stream.samplerate = sr_list[old_sr];
1875 fl_g->choice_cfg_samplerate->value(old_sr);
1876 fl_g->choice_cfg_samplerate->redraw();
1877 opus_enc_reinit(&opus_stream);
1878 print_info(_("The previous values have been set"), 1);
1879 return;
1880 }
1881 }
1882
1883 #ifdef HAVE_LIBFDK_AAC
1884 if(fl_g->choice_cfg_codec->value() == CHOICE_AAC)
1885 {
1886 rc = aac_enc_reinit(&aac_stream);
1887 if(rc != 0)
1888 {
1889 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1890 cfg.audio.samplerate = sr_list[old_sr];
1891 aac_stream.samplerate = sr_list[old_sr];
1892 fl_g->choice_cfg_samplerate->value(old_sr);
1893 fl_g->choice_cfg_samplerate->redraw();
1894 aac_enc_reinit(&aac_stream);
1895 print_info(_("The previous values have been set"), 1);
1896 return;
1897 }
1898 }
1899 #endif
1900
1901 if(fl_g->choice_cfg_codec->value() == CHOICE_FLAC)
1902 {
1903 rc = flac_enc_reinit(&flac_stream);
1904 if(rc != 0)
1905 {
1906 print_info(_("Warning:\nThe stream Sample-/Bitrate combination is invalid"), 1);
1907 cfg.audio.samplerate = sr_list[old_sr];
1908 flac_stream.samplerate = sr_list[old_sr];
1909 fl_g->choice_cfg_samplerate->value(old_sr);
1910 fl_g->choice_cfg_samplerate->redraw();
1911 flac_enc_reinit(&flac_stream);
1912 print_info(_("The previous values have been set"), 1);
1913 return;
1914 }
1915 }
1916
1917 //Reinit record codecs
1918 lame_rec.samplerate = sr_list[sel_sr];
1919 vorbis_rec.samplerate = sr_list[sel_sr];
1920 opus_rec.samplerate = sr_list[sel_sr];
1921 #ifdef HAVE_LIBFDK_AAC
1922 aac_rec.samplerate = sr_list[sel_sr];
1923 #endif
1924 flac_rec.samplerate = sr_list[sel_sr];
1925
1926 if(fl_g->choice_rec_codec->value() == CHOICE_MP3)
1927 {
1928 rc = lame_enc_reinit(&lame_rec);
1929 if(rc != 0)
1930 {
1931 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1932 cfg.audio.samplerate = sr_list[old_sr];
1933 lame_stream.samplerate = sr_list[old_sr];
1934 lame_rec.samplerate = sr_list[old_sr];
1935 fl_g->choice_cfg_samplerate->value(old_sr);
1936 fl_g->choice_cfg_samplerate->redraw();
1937 lame_enc_reinit(&lame_stream);
1938 lame_enc_reinit(&lame_rec);
1939 print_info(_("The previous values have been set"), 1);
1940 return;
1941 }
1942
1943 }
1944 if(fl_g->choice_rec_codec->value() == CHOICE_OGG)
1945 {
1946 rc = vorbis_enc_reinit(&vorbis_rec);
1947 if(rc != 0)
1948 {
1949 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1950 cfg.audio.samplerate = sr_list[old_sr];
1951 vorbis_stream.samplerate = sr_list[old_sr];
1952 vorbis_rec.samplerate = sr_list[old_sr];
1953 fl_g->choice_cfg_samplerate->value(old_sr);
1954 fl_g->choice_cfg_samplerate->redraw();
1955 vorbis_enc_reinit(&vorbis_stream);
1956 vorbis_enc_reinit(&vorbis_rec);
1957 print_info(_("The previous values have been set"), 1);
1958 return;
1959 }
1960 }
1961
1962 if(fl_g->choice_rec_codec->value() == CHOICE_OPUS)
1963 {
1964 rc = opus_enc_reinit(&opus_rec);
1965 if(rc != 0)
1966 {
1967 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1968 cfg.audio.samplerate = sr_list[old_sr];
1969 opus_stream.samplerate = sr_list[old_sr];
1970 opus_rec.samplerate = sr_list[old_sr];
1971 fl_g->choice_cfg_samplerate->value(old_sr);
1972 fl_g->choice_cfg_samplerate->redraw();
1973 opus_enc_reinit(&opus_stream);
1974 opus_enc_reinit(&opus_rec);
1975 print_info(_("The previous values have been set"), 1);
1976 return;
1977 }
1978 }
1979
1980 #ifdef HAVE_LIBFDK_AAC
1981 if(fl_g->choice_rec_codec->value() == CHOICE_AAC)
1982 {
1983 rc = aac_enc_reinit(&aac_rec);
1984 if(rc != 0)
1985 {
1986 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
1987 cfg.audio.samplerate = sr_list[old_sr];
1988 aac_stream.samplerate = sr_list[old_sr];
1989 aac_rec.samplerate = sr_list[old_sr];
1990 fl_g->choice_cfg_samplerate->value(old_sr);
1991 fl_g->choice_cfg_samplerate->redraw();
1992 aac_enc_reinit(&aac_stream);
1993 aac_enc_reinit(&aac_rec);
1994 print_info(_("The previous values have been set"), 1);
1995 return;
1996 }
1997 }
1998 #endif
1999 if(fl_g->choice_rec_codec->value() == CHOICE_FLAC)
2000 {
2001 rc = flac_enc_reinit(&flac_rec);
2002 if(rc != 0)
2003 {
2004 print_info(_("Warning:\nThe record Sample-/Bitrate combination is invalid"), 1);
2005 cfg.audio.samplerate = sr_list[old_sr];
2006 flac_rec.samplerate = sr_list[old_sr];
2007 fl_g->choice_cfg_samplerate->value(old_sr);
2008 fl_g->choice_cfg_samplerate->redraw();
2009 flac_enc_reinit(&flac_rec);
2010 print_info(_("The previous values have been set"), 1);
2011 return;
2012 }
2013 }
2014
2015
2016 //The buffer size is dependand on the samplerate
2017 input_cfg_buffer_cb(0);
2018
2019
2020 snprintf(text_buf, sizeof(text_buf), _("Samplerate set to: %dHz"), cfg.audio.samplerate);
2021 print_info(text_buf, 0);
2022
2023
2024 //reinit portaudio
2025 snd_reinit();
2026 }
2027
choice_cfg_channel_stereo_cb(void)2028 void choice_cfg_channel_stereo_cb(void)
2029 {
2030 cfg.audio.channel = 2;
2031
2032 // Reinit streaming codecs
2033 lame_stream.channel = 2;
2034 vorbis_stream.channel = 2;
2035 opus_stream.channel = 2;
2036 #ifdef HAVE_LIBFDK_AAC
2037 aac_stream.channel = 2;
2038 #endif
2039 flac_stream.channel = 2;
2040
2041
2042 if(fl_g->choice_cfg_codec->value() == CHOICE_MP3)
2043 lame_enc_reinit(&lame_stream);
2044 if(fl_g->choice_cfg_codec->value() == CHOICE_OGG)
2045 vorbis_enc_reinit(&vorbis_stream);
2046 if(fl_g->choice_cfg_codec->value() == CHOICE_OPUS)
2047 opus_enc_reinit(&opus_stream);
2048 #ifdef HAVE_LIBFDK_AAC
2049 if(fl_g->choice_cfg_codec->value() == CHOICE_AAC)
2050 aac_enc_reinit(&aac_stream);
2051 #endif
2052 if(fl_g->choice_cfg_codec->value() == CHOICE_FLAC)
2053 flac_enc_reinit(&flac_stream);
2054
2055
2056 // Reinit recording codecs
2057 lame_rec.channel = 2;
2058 vorbis_rec.channel = 2;
2059 opus_rec.channel = 2;
2060 #ifdef HAVE_LIBFDK_AAC
2061 aac_rec.channel = 2;
2062 #endif
2063 flac_rec.channel = 2;
2064
2065 if(fl_g->choice_rec_codec->value() == CHOICE_MP3)
2066 lame_enc_reinit(&lame_rec);
2067 if(fl_g->choice_rec_codec->value() == CHOICE_OGG)
2068 vorbis_enc_reinit(&vorbis_rec);
2069 if(fl_g->choice_rec_codec->value() == CHOICE_OPUS)
2070 opus_enc_reinit(&opus_rec);
2071 #ifdef HAVE_LIBFDK_AAC
2072 if(fl_g->choice_rec_codec->value() == CHOICE_AAC)
2073 aac_enc_reinit(&aac_rec);
2074 #endif
2075 if(fl_g->choice_rec_codec->value() == CHOICE_FLAC)
2076 flac_enc_reinit(&flac_rec);
2077
2078 snd_reinit();
2079
2080 print_info(_("Channels set to: stereo"), 0);
2081 }
2082
choice_cfg_channel_mono_cb(void)2083 void choice_cfg_channel_mono_cb(void)
2084 {
2085 cfg.audio.channel = 1;
2086
2087 // Reinit streaming codecs
2088 lame_stream.channel = 1;
2089 vorbis_stream.channel = 1;
2090 opus_stream.channel = 1;
2091 #ifdef HAVE_LIBFDK_AAC
2092 aac_stream.channel = 1;
2093 #endif
2094 flac_stream.channel = 1;
2095
2096 if(fl_g->choice_cfg_codec->value() == CHOICE_MP3)
2097 lame_enc_reinit(&lame_stream);
2098 if(fl_g->choice_cfg_codec->value() == CHOICE_OGG)
2099 vorbis_enc_reinit(&vorbis_stream);
2100 if(fl_g->choice_cfg_codec->value() == CHOICE_OPUS)
2101 opus_enc_reinit(&opus_stream);
2102 #ifdef HAVE_LIBFDK_AAC
2103 if(fl_g->choice_cfg_codec->value() == CHOICE_AAC)
2104 aac_enc_reinit(&aac_stream);
2105 #endif
2106 if(fl_g->choice_cfg_codec->value() == CHOICE_FLAC)
2107 flac_enc_reinit(&flac_stream);
2108
2109 // Reinit recording codecs
2110 lame_rec.channel = 1;
2111 vorbis_rec.channel = 1;
2112 opus_rec.channel = 1;
2113 #ifdef HAVE_LIBFDK_AAC
2114 aac_rec.channel = 1;
2115 #endif
2116 flac_rec.channel = 1;
2117
2118 if(fl_g->choice_rec_codec->value() == CHOICE_MP3)
2119 lame_enc_reinit(&lame_rec);
2120 if(fl_g->choice_rec_codec->value() == CHOICE_OGG)
2121 vorbis_enc_reinit(&vorbis_rec);
2122 if(fl_g->choice_rec_codec->value() == CHOICE_OPUS)
2123 opus_enc_reinit(&opus_rec);
2124 #ifdef HAVE_LIBFDK_AAC
2125 if(fl_g->choice_rec_codec->value() == CHOICE_AAC)
2126 aac_enc_reinit(&aac_rec);
2127 #endif
2128 if(fl_g->choice_rec_codec->value() == CHOICE_FLAC)
2129 flac_enc_reinit(&flac_rec);
2130
2131 //Reinit PortAudio
2132 snd_reinit();
2133
2134 print_info(_("Channels set to: mono"), 0);
2135 }
2136
button_add_srv_cancel_cb(void)2137 void button_add_srv_cancel_cb(void)
2138 {
2139 fl_g->input_add_srv_name->value("");
2140 fl_g->input_add_srv_addr->value("");
2141 fl_g->input_add_srv_port->value("");
2142 fl_g->input_add_srv_pwd->value("");
2143 fl_g->input_add_srv_mount->value("");
2144 fl_g->input_add_srv_usr->value("");
2145 fl_g->check_add_srv_tls->value(0);
2146
2147 fl_g->window_add_srv->hide();
2148 }
2149
button_add_icy_add_cb(void)2150 void button_add_icy_add_cb(void)
2151 {
2152 int i;
2153 //error checking
2154 if(strlen(fl_g->input_add_icy_name->value()) == 0)
2155 {
2156 fl_alert(_("No name specified"));
2157 return;
2158 }
2159
2160 if(cfg.main.icy_ent != NULL)
2161 {
2162 if(strlen(fl_g->input_add_icy_name->value()) + strlen(cfg.main.icy_ent) > 1000)
2163 {
2164 fl_alert(_("The number of characters of all your icy names exeeds 1000\n"
2165 "Please reduce the number of characters of each icy name"));
2166 return;
2167 }
2168 }
2169 if(strpbrk(fl_g->input_add_icy_name->value(), ";\\/\n\r") != NULL)
2170 {
2171 fl_alert(_("No newline characters and ;/\\ are allowed in the name field"));
2172 return;
2173 }
2174
2175
2176 //check if the name already exists
2177 for(i = 0; i < cfg.main.num_of_icy; i++)
2178 {
2179 if(!strcmp(fl_g->input_add_icy_name->value(), cfg.icy[i]->name))
2180 {
2181 fl_alert(_("Server name already exist!"));
2182 return;
2183 }
2184 }
2185
2186 i = cfg.main.num_of_icy;
2187 cfg.main.num_of_icy++;
2188
2189 cfg.icy = (icy_t**)realloc(cfg.icy, cfg.main.num_of_icy * sizeof(icy_t*));
2190 cfg.icy[i] = (icy_t*)malloc(sizeof(icy_t));
2191
2192 cfg.icy[i]->name = (char*)malloc(strlen(fl_g->input_add_icy_name->value())+1 );
2193 strcpy(cfg.icy[i]->name, fl_g->input_add_icy_name->value());
2194
2195 cfg.icy[i]->desc = (char*)malloc(strlen(fl_g->input_add_icy_desc->value())+1 );
2196 strcpy(cfg.icy[i]->desc, fl_g->input_add_icy_desc->value());
2197
2198 cfg.icy[i]->url = (char*)malloc(strlen(fl_g->input_add_icy_url->value())+1 );
2199 strcpy(cfg.icy[i]->url, fl_g->input_add_icy_url->value());
2200
2201 cfg.icy[i]->genre = (char*)malloc(strlen(fl_g->input_add_icy_genre->value())+1 );
2202 strcpy(cfg.icy[i]->genre, fl_g->input_add_icy_genre->value());
2203
2204 cfg.icy[i]->irc = (char*)malloc(strlen(fl_g->input_add_icy_irc->value())+1 );
2205 strcpy(cfg.icy[i]->irc, fl_g->input_add_icy_irc->value());
2206
2207 cfg.icy[i]->icq = (char*)malloc(strlen(fl_g->input_add_icy_icq->value())+1 );
2208 strcpy(cfg.icy[i]->icq, fl_g->input_add_icy_icq->value());
2209
2210 cfg.icy[i]->aim = (char*)malloc(strlen(fl_g->input_add_icy_aim->value())+1 );
2211 strcpy(cfg.icy[i]->aim, fl_g->input_add_icy_aim->value());
2212
2213 cfg.icy[i]->pub = (char*)malloc(2 * sizeof(char));
2214 snprintf(cfg.icy[i]->pub, 2, "%d", fl_g->check_add_icy_pub->value());
2215
2216 if(cfg.main.num_of_icy > 1)
2217 {
2218 cfg.main.icy_ent = (char*)realloc(cfg.main.icy_ent,
2219 strlen(cfg.main.icy_ent) +
2220 strlen(cfg.icy[i]->name) +2);
2221 sprintf(cfg.main.icy_ent, "%s;%s", cfg.main.icy_ent, cfg.icy[i]->name);
2222 }
2223 else
2224 {
2225 cfg.main.icy_ent = (char*)malloc(strlen(cfg.icy[i]->name) +1);
2226 sprintf(cfg.main.icy_ent, "%s", cfg.icy[i]->name);
2227 }
2228
2229 cfg.main.icy = (char*)realloc(cfg.main.icy, strlen(cfg.icy[i]->name)+1);
2230
2231 strcpy(cfg.main.icy, cfg.icy[i]->name);
2232
2233 fl_g->input_add_icy_name->value("");
2234 fl_g->input_add_icy_desc->value("");
2235 fl_g->input_add_icy_url->value("");
2236 fl_g->input_add_icy_genre->value("");
2237 fl_g->input_add_icy_irc->value("");
2238 fl_g->input_add_icy_icq->value("");
2239 fl_g->input_add_icy_aim->value("");
2240 fl_g->check_add_icy_pub->value(0);
2241
2242 fl_g->window_add_icy->hide();
2243
2244 fl_g->choice_cfg_act_icy->add(cfg.icy[i]->name);
2245 fl_g->choice_cfg_act_icy->redraw();
2246
2247 fl_g->button_cfg_edit_icy->activate();
2248 fl_g->button_cfg_del_icy->activate();
2249
2250 fl_g->choice_cfg_act_icy->activate();
2251
2252 // make added icy data the active icy entry
2253 fl_g->choice_cfg_act_icy->value(i);
2254 choice_cfg_act_icy_cb();
2255 }
2256
button_add_icy_cancel_cb(void)2257 void button_add_icy_cancel_cb(void)
2258 {
2259 fl_g->input_add_icy_name->value("");
2260 fl_g->input_add_icy_desc->value("");
2261 fl_g->input_add_icy_url->value("");
2262 fl_g->input_add_icy_genre->value("");
2263 fl_g->input_add_icy_irc->value("");
2264 fl_g->input_add_icy_icq->value("");
2265 fl_g->input_add_icy_aim->value("");
2266 fl_g->check_add_icy_pub->value(0);
2267 fl_g->window_add_icy->hide();
2268 }
2269
button_cfg_edit_icy_cb(void)2270 void button_cfg_edit_icy_cb(void)
2271 {
2272 if(cfg.main.num_of_icy < 1)
2273 return;
2274
2275 int icy = fl_g->choice_cfg_act_icy->value();
2276
2277 fl_g->window_add_icy->label(_("Edit Server Infos"));
2278
2279 fl_g->button_add_icy_add->hide();
2280 fl_g->button_add_icy_save->show();
2281
2282 fl_g->input_add_icy_name->value(cfg.icy[icy]->name);
2283 fl_g->input_add_icy_desc->value(cfg.icy[icy]->desc);
2284 fl_g->input_add_icy_genre->value(cfg.icy[icy]->genre);
2285 fl_g->input_add_icy_url->value(cfg.icy[icy]->url);
2286 fl_g->input_add_icy_irc->value(cfg.icy[icy]->irc);
2287 fl_g->input_add_icy_icq->value(cfg.icy[icy]->icq);
2288 fl_g->input_add_icy_aim->value(cfg.icy[icy]->aim);
2289
2290 if(!strcmp(cfg.icy[icy]->pub, "1"))
2291 fl_g->check_add_icy_pub->value(1);
2292 else
2293 fl_g->check_add_icy_pub->value(0);
2294
2295 fl_g->window_add_icy->position(fl_g->window_cfg->x(), fl_g->window_cfg->y());
2296
2297 //give the "name" input field the input focus
2298 fl_g->input_add_icy_name->take_focus();
2299 fl_g->window_add_icy->show();
2300 }
2301
choice_cfg_dev_cb(void)2302 void choice_cfg_dev_cb(void)
2303 {
2304 cfg.audio.dev_num = fl_g->choice_cfg_dev->value();
2305 update_samplerates();
2306 snd_reinit();
2307 update_channel_lists();
2308 }
2309
choice_cfg_left_channel_cb(void)2310 void choice_cfg_left_channel_cb(void)
2311 {
2312 cfg.audio.left_ch = fl_g->choice_cfg_left_channel->value()+1;
2313 }
2314
2315
choice_cfg_right_channel_cb(void)2316 void choice_cfg_right_channel_cb(void)
2317 {
2318 cfg.audio.right_ch = fl_g->choice_cfg_right_channel->value()+1;
2319 }
2320
choice_cfg_codec_mp3_cb(void)2321 void choice_cfg_codec_mp3_cb(void)
2322 {
2323 if(lame_enc_reinit(&lame_stream) != 0)
2324 {
2325 print_info(_("MP3 encoder doesn't support current\n"
2326 "Sample-/Bitrate combination"), 1);
2327
2328 if(!strcmp(cfg.audio.codec, "ogg"))
2329 fl_g->choice_cfg_codec->value(CHOICE_OGG);
2330 else if (!strcmp(cfg.audio.codec, "opus"))
2331 fl_g->choice_cfg_codec->value(CHOICE_OPUS);
2332 else if (!strcmp(cfg.audio.codec, "aac"))
2333 fl_g->choice_cfg_codec->value(CHOICE_AAC);
2334 else if (!strcmp(cfg.audio.codec, "flac"))
2335 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2336
2337 return;
2338 }
2339 strcpy(cfg.audio.codec, "mp3");
2340 print_info(_("Stream codec set to mp3"), 0);
2341 fl_g->choice_cfg_bitrate->activate();
2342 fl_g->choice_cfg_bitrate->show();
2343 }
2344
choice_cfg_codec_ogg_cb(void)2345 void choice_cfg_codec_ogg_cb(void)
2346 {
2347 if(vorbis_enc_reinit(&vorbis_stream) != 0)
2348 {
2349 print_info(_("OGG Vorbis encoder doesn't support current\n"
2350 "Sample-/Bitrate combination"), 1);
2351
2352 if(!strcmp(cfg.audio.codec, "mp3"))
2353 fl_g->choice_cfg_codec->value(CHOICE_MP3);
2354 else if (!strcmp(cfg.audio.codec, "opus"))
2355 fl_g->choice_cfg_codec->value(CHOICE_OPUS);
2356 else if (!strcmp(cfg.audio.codec, "aac"))
2357 fl_g->choice_cfg_codec->value(CHOICE_AAC);
2358 else if (!strcmp(cfg.audio.codec, "flac"))
2359 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2360
2361 return;
2362 }
2363 strcpy(cfg.audio.codec, "ogg");
2364 print_info(_("Stream codec set to ogg/vorbis"), 0);
2365 fl_g->choice_cfg_bitrate->activate();
2366 fl_g->choice_cfg_bitrate->show();
2367 }
2368
choice_cfg_codec_opus_cb(void)2369 void choice_cfg_codec_opus_cb(void)
2370 {
2371 if(opus_enc_reinit(&opus_stream) != 0)
2372 {
2373 print_info(_("Opus encoder doesn't support current\n"
2374 "Sample-/Bitrate combination"), 1);
2375
2376 if(!strcmp(cfg.audio.codec, "mp3"))
2377 fl_g->choice_cfg_codec->value(CHOICE_MP3);
2378 else if (!strcmp(cfg.audio.codec, "ogg"))
2379 fl_g->choice_cfg_codec->value(CHOICE_OGG);
2380 else if (!strcmp(cfg.audio.codec, "aac"))
2381 fl_g->choice_cfg_codec->value(CHOICE_AAC);
2382 else if (!strcmp(cfg.audio.codec, "flac"))
2383 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2384
2385 return;
2386 }
2387
2388 print_info(_("Stream codec set to opus"), 0);
2389 strcpy(cfg.audio.codec, "opus");
2390 fl_g->choice_cfg_bitrate->activate();
2391 fl_g->choice_cfg_bitrate->show();
2392 }
2393
choice_cfg_codec_aac_cb(void)2394 void choice_cfg_codec_aac_cb(void)
2395 {
2396 #ifdef HAVE_LIBFDK_AAC
2397 if (g_aac_lib_available == 0)
2398 {
2399 fl_alert(_("Could not find aac library.\nPlease follow the instructions in the manual for adding aac support."));
2400 if(!strcmp(cfg.audio.codec, "ogg"))
2401 fl_g->choice_cfg_codec->value(CHOICE_OGG);
2402 else if (!strcmp(cfg.audio.codec, "opus"))
2403 fl_g->choice_cfg_codec->value(CHOICE_OPUS);
2404 else if (!strcmp(cfg.audio.codec, "mp3"))
2405 fl_g->choice_cfg_codec->value(CHOICE_MP3);
2406 else if (!strcmp(cfg.audio.codec, "flac"))
2407 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2408
2409 return;
2410 }
2411 if(aac_enc_reinit(&aac_stream) != 0)
2412 {
2413 print_info(_("AAC encoder doesn't support current\n"
2414 "Sample-/Bitrate combination"), 1);
2415
2416 if(!strcmp(cfg.audio.codec, "ogg"))
2417 fl_g->choice_cfg_codec->value(CHOICE_OGG);
2418 else if (!strcmp(cfg.audio.codec, "opus"))
2419 fl_g->choice_cfg_codec->value(CHOICE_OPUS);
2420 else if (!strcmp(cfg.audio.codec, "mp3"))
2421 fl_g->choice_cfg_codec->value(CHOICE_MP3);
2422 else if (!strcmp(cfg.audio.codec, "flac"))
2423 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2424
2425 return;
2426 }
2427 strcpy(cfg.audio.codec, "aac");
2428 print_info(_("Stream codec set to aac"), 0);
2429 fl_g->choice_cfg_bitrate->activate();
2430 fl_g->choice_cfg_bitrate->show();
2431
2432
2433 #endif
2434 }
2435
choice_cfg_codec_flac_cb(void)2436 void choice_cfg_codec_flac_cb(void)
2437 {
2438 if(flac_enc_reinit(&flac_stream) != 0)
2439 {
2440 print_info(_("ERROR: While initializing flac settings"), 1);
2441
2442 if(!strcmp(cfg.audio.codec, "mp3"))
2443 fl_g->choice_rec_codec->value(CHOICE_MP3);
2444 else if(!strcmp(cfg.audio.codec, "ogg"))
2445 fl_g->choice_rec_codec->value(CHOICE_OGG);
2446 else if(!strcmp(cfg.audio.codec, "opus"))
2447 fl_g->choice_rec_codec->value(CHOICE_OPUS);
2448 else if(!strcmp(cfg.audio.codec, "aac"))
2449 fl_g->choice_rec_codec->value(CHOICE_AAC);
2450
2451 return;
2452 }
2453 strcpy(cfg.audio.codec, "flac");
2454 print_info(_("Stream codec set to flac"), 0);
2455
2456 fl_g->choice_cfg_bitrate->hide();
2457 fl_g->window_cfg->redraw();
2458 }
2459
choice_rec_codec_mp3_cb(void)2460 void choice_rec_codec_mp3_cb(void)
2461 {
2462 if(lame_enc_reinit(&lame_rec) != 0)
2463 {
2464 print_info(_("MP3 encoder doesn't support current\n"
2465 "Sample-/Bitrate combination"), 1);
2466
2467 //fall back to old rec codec
2468 if(!strcmp(cfg.rec.codec, "ogg"))
2469 fl_g->choice_rec_codec->value(CHOICE_OGG);
2470 else if(!strcmp(cfg.rec.codec, "wav"))
2471 fl_g->choice_rec_codec->value(CHOICE_WAV);
2472 else if(!strcmp(cfg.rec.codec, "opus"))
2473 fl_g->choice_rec_codec->value(CHOICE_OPUS);
2474 else if(!strcmp(cfg.rec.codec, "aac"))
2475 fl_g->choice_rec_codec->value(CHOICE_AAC);
2476 else if(!strcmp(cfg.rec.codec, "flac"))
2477 fl_g->choice_rec_codec->value(CHOICE_FLAC);
2478
2479 return;
2480 }
2481 strcpy(cfg.rec.codec, "mp3");
2482
2483 //check if the extension of the filename matches
2484 //the current selected codec
2485 test_file_extension();
2486
2487 print_info(_("Record codec set to mp3"), 0);
2488 fl_g->choice_rec_bitrate->activate();
2489 fl_g->choice_rec_bitrate->show();
2490 }
2491
choice_rec_codec_ogg_cb(void)2492 void choice_rec_codec_ogg_cb(void)
2493 {
2494 if(vorbis_enc_reinit(&vorbis_rec) != 0)
2495 {
2496 print_info(_("OGG Vorbis encoder doesn't support current\n"
2497 "Sample-/Bitrate combination"), 1);
2498
2499 if(!strcmp(cfg.rec.codec, "mp3"))
2500 fl_g->choice_rec_codec->value(CHOICE_MP3);
2501 else if(!strcmp(cfg.rec.codec, "wav"))
2502 fl_g->choice_rec_codec->value(CHOICE_WAV);
2503 else if(!strcmp(cfg.rec.codec, "opus"))
2504 fl_g->choice_rec_codec->value(CHOICE_OPUS);
2505 else if(!strcmp(cfg.rec.codec, "aac"))
2506 fl_g->choice_rec_codec->value(CHOICE_AAC);
2507 else if(!strcmp(cfg.rec.codec, "flac"))
2508 fl_g->choice_rec_codec->value(CHOICE_FLAC);
2509
2510 return;
2511 }
2512 strcpy(cfg.rec.codec, "ogg");
2513
2514 //check if the extension of the filename matches
2515 //the current selected codec
2516 test_file_extension();
2517
2518 print_info(_("Record codec set to ogg/vorbis"), 0);
2519 fl_g->choice_rec_bitrate->activate();
2520 fl_g->choice_rec_bitrate->show();
2521 }
2522
choice_rec_codec_opus_cb(void)2523 void choice_rec_codec_opus_cb(void)
2524 {
2525 if(opus_enc_reinit(&opus_rec) != 0)
2526 {
2527 print_info(_("Opus encoder doesn't support current\n"
2528 "Sample-/Bitrate combination"), 1);
2529
2530 if(!strcmp(cfg.rec.codec, "mp3"))
2531 fl_g->choice_rec_codec->value(CHOICE_MP3);
2532 else if(!strcmp(cfg.rec.codec, "wav"))
2533 fl_g->choice_rec_codec->value(CHOICE_WAV);
2534 else if(!strcmp(cfg.rec.codec, "ogg"))
2535 fl_g->choice_rec_codec->value(CHOICE_OGG);
2536 else if(!strcmp(cfg.rec.codec, "aac"))
2537 fl_g->choice_rec_codec->value(CHOICE_AAC);
2538 else if(!strcmp(cfg.rec.codec, "flac"))
2539 fl_g->choice_rec_codec->value(CHOICE_FLAC);
2540
2541
2542 return;
2543 }
2544 strcpy(cfg.rec.codec, "opus");
2545
2546 //check if the extension of the filename matches
2547 //the current selected codec
2548 test_file_extension();
2549
2550 print_info(_("Record codec set to opus"), 0);
2551 fl_g->choice_rec_bitrate->activate();
2552 fl_g->choice_rec_bitrate->show();
2553 }
2554
choice_rec_codec_aac_cb(void)2555 void choice_rec_codec_aac_cb(void)
2556 {
2557 #ifdef HAVE_LIBFDK_AAC
2558 if (g_aac_lib_available == 0)
2559 {
2560 fl_alert(_("Could not find aac library.\nPlease follow the instructions in the manual for adding aac support."));
2561 if(!strcmp(cfg.audio.codec, "ogg"))
2562 fl_g->choice_cfg_codec->value(CHOICE_OGG);
2563 else if (!strcmp(cfg.audio.codec, "opus"))
2564 fl_g->choice_cfg_codec->value(CHOICE_OPUS);
2565 else if (!strcmp(cfg.audio.codec, "mp3"))
2566 fl_g->choice_cfg_codec->value(CHOICE_MP3);
2567 else if (!strcmp(cfg.audio.codec, "flac"))
2568 fl_g->choice_cfg_codec->value(CHOICE_FLAC);
2569
2570 return;
2571 }
2572 if(aac_enc_reinit(&aac_rec) != 0)
2573 {
2574 print_info(_("AAC encoder doesn't support current\n"
2575 "Sample-/Bitrate combination"), 1);
2576
2577 //fall back to old rec codec
2578 if(!strcmp(cfg.rec.codec, "ogg"))
2579 fl_g->choice_rec_codec->value(CHOICE_OGG);
2580 else if(!strcmp(cfg.rec.codec, "wav"))
2581 fl_g->choice_rec_codec->value(CHOICE_WAV);
2582 else if(!strcmp(cfg.rec.codec, "opus"))
2583 fl_g->choice_rec_codec->value(CHOICE_OPUS);
2584 else if(!strcmp(cfg.rec.codec, "flac"))
2585 fl_g->choice_rec_codec->value(CHOICE_FLAC);
2586 else if(!strcmp(cfg.rec.codec, "mp3"))
2587 fl_g->choice_rec_codec->value(CHOICE_MP3);
2588
2589 return;
2590 }
2591 strcpy(cfg.rec.codec, "aac");
2592
2593 //check if the extension of the filename matches
2594 //the current selected codec
2595 test_file_extension();
2596
2597 print_info(_("Record codec set to aac"), 0);
2598 fl_g->choice_rec_bitrate->activate();
2599 fl_g->choice_rec_bitrate->show();
2600
2601
2602
2603 #endif
2604 }
2605
choice_rec_codec_flac_cb(void)2606 void choice_rec_codec_flac_cb(void)
2607 {
2608 if(flac_enc_reinit(&flac_rec) != 0)
2609 {
2610 print_info(_("ERROR: While initializing flac settings"), 1);
2611
2612 if(!strcmp(cfg.rec.codec, "mp3"))
2613 fl_g->choice_rec_codec->value(CHOICE_MP3);
2614 else if(!strcmp(cfg.rec.codec, "ogg"))
2615 fl_g->choice_rec_codec->value(CHOICE_OGG);
2616 else if(!strcmp(cfg.rec.codec, "opus"))
2617 fl_g->choice_rec_codec->value(CHOICE_OPUS);
2618 else if(!strcmp(cfg.rec.codec, "wav"))
2619 fl_g->choice_rec_codec->value(CHOICE_WAV);
2620 else if(!strcmp(cfg.rec.codec, "aac"))
2621 fl_g->choice_rec_codec->value(CHOICE_AAC);
2622
2623 return;
2624 }
2625 strcpy(cfg.rec.codec, "flac");
2626
2627 //check if the extension of the filename matches
2628 //the current selected codec
2629 test_file_extension();
2630
2631 print_info(_("Record codec set to flac"), 0);
2632 fl_g->choice_rec_bitrate->hide();
2633 fl_g->window_cfg->redraw();
2634 }
2635
choice_rec_codec_wav_cb(void)2636 void choice_rec_codec_wav_cb(void)
2637 {
2638 fl_g->choice_rec_bitrate->hide();
2639 fl_g->window_cfg->redraw();
2640
2641 strcpy(cfg.rec.codec, "wav");
2642
2643 //check if the extension of the filename matches
2644 //the current selected codec
2645 test_file_extension();
2646
2647 print_info(_("Record codec set to wav"), 0);
2648
2649 }
2650
input_tls_cert_file_cb(void)2651 void input_tls_cert_file_cb(void)
2652 {
2653 cfg.tls.cert_file = (char*)realloc(cfg.tls.cert_file,
2654 strlen(fl_g->input_tls_cert_file->value())+1);
2655
2656 strcpy(cfg.tls.cert_file, fl_g->input_tls_cert_file->value());
2657 fl_g->input_tls_cert_file->tooltip(cfg.tls.cert_file);
2658 }
2659
input_tls_cert_dir_cb(void)2660 void input_tls_cert_dir_cb(void)
2661 {
2662 int len = strlen(fl_g->input_tls_cert_dir->value());
2663
2664 cfg.tls.cert_dir = (char*)realloc(cfg.tls.cert_dir, len +2);
2665
2666 strcpy(cfg.tls.cert_dir, fl_g->input_tls_cert_dir->value());
2667
2668 #ifdef WIN32 //Replace all "Windows slashes" with "unix slashes"
2669 strrpl(&cfg.tls.cert_dir, (char*)"\\", (char*)"/", MODE_ALL);
2670 #endif
2671
2672 //Append an '/' if there isn't one
2673 if ( (len > 0) && (cfg.tls.cert_dir[len-1] != '/'))
2674 strcat(cfg.tls.cert_dir, "/");
2675
2676 fl_g->input_tls_cert_dir->value(cfg.tls.cert_dir);
2677 fl_g->input_tls_cert_dir->tooltip(cfg.tls.cert_dir);
2678 }
2679
button_tls_browse_file_cb(void)2680 void button_tls_browse_file_cb(void)
2681 {
2682 Fl_My_Native_File_Chooser nfc;
2683 nfc.title(_("Select certificate file..."));
2684 nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE);
2685
2686 switch(nfc.show())
2687 {
2688 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg());
2689 break;
2690 case 1:
2691 break; //cancel pressed
2692 default:
2693 fl_g->input_tls_cert_file->value(nfc.filename());
2694 input_tls_cert_file_cb();
2695 }
2696 }
2697
button_tls_browse_dir_cb(void)2698 void button_tls_browse_dir_cb(void)
2699 {
2700 Fl_My_Native_File_Chooser nfc;
2701 nfc.title(_("Select certificate directory..."));
2702 nfc.type(Fl_My_Native_File_Chooser::BROWSE_DIRECTORY);
2703 nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER);
2704
2705 nfc.directory(fl_g->input_tls_cert_dir->value());
2706
2707 switch(nfc.show())
2708 {
2709 case -1:
2710 fl_alert(_("ERROR: %s"), nfc.errmsg()); //error
2711 break;
2712 case 1:
2713 break; //cancel pressed
2714 default:
2715 fl_g->input_tls_cert_dir->value(nfc.filename());
2716 input_tls_cert_dir_cb();
2717 break;
2718 }
2719 }
2720
ILM216_cb(void)2721 void ILM216_cb(void)
2722 {
2723 if(Fl::event_button() == 1) //left mouse button
2724 {
2725 //change the display mode only when connected or recording
2726 //this will prevent confusing the user
2727 if(!connected && !recording)
2728 return;
2729
2730 switch(display_info)
2731 {
2732 case STREAM_TIME:
2733 if(recording)
2734 display_info = REC_TIME;
2735 else
2736 display_info = SENT_DATA;
2737 break;
2738
2739 case REC_TIME:
2740 if(connected)
2741 display_info = SENT_DATA;
2742 else
2743 display_info = REC_DATA;
2744 break;
2745
2746 case SENT_DATA:
2747 if(recording)
2748 display_info = REC_DATA;
2749 else
2750 display_info = STREAM_TIME;
2751 break;
2752
2753 case REC_DATA:
2754 if(connected)
2755 display_info = STREAM_TIME;
2756 else
2757 display_info = REC_TIME;
2758 }
2759 }
2760 /* if(Fl::event_button() == 3) //right mouse button
2761 {
2762 uchar r, g, b;
2763
2764 Fl_Color bg, txt;
2765 bg = (Fl_Color)cfg.main.bg_color;
2766 txt = (Fl_Color)cfg.main.txt_color;
2767
2768 //Set the r g b values the color_chooser should start with
2769 r = (bg & 0xFF000000) >> 24;
2770 g = (bg & 0x00FF0000) >> 16;
2771 b = (bg & 0x0000FF00) >> 8;
2772
2773 fl_color_chooser((const char*)"select background color", r, g, b);
2774
2775 //The color_chooser changes the r, g, b, values to selected color
2776 cfg.main.bg_color = fl_rgb_color(r, g, b);
2777
2778 fl_g->lcd->redraw();
2779
2780 r = (txt & 0xFF000000) >> 24;
2781 g = (txt & 0x00FF0000) >> 16;
2782 b = (txt & 0x0000FF00) >> 8;
2783
2784 fl_color_chooser((const char*)"select text color", r, g, b);
2785 cfg.main.txt_color = fl_rgb_color(r, g, b);
2786
2787 fl_g->lcd->redraw();
2788
2789
2790 }*/
2791 }
2792
button_rec_browse_cb(void)2793 void button_rec_browse_cb(void)
2794 {
2795 Fl_My_Native_File_Chooser nfc;
2796 nfc.title(_("Record to..."));
2797 nfc.type(Fl_My_Native_File_Chooser::BROWSE_DIRECTORY);
2798 nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER);
2799
2800
2801 nfc.directory(fl_g->input_rec_folder->value());
2802
2803 switch(nfc.show())
2804 {
2805 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg()); //error
2806 break;
2807 case 1: break; //cancel
2808 default:
2809 fl_g->input_rec_folder->value(nfc.filename());
2810 input_rec_folder_cb();
2811
2812 break;
2813 }
2814 }
button_rec_split_now_cb(void)2815 void button_rec_split_now_cb(void)
2816 {
2817 int mode = 0;
2818 split_recording_timer(&mode);
2819 }
2820
input_rec_filename_cb(void)2821 void input_rec_filename_cb(void)
2822 {
2823 char *tooltip;
2824
2825 cfg.rec.filename = (char*)realloc(cfg.rec.filename,
2826 strlen(fl_g->input_rec_filename->value())+1);
2827
2828 strcpy(cfg.rec.filename, fl_g->input_rec_filename->value());
2829
2830 //check if the extension of the filename matches
2831 //the current selected codec
2832 test_file_extension();
2833
2834 tooltip = strdup(cfg.rec.filename);
2835
2836 expand_string(&tooltip);
2837
2838 fl_g->input_rec_filename->copy_tooltip(tooltip);
2839
2840
2841 free(tooltip);
2842 }
2843
input_rec_folder_cb(void)2844 void input_rec_folder_cb(void)
2845 {
2846 int len = strlen(fl_g->input_rec_folder->value());
2847
2848 cfg.rec.folder = (char*)realloc(cfg.rec.folder, len +2);
2849
2850 strcpy(cfg.rec.folder, fl_g->input_rec_folder->value());
2851
2852 #ifdef WIN32 //Replace all "Windows slashes" with "unix slashes"
2853 char *p;
2854 p = cfg.rec.folder;
2855 while(*p != '\0')
2856 {
2857 if(*p == '\\')
2858 *p = '/';
2859 p++;
2860 }
2861 #endif
2862
2863 //Append an '/' if there isn't one
2864 if(cfg.rec.folder[len-1] != '/')
2865 strcat(cfg.rec.folder, "/");
2866
2867 fl_g->input_rec_folder->value(cfg.rec.folder);
2868 fl_g->input_rec_folder->tooltip(cfg.rec.folder);
2869 }
2870
input_log_filename_cb(void)2871 void input_log_filename_cb(void)
2872 {
2873 cfg.main.log_file = (char*)realloc(cfg.main.log_file,
2874 strlen(fl_g->input_log_filename->value())+1);
2875
2876 strcpy(cfg.main.log_file, fl_g->input_log_filename->value());
2877 fl_g->input_log_filename->tooltip(cfg.main.log_file);
2878 }
2879
button_cfg_browse_songfile_cb(void)2880 void button_cfg_browse_songfile_cb(void)
2881 {
2882 Fl_My_Native_File_Chooser nfc;
2883 nfc.title(_("Select Songfile"));
2884 nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE);
2885 switch(nfc.show())
2886 {
2887 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg());
2888 break;
2889 case 1:
2890 break; //cancel
2891 default:
2892 fl_g->input_cfg_song_file->value(nfc.filename());
2893 input_cfg_song_file_cb();
2894 }
2895 }
2896
input_cfg_song_file_cb(void)2897 void input_cfg_song_file_cb(void)
2898 {
2899 int len = strlen(fl_g->input_cfg_song_file->value());
2900
2901 cfg.main.song_path = (char*)realloc(cfg.main.song_path, len +1);
2902
2903 strcpy(cfg.main.song_path, fl_g->input_cfg_song_file->value());
2904
2905 #ifdef WIN32 //Replace all "Windows slashes" with "unix slashes"
2906 char *p;
2907 p = cfg.main.song_path;
2908 while(*p != '\0')
2909 {
2910 if(*p == '\\')
2911 *p = '/';
2912 p++;
2913 }
2914 #endif
2915
2916 fl_g->input_cfg_song_file->value(cfg.main.song_path);
2917 fl_g->input_cfg_song_file->tooltip(cfg.main.song_path);
2918 }
2919
check_gui_attach_cb(void)2920 void check_gui_attach_cb(void)
2921 {
2922 if(fl_g->check_gui_attach->value())
2923 {
2924 cfg.gui.attach = 1;
2925 Fl::add_timeout(0.1, &cfg_win_pos_timer);
2926 }
2927 else
2928 {
2929 cfg.gui.attach = 0;
2930 Fl::remove_timeout(&cfg_win_pos_timer);
2931 }
2932 }
2933
check_gui_ontop_cb(void)2934 void check_gui_ontop_cb(void)
2935 {
2936 if(fl_g->check_gui_ontop->value())
2937 {
2938 fl_g->window_main->stay_on_top(1);
2939 fl_g->window_cfg->stay_on_top(1);
2940 cfg.gui.ontop = 1;
2941 }
2942 else
2943 {
2944 fl_g->window_main->stay_on_top(0);
2945 fl_g->window_cfg->stay_on_top(0);
2946 cfg.gui.ontop = 0;
2947 }
2948
2949 }
check_gui_hide_log_window_cb(void)2950 void check_gui_hide_log_window_cb(void)
2951 {
2952 if(fl_g->check_gui_hide_log_window->value())
2953 cfg.gui.hide_log_window = 1;
2954 else
2955 cfg.gui.hide_log_window = 0;
2956 }
2957
check_gui_remember_pos_cb(void)2958 void check_gui_remember_pos_cb(void)
2959 {
2960 if(fl_g->check_gui_remember_pos->value())
2961 cfg.gui.remember_pos = 1;
2962 else
2963 cfg.gui.remember_pos = 0;
2964 }
2965
check_gui_lcd_auto_cb(void)2966 void check_gui_lcd_auto_cb(void)
2967 {
2968 if(fl_g->check_gui_lcd_auto->value())
2969 {
2970 cfg.gui.lcd_auto = 1;
2971 }
2972 else
2973 {
2974 cfg.gui.lcd_auto = 0;
2975 }
2976 }
2977
button_gui_bg_color_cb(void)2978 void button_gui_bg_color_cb(void)
2979 {
2980 uchar r, g, b;
2981
2982 Fl_Color bg;
2983 bg = (Fl_Color)cfg.main.bg_color;
2984
2985 //Set the r g b values the color_chooser should start with
2986 r = (bg & 0xFF000000) >> 24;
2987 g = (bg & 0x00FF0000) >> 16;
2988 b = (bg & 0x0000FF00) >> 8;
2989
2990 fl_color_chooser(_("select background color"), r, g, b);
2991
2992 //The color_chooser changes the r, g, b, values to selected color
2993 cfg.main.bg_color = fl_rgb_color(r, g, b);
2994
2995 fl_g->button_gui_bg_color->color(cfg.main.bg_color, fl_lighter((Fl_Color)cfg.main.bg_color));
2996 fl_g->button_gui_bg_color->redraw();
2997 fl_g->lcd->redraw();
2998 }
2999
button_gui_text_color_cb(void)3000 void button_gui_text_color_cb(void)
3001 {
3002 uchar r, g, b;
3003
3004 Fl_Color txt;
3005 txt = (Fl_Color)cfg.main.txt_color;
3006
3007 //Set the r g b values the color_chooser should start with
3008 r = (txt & 0xFF000000) >> 24;
3009 g = (txt & 0x00FF0000) >> 16;
3010 b = (txt & 0x0000FF00) >> 8;
3011
3012 fl_color_chooser(_("select text color"), r, g, b);
3013
3014 //The color_chooser changes the r, g, b, values to selected color
3015 cfg.main.txt_color = fl_rgb_color(r, g, b);
3016
3017 fl_g->button_gui_text_color->color(cfg.main.txt_color, fl_lighter((Fl_Color)cfg.main.txt_color));
3018 fl_g->button_gui_text_color->redraw();
3019 fl_g->lcd->redraw();
3020 }
3021
choice_gui_language_cb(void)3022 void choice_gui_language_cb(void)
3023 {
3024 switch (fl_g->choice_gui_language->value()) {
3025 case LANG_DE:
3026 cfg.gui.lang = LANG_DE;
3027 break;
3028 case LANG_EN:
3029 cfg.gui.lang = LANG_EN;
3030 break;
3031 default:
3032 cfg.gui.lang = LANG_SYSTEM;
3033 break;
3034 }
3035
3036 fl_alert(_("Please restart butt to apply new language."));
3037
3038 }
3039
3040
check_cfg_auto_start_rec_cb(void)3041 void check_cfg_auto_start_rec_cb(void)
3042 {
3043 cfg.rec.start_rec = fl_g->check_cfg_auto_start_rec->value();
3044 fl_g->lcd->redraw(); //update the little record icon
3045 }
check_cfg_auto_stop_rec_cb(void)3046 void check_cfg_auto_stop_rec_cb(void)
3047 {
3048 cfg.rec.stop_rec = fl_g->check_cfg_auto_stop_rec->value();
3049 }
3050
3051
check_cfg_rec_after_launch_cb(void)3052 void check_cfg_rec_after_launch_cb(void)
3053 {
3054 cfg.rec.rec_after_launch = fl_g->check_cfg_rec_after_launch->value();
3055 }
3056
check_cfg_rec_hourly_cb(void)3057 void check_cfg_rec_hourly_cb(void)
3058 {
3059 //cfg.rec.start_rec_hourly = fl_g->check_cfg_rec_hourly->value();
3060 }
3061
check_cfg_connect_cb(void)3062 void check_cfg_connect_cb(void)
3063 {
3064 cfg.main.connect_at_startup = fl_g->check_cfg_connect->value();
3065 }
3066
check_cfg_force_reconnecting_cb(void)3067 void check_cfg_force_reconnecting_cb(void)
3068 {
3069 cfg.main.force_reconnecting = fl_g->check_cfg_force_reconnecting->value();
3070 }
3071
input_cfg_signal_cb(void)3072 void input_cfg_signal_cb(void)
3073 {
3074 // Values < 0 are not allowed
3075 if(fl_g->input_cfg_signal->value() <= 0)
3076 {
3077 fl_g->input_cfg_signal->value(0);
3078 Fl::remove_timeout(&stream_signal_timer);
3079 }
3080 else
3081 Fl::add_timeout(1, &stream_signal_timer);
3082
3083 cfg.main.signal_threshold = fl_g->input_cfg_signal->value();
3084 }
3085
3086
input_cfg_present_level_cb(void)3087 void input_cfg_present_level_cb(void)
3088 {
3089 if(fl_g->input_cfg_present_level->value() < -90)
3090 {
3091 fl_alert(_("Value must be a number between -90.0 and 0"));
3092 fl_g->input_cfg_present_level->value(-cfg.audio.signal_level);
3093 }
3094
3095 if(fl_g->input_cfg_present_level->value() > 0)
3096 {
3097 fl_alert(_("Value must be a number between -90.0 and 0"));
3098 fl_g->input_cfg_present_level->value(-cfg.audio.signal_level);
3099 }
3100
3101 cfg.audio.signal_level = -fl_g->input_cfg_present_level->value();
3102 }
3103
input_cfg_absent_level_cb(void)3104 void input_cfg_absent_level_cb(void)
3105 {
3106 if(fl_g->input_cfg_absent_level->value() < -90)
3107 {
3108 fl_alert(_("Value must be a number between -90.0 and 0"));
3109 fl_g->input_cfg_absent_level->value(-cfg.audio.silence_level);
3110 }
3111
3112 if(fl_g->input_cfg_absent_level->value() > 0)
3113 {
3114 fl_alert(_("Value must be a number between -90.0 and 0"));
3115 fl_g->input_cfg_absent_level->value(-cfg.audio.silence_level);
3116 }
3117
3118 cfg.audio.silence_level = -fl_g->input_cfg_absent_level->value();
3119 }
3120
input_cfg_silence_cb(void)3121 void input_cfg_silence_cb(void)
3122 {
3123 // Values < 0 are not allowed
3124 if(fl_g->input_cfg_silence->value() < 0)
3125 {
3126 fl_g->input_cfg_silence->value(0);
3127 Fl::remove_timeout(&stream_silence_timer);
3128 }
3129 else
3130 Fl::add_timeout(1, &stream_silence_timer);
3131
3132
3133 cfg.main.silence_threshold = fl_g->input_cfg_silence->value();
3134 }
3135
input_rec_signal_cb(void)3136 void input_rec_signal_cb(void)
3137 {
3138 // Values < 0 are not allowed
3139 if(fl_g->input_rec_signal->value() <= 0)
3140 {
3141 fl_g->input_rec_signal->value(0);
3142 Fl::remove_timeout(&record_signal_timer);
3143 }
3144 else
3145 Fl::add_timeout(1, &record_signal_timer);
3146
3147 cfg.rec.signal_threshold = fl_g->input_rec_signal->value();
3148 }
3149
input_rec_silence_cb(void)3150 void input_rec_silence_cb(void)
3151 {
3152 // Values < 0 are not allowed
3153 if(fl_g->input_rec_silence->value() < 0)
3154 {
3155 fl_g->input_rec_silence->value(0);
3156 Fl::remove_timeout(&record_silence_timer);
3157 }
3158 else
3159 Fl::add_timeout(1, &record_silence_timer);
3160
3161 cfg.rec.silence_threshold = fl_g->input_rec_silence->value();
3162 }
3163
check_song_update_active_cb(void)3164 void check_song_update_active_cb(void)
3165 {
3166 if(fl_g->check_song_update_active->value())
3167 {
3168 if(connected)
3169 {
3170 static int reset = 1;
3171 Fl::remove_timeout(&songfile_timer);
3172 Fl::add_timeout(0.1, &songfile_timer, &reset);
3173 }
3174 cfg.main.song_update = 1;
3175 }
3176 else
3177 {
3178 Fl::remove_timeout(&songfile_timer);
3179 if (cfg.main.song != NULL)
3180 {
3181 free(cfg.main.song);
3182 cfg.main.song = NULL;
3183 }
3184 cfg.main.song_update = 0;
3185 }
3186 }
3187
check_read_last_line_cb(void)3188 void check_read_last_line_cb(void)
3189 {
3190 cfg.main.read_last_line = fl_g->check_read_last_line->value();
3191 }
3192
check_sync_to_full_hour_cb(void)3193 void check_sync_to_full_hour_cb(void)
3194 {
3195 if(fl_g->check_sync_to_full_hour->value())
3196 cfg.rec.sync_to_hour = 1;
3197 else
3198 cfg.rec.sync_to_hour = 0;
3199 }
3200
slider_gain_cb(void)3201 void slider_gain_cb(void)
3202 {
3203 float gain_db;
3204
3205 //Without redrawing the main window the slider knob is not redrawn correctly
3206 fl_g->window_main->redraw();
3207
3208 gain_db = (float)fl_g->slider_gain->value();
3209
3210 if((int)gain_db == 0)
3211 cfg.main.gain = 1;
3212 else
3213 cfg.main.gain = util_db_to_factor(gain_db);
3214
3215 fl_g->slider_gain->value_cb2("dB");
3216 }
3217
input_rec_split_time_cb(void)3218 void input_rec_split_time_cb(void)
3219 {
3220 // Values < 0 are not allowed
3221 if (fl_g->input_rec_split_time->value() < 0)
3222 {
3223 fl_g->input_rec_split_time->value(0);
3224 }
3225
3226 cfg.rec.split_time = fl_g->input_rec_split_time->value();
3227 }
3228
button_cfg_export_cb(void)3229 void button_cfg_export_cb(void)
3230 {
3231 char *filename;
3232
3233 Fl_My_Native_File_Chooser nfc;
3234
3235 nfc.title(_("Export to..."));
3236 nfc.type(Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE);
3237 nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER);
3238
3239
3240 switch(nfc.show())
3241 {
3242 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg()); //error
3243 return;
3244 break;
3245 case 1: return; // cancel
3246 break;
3247 default:
3248 filename = (char*)nfc.filename();
3249 }
3250
3251 cfg_write_file(filename);
3252 }
3253
button_cfg_import_cb(void)3254 void button_cfg_import_cb(void)
3255 {
3256 char *filename;
3257 char info_buf[256];
3258
3259 Fl_My_Native_File_Chooser nfc;
3260 nfc.title(_("Import..."));
3261 nfc.type(Fl_My_Native_File_Chooser::BROWSE_FILE);
3262
3263 switch(nfc.show())
3264 {
3265 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg()); //error
3266 return;
3267 break;
3268 case 1: return; // cancel
3269 break;
3270 default: filename = (char*)nfc.filename();
3271 break;
3272 }
3273
3274 //read config and initialize config struct
3275 if(cfg_set_values(filename) != 0)
3276 {
3277 snprintf(info_buf, sizeof(info_buf), _("Could not import config %s"), filename);
3278 print_info(info_buf, 1);
3279 return;
3280 }
3281
3282 //re-initialize some stuff after config has been successfully imported
3283 init_main_gui_and_audio();
3284 fill_cfg_widgets();
3285 snd_reinit();
3286
3287 snprintf(info_buf, sizeof(info_buf), _("Config imported %s"), filename);
3288 print_info(info_buf, 1);
3289 }
3290
check_update_at_startup_cb(void)3291 void check_update_at_startup_cb(void)
3292 {
3293 cfg.main.check_for_update = fl_g->check_update_at_startup->value();
3294 }
3295
button_cfg_check_for_updates_cb(void)3296 void button_cfg_check_for_updates_cb(void)
3297 {
3298 int rc;
3299 char uri[100];
3300 char *new_version;
3301 int ret = update_check_for_new_version();
3302
3303 switch(ret) {
3304 case UPDATE_NEW_VERSION:
3305 new_version = update_get_version();
3306 rc = fl_choice(_("New version available: %s\nYou have version %s"), _("Cancel"), _("Get new version"), NULL, new_version, VERSION);
3307 if(rc == 1)
3308 {
3309 //snprintf(uri, sizeof(uri)-1, "https://sourceforge.net/projects/butt/files/butt/butt-%s/", new_version);
3310 snprintf(uri, sizeof(uri)-1, "https://danielnoethen.de/butt/index.html#_download");
3311 fl_open_uri(uri);
3312 }
3313
3314 break;
3315 case UPDATE_SOCKET_ERROR:
3316 fl_alert(_("Could not get update information.\nReason: Network error"));
3317 break;
3318 case UPDATE_ILLEGAL_ANSWER:
3319 fl_alert(_("Could not get update information.\nReason: Unknown answer from server"));
3320 break;
3321 case UPDATE_UP_TO_DATE:
3322 fl_alert(_("You have the latest version!"));
3323 break;
3324 default:
3325 fl_alert(_("Could not get update information.\nReason: Unknown"));
3326 break;
3327 }
3328 }
3329
check_cfg_mono_to_stereo_cb(void)3330 void check_cfg_mono_to_stereo_cb(void)
3331 {
3332 cfg.audio.mono_to_stereo = fl_g->check_cfg_mono_to_stereo->value();
3333 }
3334
button_cfg_log_browse_cb(void)3335 void button_cfg_log_browse_cb(void)
3336 {
3337 Fl_My_Native_File_Chooser nfc;
3338 nfc.title(_("Select logfile..."));
3339 nfc.type(Fl_My_Native_File_Chooser::BROWSE_SAVE_FILE);
3340 nfc.options(Fl_My_Native_File_Chooser::NEW_FOLDER);
3341
3342 switch(nfc.show())
3343 {
3344 case -1: fl_alert(_("ERROR: %s"), nfc.errmsg());
3345 break;
3346 case 1:
3347 break; //cancel
3348 default:
3349 fl_g->input_log_filename->value(nfc.filename());
3350 input_log_filename_cb();
3351 }
3352 }
3353
window_main_close_cb(void)3354 void window_main_close_cb(void)
3355 {
3356
3357
3358 if(connected || recording)
3359 {
3360 int ret;
3361 if(connected)
3362 ret = fl_choice(_("butt is currently streaming.\n"
3363 "Do you really want to close butt now?"),
3364 _("no"), _("yes"), NULL);
3365 else
3366 ret = fl_choice(_("butt is currently recording.\n"
3367 "Do you really want to close butt now?"),
3368 _("no"), _("yes"), NULL);
3369
3370 if(ret == 0)
3371 return;
3372 }
3373
3374
3375 if (cfg.gui.remember_pos)
3376 {
3377 cfg.gui.x_pos = fl_g->window_main->x_root();
3378 cfg.gui.y_pos = fl_g->window_main->y_root();
3379 }
3380
3381 cfg_write_file(NULL);
3382 exit(0);
3383 }
3384
check_cfg_use_app_cb()3385 void check_cfg_use_app_cb()
3386 {
3387 if(fl_g->check_cfg_use_app->value())
3388 {
3389 int app = fl_g->choice_cfg_app->value();
3390 current_track_app = getCurrentTrackFunctionFromId(app);
3391 cfg.main.app_update = 1;
3392 cfg.main.app_update_service = app;
3393
3394 static int reset = 1;
3395 Fl::remove_timeout(&app_timer);
3396 Fl::add_timeout(0.1, &app_timer, &reset);
3397 }
3398 else
3399 {
3400 cfg.main.app_update = 0;
3401 Fl::remove_timeout(&app_timer);
3402
3403 if (cfg.main.song != NULL)
3404 {
3405 free(cfg.main.song);
3406 cfg.main.song = NULL;
3407 }
3408 }
3409 }
3410
choice_cfg_app_cb()3411 void choice_cfg_app_cb()
3412 {
3413 current_track_app = getCurrentTrackFunctionFromId(fl_g->choice_cfg_app->value());
3414 cfg.main.app_update_service = fl_g->choice_cfg_app->value();
3415 }
3416
check_activate_eq_cb(void)3417 void check_activate_eq_cb(void)
3418 {
3419 cfg.dsp.equalizer = fl_g->check_activate_eq->value();
3420 }
3421
slider_equalizer1_cb(double v)3422 void slider_equalizer1_cb(double v)
3423 {
3424 static char str[10];
3425 cfg.dsp.gain1 = v;
3426 snprintf(str, 10, "%+.1f", v);
3427 fl_g->equalizerGain1->label(str);
3428 fl_g->equalizerSlider1->value_cb2("dB"); // updates the tooltip
3429
3430 }
3431
slider_equalizer2_cb(double v)3432 void slider_equalizer2_cb(double v)
3433 {
3434 static char str[10];
3435 cfg.dsp.gain2 = v;
3436 snprintf(str, 10, "%+.1f", v);
3437 fl_g->equalizerGain2->label(str);
3438 fl_g->equalizerSlider2->value_cb2("dB");
3439 }
3440
slider_equalizer3_cb(double v)3441 void slider_equalizer3_cb(double v)
3442 {
3443 static char str[10];
3444 cfg.dsp.gain3 = v;
3445 snprintf(str, 10, "%+.1f", v);
3446 fl_g->equalizerGain3->label(str);
3447 fl_g->equalizerSlider3->value_cb2("dB");
3448 }
3449
slider_equalizer4_cb(double v)3450 void slider_equalizer4_cb(double v)
3451 {
3452 static char str[10];
3453 cfg.dsp.gain4 = v;
3454 snprintf(str, 10, "%+.1f", v);
3455 fl_g->equalizerGain4->label(str);
3456 fl_g->equalizerSlider4->value_cb2("dB");
3457 }
3458
slider_equalizer5_cb(double v)3459 void slider_equalizer5_cb(double v)
3460 {
3461 static char str[10];
3462 cfg.dsp.gain5 = v;
3463 snprintf(str, 10, "%+.1f", v);
3464 fl_g->equalizerGain5->label(str);
3465 fl_g->equalizerSlider5->value_cb2("dB");
3466 }
3467
3468
check_activate_drc_cb(void)3469 void check_activate_drc_cb(void)
3470 {
3471 cfg.dsp.compressor = fl_g->check_activate_drc->value();
3472 }
3473
slider_threshold_cb(double v)3474 void slider_threshold_cb(double v)
3475 {
3476 static char str[10];
3477 cfg.dsp.threshold = v;
3478 snprintf(str, 10, "%+.1f", v);
3479 fl_g->threshold->label(str);
3480 fl_g->thresholdSlider->value_cb2("dBFS"); // updates the tooltip
3481
3482 }
3483
slider_ratio_cb(double v)3484 void slider_ratio_cb(double v)
3485 {
3486 static char str[10];
3487 cfg.dsp.ratio = v;
3488 snprintf(str, 10, "%.1f", v);
3489 fl_g->ratio->label(str);
3490 fl_g->ratioSlider->value_cb2(":1");
3491 }
3492
slider_attack_cb(double v)3493 void slider_attack_cb(double v)
3494 {
3495 static char str[10];
3496 cfg.dsp.attack = v;
3497 snprintf(str, 10, "%.1fs", v);
3498 fl_g->attack->label(str);
3499 fl_g->attackSlider->value_cb2("s");
3500 }
3501
slider_release_cb(double v)3502 void slider_release_cb(double v)
3503 {
3504 static char str[10];
3505 cfg.dsp.release = v;
3506 snprintf(str, 10, "%.1fs", v);
3507 fl_g->release->label(str);
3508 fl_g->releaseSlider->value_cb2("s");
3509 }
3510
slider_makeup_cb(double v)3511 void slider_makeup_cb(double v)
3512 {
3513 static char str[10];
3514 cfg.dsp.makeup_gain = v;
3515 snprintf(str, 10, "%+.1f", v);
3516 fl_g->makeup->label(str);
3517 fl_g->makeupSlider->value_cb2("dB");
3518 }
3519
3520