/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#+
#+     Glade / Gtk Programming
#+
#+     Copyright (C) 2019 by Kevin C. O'Kane
#+
#+     Kevin C. O'Kane
#+     kc.okane@gmail.com
#+     https://www.cs.uni.edu/~okane
#+     http://threadsafebooks.com/
#+
#+ This program is free software; you can redistribute it and/or modify
#+ it under the terms of the GNU General Public License as published by
#+ the Free Software Foundation; either version 2 of the License, or
#+ (at your option) any later version.
#+
#+ This program is distributed in the hope that it will be useful,
#+ but WITHOUT ANY WARRANTY; without even the implied warranty of
#+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#+ GNU General Public License for more details.
#+
#+ You should have received a copy of the GNU General Public License
#+ along with this program; if not, write to the Free Software
#+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#+
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

// August 24, 2019

#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <gtk/gtk.h>
#include <gtk/gtkx.h>
#include <math.h>
#include <time.h>
#include <ctype.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/shm.h>

#define ENCODER_WIDTH 454
#define ENCODER_HEIGHT 292
#define WINDOW_BAR 30

GtkWidget		*window; // main window
GtkWidget		*fixed1;
GtkWidget		*start;
GtkWidget		*encImage;
GtkWidget		*castImage;
GtkWidget		*fpsImage;
GtkWidget		*keyImage;
GtkWidget		*audioImage;
GtkWidget		*lib264Image;
GtkWidget		*castSize;
GtkWidget		*label1;
GtkWidget		*radio1;
GtkWidget		*radio2;
GtkWidget		*radio3;
GtkWidget		*radio4;
GtkWidget		*radio640x480;
GtkWidget		*xga;
GtkWidget		*svga;
GtkWidget		*wxga;
GtkWidget		*s1536x864;
GtkWidget		*s1600x900;
GtkWidget		*s640x360;
GtkWidget		*server;
GtkWidget		*key;
GtkWidget		*fps1;
GtkWidget		*fps2;
GtkWidget		*fps10;
GtkWidget		*fps20;
GtkWidget		*ScreenOnly;
GtkWidget		*testCast;
GtkWidget		*CameraOnly;
GtkWidget		*kframe1; 
GtkWidget		*kframe5; 
GtkWidget		*kframe10; 
GtkWidget		*crf20; 
GtkWidget		*crf25; 
GtkWidget		*crf15; 
GtkWidget		*crf30; 
GtkWidget		*veryfast; 
GtkWidget		*faster; 
GtkWidget		*fast; 
GtkWidget		*medium; 
GtkWidget		*audio128; 
GtkWidget		*audio160; 
GtkWidget		*route; 
GtkWidget		*source1; 
GtkWidget		*source2; 
GtkWidget		*tooltips; 
GtkWidget		*player; 
GtkWidget		*okay; 
GtkBuilder		*builder; 

void	exportEnv();

int	audioBitRate = 160, crf = 25, keyframe = 150, fps = 24, 
		numChan = 1, audChan = 1, screenCast = 1, X, Y, H, W;
int	firstTime = 1, castOn = 0, loopback = 0; // loopback
double	D;

char	preset[64] = "fast";
char	rtmpServer[2048] = "<none>";
char	rtmpKey[2048] = "<none>";

char	monitor[2048] = "<none>";
char	microphone[2048] = "<none>";
char	defaultSink[2048] = "<none>";
char	altSink[2048] = "<none>";
char	altMic[2048] = "<none>";
char	altMon[2048] = "<none>";

gboolean	timer_handler();
void		on_destroy(); 

char	default_source[1024] = "";
char	default_sink[1024] = "";

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// paint css on a widget
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void    css_set(GtkCssProvider * cssProvider, GtkWidget *g_widget) {

        GtkStyleContext *context;

        context = gtk_widget_get_style_context(g_widget);
        gtk_style_context_add_provider (context,
                GTK_STYLE_PROVIDER(cssProvider), 500);
        gtk_style_context_save (context);
        }


int main(int argc, char *argv[]) {

	char cmd[2048];

	gtk_init(&argc, &argv); // init Gtk

	builder = gtk_builder_new_from_resource ("/part1/part1.glade");
 
	window = GTK_WIDGET(gtk_builder_get_object(builder, "window")); // main window

	g_signal_connect(window, "destroy", G_CALLBACK(on_destroy), NULL);

        gtk_builder_connect_signals(builder, NULL);

	fixed1		= GTK_WIDGET(gtk_builder_get_object(builder, "fixed1"));
	start		= GTK_WIDGET(gtk_builder_get_object(builder, "start"));
	encImage	= GTK_WIDGET(gtk_builder_get_object(builder, "encImage"));
	route		= GTK_WIDGET(gtk_builder_get_object(builder, "route"));
	castImage	= GTK_WIDGET(gtk_builder_get_object(builder, "castImage"));
	fpsImage	= GTK_WIDGET(gtk_builder_get_object(builder, "fpsImage"));
	keyImage	= GTK_WIDGET(gtk_builder_get_object(builder, "keyImage"));
	audioImage	= GTK_WIDGET(gtk_builder_get_object(builder, "audioImage"));
	castSize	= GTK_WIDGET(gtk_builder_get_object(builder, "castSize"));
	lib264Image	= GTK_WIDGET(gtk_builder_get_object(builder, "lib264Image"));
	label1		= GTK_WIDGET(gtk_builder_get_object(builder, "label1"));
	radio1		= GTK_WIDGET(gtk_builder_get_object(builder, "radio1"));
	radio2		= GTK_WIDGET(gtk_builder_get_object(builder, "radio2"));
	radio3		= GTK_WIDGET(gtk_builder_get_object(builder, "radio3"));
	radio4		= GTK_WIDGET(gtk_builder_get_object(builder, "radio4"));
	radio640x480	= GTK_WIDGET(gtk_builder_get_object(builder, "radio640x480"));
	xga		= GTK_WIDGET(gtk_builder_get_object(builder, "xga"));
	svga		= GTK_WIDGET(gtk_builder_get_object(builder, "svga"));
	wxga		= GTK_WIDGET(gtk_builder_get_object(builder, "wxga"));
	s1536x864	= GTK_WIDGET(gtk_builder_get_object(builder, "s1536x864"));
	s1600x900	= GTK_WIDGET(gtk_builder_get_object(builder, "s1600x900"));
	s640x360	= GTK_WIDGET(gtk_builder_get_object(builder, "s640x360"));
	server		= GTK_WIDGET(gtk_builder_get_object(builder, "server"));
	fps1		= GTK_WIDGET(gtk_builder_get_object(builder, "fps1"));
	fps2		= GTK_WIDGET(gtk_builder_get_object(builder, "fps2"));
	fps10		= GTK_WIDGET(gtk_builder_get_object(builder, "fps10"));
	fps20		= GTK_WIDGET(gtk_builder_get_object(builder, "fps20"));
	key		= GTK_WIDGET(gtk_builder_get_object(builder, "key"));
	source1		= GTK_WIDGET(gtk_builder_get_object(builder, "source1"));
	source2		= GTK_WIDGET(gtk_builder_get_object(builder, "source2"));
	ScreenOnly	= GTK_WIDGET(gtk_builder_get_object(builder, "ScreenOnly"));
	testCast	= GTK_WIDGET(gtk_builder_get_object(builder, "testCast"));
	CameraOnly	= GTK_WIDGET(gtk_builder_get_object(builder, "CameraOnly"));
	kframe1		= GTK_WIDGET(gtk_builder_get_object(builder, "kframe1"));
	kframe5		= GTK_WIDGET(gtk_builder_get_object(builder, "kframe5"));
	kframe10	= GTK_WIDGET(gtk_builder_get_object(builder, "kframe10"));
	crf20		= GTK_WIDGET(gtk_builder_get_object(builder, "crf20"));
	crf25		= GTK_WIDGET(gtk_builder_get_object(builder, "crf25"));
	crf15		= GTK_WIDGET(gtk_builder_get_object(builder, "crf15"));
	crf30		= GTK_WIDGET(gtk_builder_get_object(builder, "crf30"));
	veryfast	= GTK_WIDGET(gtk_builder_get_object(builder, "veryfast"));
	faster		= GTK_WIDGET(gtk_builder_get_object(builder, "faster"));
	fast		= GTK_WIDGET(gtk_builder_get_object(builder, "fast"));
	audio128	= GTK_WIDGET(gtk_builder_get_object(builder, "audio128"));
	audio160	= GTK_WIDGET(gtk_builder_get_object(builder, "audio160"));
	medium		= GTK_WIDGET(gtk_builder_get_object(builder, "medium"));
	tooltips	= GTK_WIDGET(gtk_builder_get_object(builder, "tooltips"));
	player		= GTK_WIDGET(gtk_builder_get_object(builder, "player"));
	okay		= GTK_WIDGET(gtk_builder_get_object(builder, "okay"));

	g_object_unref(builder);

//	======================================================
//	Paint the application with a font restriction.
//	All fonts under 'window' will be restricted to
//	12px Noto Sans. This is due to different window
//	managers using different fonts and messing up
//	the layout. Adjust as needed.
//	======================================================

	GtkCssProvider  *cssProvider1;
        cssProvider1  = gtk_css_provider_new();
        gtk_css_provider_load_from_data(cssProvider1, 
		"* { font: 12px Ubuntu; }", -1, NULL);
        css_set(cssProvider1, window);


//	gtk_window_set_keep_above (GTK_WINDOW(window), TRUE); // optional

	gtk_widget_show(window);

//	Invoke timer every second:
	g_timeout_add_seconds(1, (GSourceFunc) timer_handler, NULL);

        GdkColor color; // background colors
        color.red = 0x3333;
        color.green = 0x3333;
        color.blue = 0x9999;
        gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color);

//	Default casting window definition

	H = 720;	 // height
	W = 1280;	// width
	X = 4;		// horizontal coordinate
	Y = 30;		// vertical coordinate
	gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
	gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left

// 	Color the backgrounds

        color.red	= 0x6666;
        color.green	= 0xdddd;
        color.blue	= 0x6666;

	gtk_widget_modify_bg(ScreenOnly, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(CameraOnly, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(castImage, GTK_STATE_NORMAL, &color);

        color.red	= 0xdddd;
        color.green	= 0x5555;
        color.blue	= 0xdddd;

	gtk_widget_modify_bg(kframe1, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(kframe5, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(kframe10, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(keyImage, GTK_STATE_NORMAL, &color);

        color.red	= 0x6666;
        color.green	= 0xdddd;
        color.blue	= 0xdddd;

	gtk_widget_modify_bg(fps1, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(fps2, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(fps10, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(fps20, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(fpsImage, GTK_STATE_NORMAL, &color);

        color.red	= 0xdddd;
        color.green	= 0xdddd;
        color.blue	= 0x4444;

	gtk_widget_modify_bg(radio1, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(radio2, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(radio3, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(radio4, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(radio640x480, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(xga, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(svga, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(castSize, GTK_STATE_NORMAL, &color);

        color.red	= 0xe800;
        color.green	= 0xe900;
        color.blue	= 0xb300;

	gtk_widget_modify_bg(audioImage, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(audio128, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(audio160, GTK_STATE_NORMAL, &color);

        color.red	= 0xe900;
        color.green	= 0xe900;
        color.blue	= 0xe900;

	system("killall Player-bin");
	system("killall vlc");

//	--------------------------------------------------------------------------------
//	Find the default PulseAudio sources.
//	This selects the first two sources which are taken as the monitor and microphone.
//	--------------------------------------------------------------------------------

	strcpy(monitor, 
		"bash -c \"pactl list short sources | head -4 | cut -d $\'\\t\' -f2-2\"");

	FILE *f1 = popen(monitor, "r");

	if (f1 == NULL ) {
		printf("*** pulse source error\n");
		return EXIT_FAILURE;
		}

	fgets(monitor,1024,f1);
	monitor[strlen(monitor)-1] = 0; // new line character chopped

	fgets(microphone,1024,f1);
	microphone[strlen(microphone)-1] = 0; // new line character chopped

	if (fgets(altMon,1024,f1)) { numChan = 2; altMon[strlen(altMon)-1] = 0; } // new line 
	else { strcpy(altMon,""); }

	if (fgets(altMic,1024,f1)) altMic[strlen(altMic)-1] = 0; // new line 
	else strcpy(altMic,"");

	fclose(f1);

	strcpy(defaultSink, 
		"bash -c \"pactl list short sinks | head -2 | cut -d $\'\\t\' -f2-2\"");

	f1 = popen(defaultSink, "r");

	if (f1 == NULL ) {
		printf("*** pulse source error\n");
		return EXIT_FAILURE;
		}

	fgets(defaultSink,1024,f1);
	defaultSink[strlen(defaultSink)-1] = 0; // new line char chopped

	if (fgets(altSink,1024,f1)) altSink[strlen(altSink)-1] = 0; // new line char chopped
	else strcpy(altSink,"");

	fclose(f1);

	printf("\nPulseAudio components: \n");
	printf("mic 1  = %s\n", microphone);
	printf("mon 1  = %s \n", monitor);
	printf("sink 1 = %s\n", defaultSink);
	printf("sink 2 = %s\n", altSink);
	printf("mon 2  = %s\n", altMon);
	printf("mic 2  = %s\n", altMic);

        loopback = 1;

        printf("\nCreate PulseAudio loopback stream (msgs may be out of order):\n");

        system("pactl unload-module module-null-sink");
                printf("pactl unload-module module-null-sink\n");

        system("pactl unload-module module-loopback");
                printf("pactl unload-module module-loopback\n");

        system("pactl unload-module module-stream-restore");
                printf("pactl unload-module module-stream-restore\n");

	printf("....................................\n");

        system("pactl load-module module-null-sink sink_name=casting");
                printf("pactl load-module module-null-sink sink_name=casting\n");

	sprintf(cmd, "pactl load-module module-loopback source=%s sink=casting", monitor);
	system(cmd);
	printf("%s\n", cmd);

	sprintf(cmd, "pactl load-module module-loopback source=%s sink=casting", microphone);
	system(cmd);
	printf("%s\n", cmd);

	if (numChan > 1) {

	        system("pactl load-module module-null-sink sink_name=encoder");
                printf("pactl load-module module-null-sink sink_name=encoder\n");

		sprintf(cmd, "pactl load-module module-loopback source=encoder.monitor sink=%s", altSink);
		system(cmd);
		printf("%s\n", cmd);

		sprintf(cmd, "pactl load-module module-loopback source=%s sink=casting", altMon); // reroute audio
		system(cmd);
		printf("%s\n", cmd);

		sprintf(cmd, "pactl load-module module-loopback source=%s sink=casting", altMic);
		system(cmd);
		printf("%s\n", cmd);
		}

        color.red	= 0xc100;
        color.green	= 0x7000;
        color.blue	= 0x1100;

	gtk_widget_modify_bg(encImage, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(crf20, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(crf25, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(crf15, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(crf30, GTK_STATE_NORMAL, &color);

        color.red	= 0x7200;
        color.green	= 0x9f00;
        color.blue	= 0xcf00;

	gtk_widget_modify_bg(lib264Image, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(veryfast, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(fast, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(faster, GTK_STATE_NORMAL, &color);
	gtk_widget_modify_bg(medium, GTK_STATE_NORMAL, &color);

	gtk_entry_set_text(GTK_ENTRY(server), rtmpServer);
	gtk_entry_set_text(GTK_ENTRY(key), "********");


//	gtk_widget_hide(player);
	gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(player));

	if (numChan > 1 ) gtk_widget_hide(route);
            
	gtk_main();

	return EXIT_SUCCESS;
	}

void	on_destroy() {	// called when the main window terminates

		char cmd[1024];

		printf("\nExit encoder - restore Pulse defaults\n");

//		restore Pulse streams

		printf("pactl unload-module module-null-sink\n");
		system("pactl unload-module module-null-sink");
	
		printf("pactl unload-module module-loopback\n");
		system("pactl unload-module module-loopback");

		sprintf(cmd, "pactl set-default-source %s", microphone);
		printf("%s\n", cmd);
		system (cmd);

		sprintf(cmd, "pactl set-default-sink %s\n", defaultSink);
		printf("%s\n", cmd);
		system (cmd);

		system ("killall ffmpeg");
		system ("killall vlc");

		system("pulseaudio -k"); // unload all added modules
		system("wait 1");

		castOn = 0;

		gtk_main_quit();
		}

//	The following is called when the casting window is closed or destroyed.
//	It does not destroy, just hides. It will be destroyed when the main
//	window is destroyed.

gboolean timer_handler() { // every second
	char cmd[1024];

	if (firstTime) {
		firstTime = 0;

		FILE *f2 = popen("ps -ale | grep Player-bin", "r");
		cmd[0] = 0;
		if (fgets(cmd, 1024, f2) != NULL) {
			gtk_message_dialog_format_secondary_text (
				GTK_MESSAGE_DIALOG(player),
				"There is an instance of Player-bin running.\n"
				"You must re-start it to use the encoder audio channels.");
			gtk_widget_show(player);
			}
		fclose(f2);

		if (numChan < 2 ) {
			gtk_message_dialog_format_secondary_text (
				GTK_MESSAGE_DIALOG(player),
				"There is one audio card present.\n\n"
				"You should click the button to run\n"
				"'route.script' if you want local\n"
				"audio feedback of your broadcast.\n\n"
				"Running 'route.script' will close\n"
				"any instances of VLC or Player-bin.\n"
				"These will need to be re-started.\n"
				"If you are running any other players,\n"
				"you will need to re-start these as well\n\n"
				"Depending on your audio card, You may\n"
				"need to adjust your microphone level in\n"
				"Pulse Audio Control (real name: pavucontrol).\n\n"
				"When you have finished with the encoder,\n"
				"you may need to re-start PulseAudio\n"
				"(pulseaudio -k).");
			gtk_widget_show(player);
			}
		else {
			gtk_message_dialog_format_secondary_text (
				GTK_MESSAGE_DIALOG(player),
				"A second audio card has been detected.\n\n"
				"All instances of Player-bin and vlc have\n"
				"closed. They must be restarted due\n"
				"to the creation of virtual audio channels.\n"
				"You should close and re-start any other\n"
				"players as well.\n\n"
				"Your primary card will be used for \n"
				"microphone input and audio processing\n"
				"while the audio feedback of your cast \n"
				"will appear on the second card's speaker\n"
				"output jack\n\n"
				"You may need to adjust the microphone level\n"
				"for your primary card using Pulse Audio\n"
				"Control (real name: pavucontrol).\n\n"
				"When finished, you may need to re-start\n"
				"PulseAudio (pulseaudio -k)\n");
			gtk_widget_show(player);
			}
		}

        return TRUE;
        }

gboolean	on_start_state_set(GtkWidget *b) {

	char cmd[2048];

	if (! gtk_switch_get_active(GTK_SWITCH(b))) {
		system ("killall ffmpeg");
		printf("*** stop ffmpeg\n");
		castOn = 0;
		return TRUE;
		}

//	The delay factor (can be +/-). If your audio and video are out of sync,
//	play with this. The setting is hardware dependent.

	D = 0.01;

// .......................................
//	Some standard video sizes:

//		hd720 means 1280x720
//		hd480 means 852x480
//		nhd means 640x360
//		vga means 640x480
//		ntsc means 720x480
//		xga means 1024x768
//		svga means 800x600
// .......................................

	char audSource[1024];

	if (screenCast == 1) {	// the main ffmpeg command
		
		if (strcmp(rtmpServer,"<none>") == 0 ) {
			gtk_message_dialog_format_secondary_text (
				GTK_MESSAGE_DIALOG(player),
				"The rtmpServer field is invalid.");
			gtk_widget_show(player);
			gtk_switch_set_active(GTK_SWITCH(start), FALSE);
			return TRUE;
			}
		
		if (strcmp(rtmpKey,"<none>") == 0 ) {
			gtk_message_dialog_format_secondary_text (
				GTK_MESSAGE_DIALOG(player),
				"The rtmpKey field is invalid.");
			gtk_widget_show(player);
			gtk_switch_set_active(GTK_SWITCH(start), FALSE);
			return TRUE;
			}

		sprintf(cmd,

                        "ffmpeg -hide_banner -loglevel error -threads 0 -thread_queue_size 16384 "
                        " -ar 44100 "
			"-f pulse -i casting.monitor "
			"-itsoffset %.2f "
                        "-f x11grab "
                        "-video_size %dx%d "
                        "-i :0.0+%d,%d "
                        " -r %d "
                        "-c:v libx264 -preset %s "
                        "-framerate %d "
                        "-crf %d -b:v 2M -maxrate 3M -bufsize 20M "
                        "-vf \"format=yuv420p\" "
                        "-g %d "
                        "-c:a aac "
                        "-b:a %dk "
                        "-f flv %s/%s &",

                        D, W, H, X + 494, Y, fps,
                        preset, fps, crf, keyframe, audioBitRate,
                        rtmpServer,rtmpKey);

		}

	else if (screenCast == 2) {
              sprintf(cmd,

                        "ffmpeg -hide_banner -loglevel error -threads 0 -thread_queue_size 16384 "
                        " -ar 44100 "
			"-f pulse -i casting.monitor "
			"-f pulse -i %s "
			"-itsoffset %.2f "
                        "-f x11grab "
                        "-video_size %dx%d "
                        "-i :0.0+%d,%d "
                        " -r %d "
                        "-c:v libx264 -preset %s "
                        "-framerate %d "
                        "-crf %d -b:v 2M -maxrate 3M -bufsize 20M "
                        "-vf \"format=yuv420p\" "
                        "-g %d "
                        "-c:a aac "
                        "-b:a %dk "
                        "-y -f mp4 test.mp4 &",

                        microphone, D, W, H, X + 494, Y, fps,
                        preset, fps, crf, keyframe, audioBitRate);
		}

	else {	// casting a video source only (/dev/video0)
		sprintf(cmd,
	
        		"ffmpeg -hide_banner -loglevel error -threads 0 -thread_queue_size 16384 "
			" -ar 44100 "
        		"-f pulse -i casting.monitor "
			"-itsoffset %.2f "
        		"-i /dev/video0 "
			" -r %d "
			"-c:v libx264 -preset %s "
			"-framerate %d "
        		"-crf %d -b:v 2M -maxrate 3M -bufsize 20M "
        		"-vf \"format=yuv420p\" "
			"-g %d "
        		"-c:a aac "
			"-b:a %dk "
			"-f flv %s/%s &",
	
			D, fps, preset, fps, crf, keyframe, audioBitRate,
			rtmpServer,rtmpKey);
		}

 	system (cmd) ;
	castOn = 1;

// 	Display ffmpeg command with server key not shown

	for (int i=0; cmd[i] != 0; i++) 
		if (strncmp(&cmd[i], "-f flv", 6) == 0) cmd[i+6] = 0; 

	strcat(cmd, " server/key"); // replace real server name and key

	printf("\n*****************************************************\n");
	printf("%s\n", cmd);
	printf("*****************************************************\n\n");

	return FALSE;
	}

void	on_source1_toggled(GtkWidget *b) {

	char cmd[2048];

	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		audChan = 1;

		sprintf(cmd, "pactl set-default-source %s", microphone);
		printf("%s\n", cmd);
		system (cmd);

		sprintf(cmd, "pactl set-default-sink %s\n", defaultSink);
		printf("%s\n", cmd);
		system (cmd);
		}
	}

void	on_source2_toggled(GtkWidget *b) {

	char cmd[2048];

	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		audChan = 2;

		sprintf(cmd, "pactl set-default-source %s", altMic);
		printf("%s\n", cmd);
		system (cmd);

		sprintf(cmd, "pactl set-default-sink %s\n", altSink);
		printf("%s\n", cmd);
		system (cmd);
		}
	}

//	Establish casting window dimensions when radio button set.


void	on_radio1_toggled(GtkWidget *b) { // 1920x1080

	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 1080; W = 1920; X = Y = 0;
		gtk_window_resize (GTK_WINDOW(window), 1, 1 ); // full screen
//		gtk_widget_hide(window2); // hide casting area
		exportEnv();
		}
	}

void	on_radio2_toggled(GtkWidget *b) { // 1280x720
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 720;
		W = 1280; 
		X = 4;
		Y = 30;
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		exportEnv();
		}
	}

void	on_radio3_toggled(GtkWidget *b) { // 852x480
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 480;
		W = 852;
		X = 4;
		Y = 30;
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left

		exportEnv();
		}
	}

void	on_radio4_toggled(GtkWidget *b) { // 720x480
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 480;
		W = 720;
		X = 4;
		Y = 30;
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		exportEnv();
		}
	}

void	on_radio640x480_toggled(GtkWidget *b) { // 640x480
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 480;
		W = 640;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_svga_toggled(GtkWidget *b) { // 800x600
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 600;
		W = 800;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_wxga_toggled(GtkWidget *b) { 
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 980;
		W = 1440;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_s1536x864_toggled(GtkWidget *b) { 
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		W = 1536;
		H = 864;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_s1600x900_toggled(GtkWidget *b) { 
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		W = 1600;
		H = 900;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_s640x360_toggled(GtkWidget *b) { 
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		W = 640;
		H = 360;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

void	on_xga_toggled(GtkWidget *b) { // 1024x768
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		H = 768;
		W = 1024;
		X = 4;
		Y = 30;
		exportEnv();
		gtk_window_resize (GTK_WINDOW(window), W + 495, H ); 
		gtk_window_move(GTK_WINDOW(window), 0, 0); // move window to upper left
		}
	}

//	More radio buttons

void	on_ScreenOnly_toggled(GtkWidget *b) {
	screenCast = 1;
	}

void	on_CameraOnly_toggled(GtkWidget *b) {
	screenCast = 0;
	}

//	A server URL has been pasted into the entry box

void	on_server_changed(GtkWidget *e) {
        char tmp[128];
        strcpy(rtmpServer, gtk_entry_get_text(GTK_ENTRY(e)));
        }

//	A casting key has been pasted into the entry box

void	on_key_changed(GtkWidget *e) {
	char tmp[1024];
        strcpy(tmp, gtk_entry_get_text(GTK_ENTRY(e)));
	if (tmp[0] == '*') return;
	strcpy(rtmpKey,tmp);
	gtk_entry_set_invisible_char (GTK_ENTRY(e), '*'); // don't show the key
	gtk_entry_set_visibility (GTK_ENTRY(e), FALSE);
	}

//	more radio buttons

void	on_fps1_toggled(GtkWidget *b) { fps = 24; }
void	on_fps2_toggled(GtkWidget *b) { fps = 30; }
void	on_fps10_toggled(GtkWidget *b) { fps = 10; }
void	on_fps20_toggled(GtkWidget *b) { fps = 20; }

void	on_kframe1_toggled(GtkWidget *b) { keyframe = fps; }
void	on_kframe5_toggled(GtkWidget *b) { keyframe = fps * 5; }
void	on_kframe10_toggled(GtkWidget *b) { keyframe = fps * 10; }

void	on_crf20_toggled(GtkWidget *b) { crf = 20; }
void	on_crf25_toggled(GtkWidget *b) { crf = 25; }
void	on_crf15_toggled(GtkWidget *b) { crf = 15; }
void	on_crf30_toggled(GtkWidget *b) { crf = 30; }

void	on_veryfast_toggled(GtkWidget *b) { strcpy(preset, "veryfast"); }
void	on_fast_toggled(GtkWidget *b) { strcpy(preset, "fast"); }
void	on_faster_toggled(GtkWidget *b) { strcpy(preset, "faster"); }
void	on_medium_toggled(GtkWidget *b) { strcpy(preset, "medium"); }

void	on_audio128_toggled(GtkWidget *b) { audioBitRate = 128; }
void	on_audio160_toggled(GtkWidget *b) { audioBitRate = 160; }

void	exportEnv() { // not presently used
	char *t1, cmd[1024];

	t1 = getenv("HOME");
	if (!t1) return;

	sprintf(cmd,"%s/SGR-Encoder.conf", t1);

	FILE *f1 = fopen(cmd,"w");
	fprintf(f1,"%d %d %d %d\n", H, W, X + ENCODER_WIDTH, Y + ENCODER_HEIGHT);
	fclose(f1);
	}

void	on_tooltips_toggled(GtkWidget *b) {  // turn on/off the tooltips
	if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(b))) {
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio1), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio2), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio3), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio4), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio640x480), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(xga), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(svga), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(wxga), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s1536x864), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s1600x900), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s640x360), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(server), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(key), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps1), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps2), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps10), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps20), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(ScreenOnly), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(CameraOnly), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe1), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe5), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe10), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf20), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf25), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf30), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(veryfast), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(faster), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fast), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(medium), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(audio128), FALSE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(audio160), FALSE);
		}
	else {
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio1), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio2), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio3), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio4), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(radio640x480), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(xga), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(svga), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(wxga), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s1536x864), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s1600x900), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(s640x360), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(server), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(key), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps1), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps2), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps10), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fps20), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(ScreenOnly), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(CameraOnly), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe1), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe5), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(kframe10), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf20), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf25), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(crf30), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(veryfast), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(faster), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(fast), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(medium), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(audio128), TRUE);
		gtk_widget_set_has_tooltip (GTK_WIDGET(audio160), TRUE);
		}
	}

void	on_okay_clicked(GtkWidget *b) {
//		gtk_widget_destroy(b);
		gtk_widget_hide(player);
		}

void	on_route_clicked (GtkWidget *b) {
		int i;
		char cmd[1024], directory[1024];

		readlink("/proc/self/exe", directory, 1024); // where are we?

		for (i = strlen(directory); i > 0; i--)
			if (directory[i] == '/' ) {
			directory[i] = 0;
			break;
			}

		strcpy(directory, "route.output");

		strcpy(cmd, "route.script > ");
		strcat(cmd, directory );

		i = system(cmd);

		if ( i == 0 ) { // no error
			gtk_widget_hide(route);
			return;
			}

		gtk_message_dialog_format_secondary_text (
			GTK_MESSAGE_DIALOG(player),
			"The file 'route.script' returned an error code.\n"
			"The audio channels were not correctly configured.");
		gtk_widget_show(player);
		}

void	on_testCast_toggled(GtkButton *b) {
	screenCast = 2;
	}

gboolean on_audioImage_query_tooltip(GtkWidget *widget,gint x,gint y,
                gboolean keyboard, GtkTooltip *tooltip) {
        char tip[4096];
	strcpy(tip, "Mon: ");
	strcat(tip, monitor);
	strcat(tip, "\nMic: ");
	strcat(tip, microphone);
	strcat(tip, "\nSink: ");
	strcat(tip, defaultSink);
	strcat(tip, "\nAlt Sink: ");
	strcat(tip, altSink);
	strcat(tip, "\nAlt Mic: ");
	strcat(tip, altMic);
	strcat(tip, "\nAlt Mon: ");
	strcat(tip, altMon);
        gtk_tooltip_set_text(tooltip, tip);
        return 1;
        }

