/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#+
#+     Internet Radio Automation & Encoding Toolkit
#+
#+     Copyright (C) 2018 - 2025 by Kevin C. O'Kane
#+
#+     Kevin C. O'Kane
#+     kc.okane@gmail.com
#+     https://www.cs.uni.edu/~okane
#+     https://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
#+
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

//	Sept 18, 2025

//------------------------------------------------------------------
//	This is the root file for the Linux version of the player
//------------------------------------------------------------------

#define _GNU_SOURCE

#include "common/includes.h"
#include "common/structures.h"
#include "common/defines.h"
#include "common/common-fcn-headers.h"
#include "common/global-vars.h"
#include "common/common-widgets.h"
#include "common/common-externs.h"
#include "common/common-fcn-headers.h"

WebKitWebView *webView = NULL;

struct THR1 thr_data;

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// main main main main main main main main main main main main main
// main main main main main main main main main main main main main
// main main main main main main main main main main main main main
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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

	char cmd[2048], tmp[2048];
	int i, j, k, m, n;

//----------------------------------
//	Pulse Audio interface init
//----------------------------------

	context_source = NULL;
	context_sink = NULL;
	stream_sink = NULL;
	stream_source = NULL;
	device_name_source = NULL;
	device_name_sink = NULL;
	device_description_source = NULL;
	device_description_sink = NULL;

//--------------------------------------------------------------
//	Following must be called before any other X11 calls
//	Needed in order to enable vdpau in vlc in Windows WSL2
//--------------------------------------------------------------

	setenv("GDK_BACKEND", "x11", 1);
	setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1", 1); // correct nvidia issue

	XInitThreads();

	printf("\n-------- S T A R T-------------------------------\n");

//-----------------------------------------------------------------------------
//	The setting of the GDK_BACKEND above to x11 appears to solve the
//	Wayland problem the following was written to address but the code
//	is retained in case the problem comes back.
//
//	{	char *p = getenv("XDG_SESSION_TYPE");
//		if (p == NULL) {
//			p = getenv("GDK_BACKEND");
//			if (p == NULL) {
//				strcpy(session_type, "NULL");
//				}
//			else strcpy(session_type, p);
//			}
//
//		else strcpy(session_type, p);
//		}
//
//	printf("*** session type: %s\n", session_type);
//-----------------------------------------------------------------------------

	srand( (unsigned int) time(0) );

//----------------------------------------------
//	PulseAudio interface
//----------------------------------------------

//--------------------
//	PLAYER SINK
//--------------------

	printf("\n------------------ sink connect --------\n");

	GMainContext *mcd_sink;

	mcd_sink = g_main_context_default();

	m_sink = pa_glib_mainloop_new(mcd_sink);

	pa_mainloop_api * mla_sink;

	mla_sink = pa_glib_mainloop_get_api(m_sink);

	context_sink = pa_context_new(mla_sink, PULSE_SINK_NAME);

	pa_context_set_state_callback(
	    context_sink,
	    sink_connection_state_callback,
	    NULL);

	if (pa_context_connect(context_sink, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0 )
		printf("*** sink context connect error\n");

	printf("*** sink connected\n");

//------------------------
//	MICROPHONE SOURCE
//------------------------

	printf("\n------------------ source connect --------\n");

	GMainContext *mcd_source;

	mcd_source = g_main_context_default();

	m_source = pa_glib_mainloop_new(mcd_source);

	pa_mainloop_api * mla_source;

	mla_source = pa_glib_mainloop_get_api(m_source);

	context_source = pa_context_new(mla_source, PULSE_SOURCE_NAME);

	pa_context_set_state_callback(
	    context_source,
	    source_connection_state_callback,
	    NULL);

	if (pa_context_connect(context_source, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL) < 0 )
		printf("*** source context connect error\n");

	printf("*** source connected\n");

	g_timeout_add(timer_res, (GSourceFunc) pulse_timer_handler, NULL);

//------------------
//	Tile colors
//------------------

	cover.red = TILE_ALBUM_MARKER_RED;
	cover.green = TILE_ALBUM_MARKER_GREEN;
	cover.blue = TILE_ALBUM_MARKER_BLUE;

	webplay.red = TILE_WEB_RED;
	webplay.green = TILE_WEB_GREEN;
	webplay.blue = TILE_WEB_BLUE;

	unplayed.red = TILE_UNPLAYED_RED;
	unplayed.green = TILE_UNPLAYED_GREEN;
	unplayed.blue = TILE_UNPLAYED_BLUE;

	played.red = TILE_PLAYED_RED;
	played.green = TILE_PLAYED_GREEN;
	played.blue = TILE_PLAYED_BLUE;

	notplayable.red = LOW_TRAY_NOT_PLAYABLE_RED;
	notplayable.green = LOW_TRAY_NOT_PLAYABLE_GREEN;
	notplayable.blue = LOW_TRAY_NOT_PLAYABLE_BLUE;

	playing.red = TILE_PLAYING_RED;
	playing.green = TILE_PLAYING_GREEN;
	playing.blue = TILE_PLAYING_BLUE;

	low_tray.red = 0x0000;
	low_tray.green = 0x9999;
	low_tray.blue = 0x0000;

//---------------------------------------
//	ffmpeg interface
//	must be called here - do not move.
//---------------------------------------

//	av_register_all();

	memory_alloc();

//----------------------------------------------------------------------
//	shmget() returns an identifier in shmid  - to communicate with
//	any forked processes - not currently used
//	key_t key = ftok("shmfile", 65);
//	shmid = shmget(key, 1024, 0666 | IPC_CREAT);
//	Sharedstr = (char*) shmat(shmid, (void*) 0, 0);
//	strcpy(Sharedstr, "empty");
//----------------------------------------------------------------------

	for (int i = 0; i < 20; i++) // equalizer preset backups
		for(int j = 0; j < 10; j++)
			SP->preSetBak[i][j] = -1;

	SearchFlg = 0; // entry1
	micmute = 0;
	SP->volumeLevel = INIT_VOLUME;
	SP->auto_muted = 0; // initially off

//----------------------------------------------------------------------
//      Establish the location for the code directory
//      The files 'program.lst' and 'sounders.config' should be here.
//      'program.lst' contains the references to the music files.
//----------------------------------------------------------------------

	char *home_env = getenv("HOME");

	if (Code_Home == NULL) {
		printf("*** Unable to locate HOME envirnment variable.\n");
		return EXIT_FAILURE;
		}

	strcpy(Code_Home, home_env);
	strcat(Code_Home, "/sgr-player");

	strcpy(tmp, "mkdir -p \"");
	strcat(tmp, Code_Home);
	strcat(tmp, "\"");
	system(tmp);

	strcpy(tmp, "mkdir -p \"");
	strcat(tmp, Code_Home);
	strcat(tmp, "/web\"");
	system(tmp);

	printf("Web home: %s\n", tmp);

	strcpy(Code_Home, home_env);
	strcat(Code_Home, "/sgr-player");

	strcpy(tmp, "mkdir -p \"");
	strcat(tmp, Code_Home);
	strcat(tmp, "/media\"");
	system(tmp);

	strcpy(Music_Home_Directory, Code_Home);
	strcat(Music_Home_Directory, "/media");

	printf("Code home directory: %s\n", Code_Home);

	strcpy(Program_List, "\"");
	strcat(Program_List,Code_Home);
	strcat(Program_List,"/program.lst");     // file address of tmp.lst
	strcat(Program_List, "\"");

	printf("Code home directory: %s\n", Code_Home);

	strcpy(Album_List,Code_Home);
	strcat(Album_List,"/album.lst");	// file address of album.lst


	strcpy(Web_Page, "https://www.cs.uni.edu/~okane/pocketradio.html");

	cli_args(argc, argv);

	printf("Initial Web Page: %s\n", Web_Page);
	printf("Code Home: %s\n", Code_Home);
	printf("Music Home Directory: %s\n", Music_Home_Directory);
	printf("Sounder Max: %d\n", PROGRAM_MAX);
	printf("Program List: %s\n\n", Program_List);
	printf("Album List: %s\n\n", Album_List);

//------------------------
//      init constants
//------------------------

	copyClipRow=-1;
	strcpy(cutRow,"");
	strcpy(top1,"");
	strcpy(top2,"");
	strcpy(top3,"");
	cutPlayed=0;
	cutPlay=0;
	e7Row=0;
	e8Row=0;
	e9Row=0;
	e10Row=0;
	e11Row=0;
	e12Row=0;
	e13Row=0;
	e14Row=0;
	e2Row=0;
	e3Row=0;
	e4Row=0;
	e15Row=0;

//----------------------------------------------------------------
//      allocate memory for program entries
//----------------------------------------------------------------

	for (i=0; i < PROGRAM_MAX; i++ ) {

		// allocate shared memory for ST

		programData[i] = (struct ST *) malloc(sizeof(struct ST));

		programData[i]->play = 0; // play it?
		programData[i]->del = 0; // delete it?
		programPlayed[i] = 0; // play count
		programTime[i] = -1;
		}

//------------------------------------------------------------------
//      PGM_MAX is the maximum length of a line in the program list
//------------------------------------------------------------------

	while(SP->scount < PROGRAM_MAX) { // blank out entire list

		ProgramArray[SP->scount] = (char *) malloc(PGM_MAX);

		strcpy(ProgramArray[SP->scount],"");
		programData[SP->scount]->play = 1;
		programPlayed[SP->scount] = 0; // play count
		(SP->scount)++;
		}

//------------------------------------------------------------------
//      ALB_MAX is the maximum length of a line in the album list
//      ALBUM_MAX is count of entries
//------------------------------------------------------------------

	while (SP->acount < ALBUM_MAX) {        // ALBUM_MAX is size of array

		AlbumArray[SP->acount] = (char *) malloc(ALB_MAX);

		strcpy(AlbumArray[SP->acount],"");
		(SP->acount)++;
		}

//-----------------------------------------------------------------------------
//      call to LoadAlbums() delayed until after builder for pointers to init
//-----------------------------------------------------------------------------

	widgets = (struct APW*) malloc(sizeof(struct APW));

	if (!g_thread_supported ()) {
		g_thread_init(NULL);
		}
	gdk_threads_init();
	gdk_threads_enter();

	gtk_init(&argc, &argv);

// bug fix

	webkit_web_view_get_type();
	webkit_settings_get_type();

//---------------------------------------------------------------------
// establish contact with xml code used to adjust widget settings
//---------------------------------------------------------------------

	builder = gtk_builder_new_from_resource ("/part1/Player.glade");

	window = GTK_WIDGET(gtk_builder_get_object(builder, "window_main"));

	gtk_builder_connect_signals(builder, NULL);

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

	gtk_widget_add_events(GTK_WIDGET(window), GDK_CONFIGURE);
	g_signal_connect(window, "configure-event", G_CALLBACK(on_window_main_configure), NULL);

//---------------------------------------------------------------------
// get the definitions of the major components / widgets
//---------------------------------------------------------------------

#include "common/common-objects.h"

	//------------------------------------------------------------
	// make these button pointers available to the timer function
	//------------------------------------------------------------

	widgets -> timer = timer;
	widgets -> timeNext = timeNext;
	widgets -> TimeToHour = TimeToHour;
	widgets -> nextPlay = nextPlay;
	widgets -> currentFile = currentFile;

//--------------------------
//	css provider code
//--------------------------

	cssProvider_top		= gtk_css_provider_new();
	cssProviderUP		= gtk_css_provider_new();
	cssProviderProg		= gtk_css_provider_new();
	cssProviderDOWN		= gtk_css_provider_new();
	cssProviderpauseVideo	= gtk_css_provider_new();
	cssProviderpauseAtEnd	= gtk_css_provider_new();
	cssProvider_entry1	= gtk_css_provider_new();
	cssProvider_entry2	= gtk_css_provider_new();
	cssProvider_entry3	= gtk_css_provider_new();
	cssProvider_entry4	= gtk_css_provider_new();

//-------------------------------------
//
//	import GTK theme for the Player
//
//-------------------------------------

	GtkCssProvider  *cssProviderMain;
	cssProviderMain  = gtk_css_provider_new();
	gtk_css_provider_load_from_resource(cssProviderMain, "/part1/css/gtk.css");
	gtk_style_context_add_provider_for_screen(gdk_screen_get_default(),
	        GTK_STYLE_PROVIDER(cssProviderMain),
	        GTK_STYLE_PROVIDER_PRIORITY_USER);

//	example image css code
//"* { background-image:  radial-gradient(circle farthest-side at left bottom, red, yellow 50px, green); }"
//"* { background-image:  linear-gradient(45deg, lightgreen, lightblue); }"
//"* { background-image:  linear-gradient(45deg, lightblue, pink); }"
//"* { background-image: -gtk-gradient (linear, left top, left bottom, from(yellow), to(lightblue)); }"

//	gtk_css_provider_load_from_resource(cssProvidersave1, "/part1/css/save1.css");
//	css_set1(cssProvidersave1, save1); // attach css to save1

//---------------------------------------------
//	create providers to be used elsewhere
//---------------------------------------------

	gtk_css_provider_load_from_data(cssProvider_entry1,
	                                "* { color: " UNPLAYED_ROW_TEXT_COLOR "; font-size: "
	                                UNPLAYED_ROW_FONT_SIZE "; background: " UNPLAYED_ROW_BG_COLOR "; }",
	                                -1, NULL); // bg color of 12 pgm entry boxes

	gtk_css_provider_load_from_data(cssProvider_entry2,
	                                "* { background-color: " PLAYING_ROW_BG_COLOR "; }",
	                                -1, NULL); // color of entry box of playing row

	gtk_css_provider_load_from_data(cssProvider_entry3,
	                                "* { font-size: " PLAYED_ROW_FONT_SIZE "; background-color: " PLAYED_ROW_BG_COLOR "; }",
	                                -1, NULL);

	gtk_css_provider_load_from_data(cssProvider_entry4,
	                                "* { font-size: " PLAYED_ROW_FONT_SIZE "; background-color: " WEB_ROW_BG_COLOR "; }",
	                                -1, NULL);

	gtk_css_provider_load_from_data(cssProviderUP,
	                                "slider { border: 0px solid blue; padding-left: 0px; padding-right: 0px; "
	                                "min-height: 10px; border-radius: 16px; outline: black; background: "
	                                "lightgreen; border-color: black;} "
	                                "trough {min-width: 5px; background-color: blue; border-radius: 10px; } "
	                                " scrollbar {background: black; } ", -1, NULL);

	gtk_css_provider_load_from_data(cssProviderDOWN,
	                                "slider { border: 0px solid blue; padding-left: 0px; padding-right: 0px; "
	                                "min-height: 10px; border-radius: 16px; outline: black; background: "
	                                "lightgreen; border-color: black;} "
	                                "trough {min-width: 5px; background-color: red; border-radius: 10px; } "
	                                " scrollbar {background: black; } ", -1, NULL);

	gtk_css_provider_load_from_data(cssProvider_top,
	                                " * { font-family: mono; font-weight: bold; font-size: 14px ; "
	                                "background-color: black; color: yellow; } ",
	                                -1, NULL);

	gtk_css_provider_load_from_data(cssProviderProg,
	                                "* { border: 0px solid blue; padding-left: 0px; padding-right: 0px; "
	                                "border-radius: 0px; outline: black; background: lightblue; border-color: black;} "
	                                "trough {background-color: black;} ", -1, NULL);

//	future reference
//	gtk_entry_set_width_chars (GTK_ENTRY(searchEntry2), entryWidth);

	gtk_widget_set_events(window, GDK_POINTER_MOTION_MASK);
//      gtk_widget_set_events(draw1, GDK_POINTER_MOTION_MASK);
	gtk_widget_set_events(draw1, GDK_ENTER_NOTIFY_MASK);
	gtk_widget_set_events(draw1, GDK_LEAVE_NOTIFY_MASK);
//      gtk_widget_set_events(draw1, GDK_ALL_EVENTS_MASK);

	gtk_widget_set_events(scroll, GDK_SCROLL_MASK);
	gtk_widget_set_events(scroll2, GDK_SCROLL_MASK);

	gtk_widget_set_events(albumScroll, GDK_SCROLL_MASK);
	gtk_widget_set_events(vlcPosition, GDK_SCROLL_MASK);

	gtk_widget_set_events(preAmp, GDK_SCROLL_MASK);
	gtk_widget_set_events(h60, GDK_SCROLL_MASK);
	gtk_widget_set_events(h170, GDK_SCROLL_MASK);
	gtk_widget_set_events(h310, GDK_SCROLL_MASK);
	gtk_widget_set_events(h600, GDK_SCROLL_MASK);
	gtk_widget_set_events(h1000, GDK_SCROLL_MASK);
	gtk_widget_set_events(h3000, GDK_SCROLL_MASK);
	gtk_widget_set_events(h6000, GDK_SCROLL_MASK);
	gtk_widget_set_events(h12000, GDK_SCROLL_MASK);
	gtk_widget_set_events(h14000, GDK_SCROLL_MASK);
	gtk_widget_set_events(h16000, GDK_SCROLL_MASK);

	gtk_widget_set_events(p1,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p2,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p3,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p4,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p5,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p6,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p7,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p8,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p9,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p10,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p11,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p12,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p13,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p14,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p15,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p16,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p17,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p18,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p19,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p20,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p21,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p22,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p23,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p24,  GDK_SCROLL_MASK);
	gtk_widget_set_events(p25,  GDK_SCROLL_MASK);

	gtk_widget_set_events(button3,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button8,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button9,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button2,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button5,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button6,  GDK_SCROLL_MASK);
	gtk_widget_set_events(button10, GDK_SCROLL_MASK);
	gtk_widget_set_events(button11, GDK_SCROLL_MASK);
	gtk_widget_set_events(button13, GDK_SCROLL_MASK);
	gtk_widget_set_events(button12, GDK_SCROLL_MASK);
	gtk_widget_set_events(button14, GDK_SCROLL_MASK);
	gtk_widget_set_events(button15, GDK_SCROLL_MASK);

	gtk_widget_set_events(GTK_WIDGET(entry7), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry8), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry9), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry10), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry11), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry12), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry13), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry14), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry2), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry3), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry4), GDK_SCROLL_MASK);
	gtk_widget_set_events(GTK_WIDGET(entry15), GDK_SCROLL_MASK);


//---------------------------------------------------------------------
// load the first 24 program buttons with content
//---------------------------------------------------------------------

	LoadProgram(Program_List);

	DisplayProgramButtons();	// first 24 buttons loaded

	SP->begin = 0;	// next window begins here
	SP->Xbegin = 0;	// next window begins here

	g_object_unref(builder);

	for (int i = 0; i < 5; i++) strcpy(directories[i], Music_Home_Directory);

//-----------------------
//	main timer setup
//-----------------------

	g_timeout_add_seconds(TIMER_SECONDS, (GSourceFunc) timer_handler, widgets);

//---------------
//	camera 0
//---------------

//	gboolean cam_start();
//
//	thr_data.camFlag = 1;
//
//      thr_data.camThread = g_thread_new ("camThread", cam_start, &thr_data);

//-------------------------
//	slides timer setup
//-------------------------

	g_timeout_add_seconds(1, (GSourceFunc) picture_handler, widgets);

	gtk_widget_show(window);

	gtk_widget_hide(egg_image);

	gtk_widget_hide(programMode); // Automation On label visible when in program mode
	gtk_widget_hide(programMode1); // Automation On label visible when in program mode
	gtk_widget_hide(nextPlay); // Automation On label visible when in program mode

	spectrum_width = 1;

	chdir(Music_Home_Directory);

//---------------------------
//      Background colors
//---------------------------

	GdkColor color; // default background color

	if (! gdk_color_parse (BackgroundColorString, &background_color)) { // check CLI color
		printf("*** --background-color value did not parse.\n");
		background_color.red   = BACKGROUND_COLOR_DEFAULT_RED;
		background_color.green = BACKGROUND_COLOR_DEFAULT_GREEN;
		background_color.blue  = BACKGROUND_COLOR_DEFAULT_BLUE;
		color.red   = BACKGROUND_COLOR_DEFAULT_RED;
		color.green = BACKGROUND_COLOR_DEFAULT_GREEN;
		color.blue  = BACKGROUND_COLOR_DEFAULT_BLUE;
		}

//------------------------------------------------
//	cairo uses 0.0 to 1.0 for color numbers
//------------------------------------------------

	cairo_bg_red = background_color.red / 65535.0;
	cairo_bg_green = background_color.green / 65535.0;
	cairo_bg_blue = background_color.blue / 65535.0;

	gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &background_color);

//      gtk_window_set_title(GTK_WINDOW(pgm_window), "SGR Player Program Manager");

//-----------------------------
//      attch to this window
//-----------------------------

	gtk_window_set_transient_for (GTK_WINDOW(g_dbox1), GTK_WINDOW(window));

	SP->Pause = 0;
	SP->PauseKill = 0;
	gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON(pauseAtEnd), TRUE);

	SP->playonce = 1;

//--------------------------------------------------
//      set maximum limit of program scroll bars
//--------------------------------------------------

//      after program.lst is loaded:

	gtk_range_set_range (GTK_RANGE(scroll), 0, SP->scount);
	gtk_range_set_range (GTK_RANGE(scroll2), 0, SP->scount);

	gtk_range_set_range (GTK_RANGE(search_scroll), 0, SP->scount);

//----------------------------------------------
//      set increment of program scroll bars
//----------------------------------------------

	gtk_range_set_increments (GTK_RANGE(scroll), 1., 1.);
	gtk_range_set_increments (GTK_RANGE(scroll2), 1., 1.);

	gtk_range_set_increments (GTK_RANGE(search_scroll), 1., 1.);

//*****************************************************************
//
//	PulseAudio Interface
//
//*****************************************************************

//--------------------------------------------------------------------------
//	mode tells the pulse functions that connect whether to connect to
//	the microphone source (RECORD) or playback sink (PLAYBACK)
//	The following is the connection to the sink (autio from VLC and other
//	players. The code for the source (RECORD) must wait until the
//	sink connects. The source will be connected in timer_handler() after
//	about 3 seconds.
//--------------------------------------------------------------------------

	static enum {
		PLAYBACK,
		RECORD
		} mode = PLAYBACK;

	mode = PLAYBACK; // connect to default PulseAudio sink

	SP->volumeLevel = INIT_VOLUME; // preamp

//	system("pulseaudio --start");
	system("pulseaudio --cleanup-shm");

#if PLAYER_ON_TOP == 1
	gtk_window_set_keep_above (GTK_WINDOW(window), TRUE); // optional
#endif

	gtk_widget_show_all(window);
	gtk_widget_hide(egg_image);

	createPresets();
	SP->currentPreset = 0; // flat

	gdk_window = gtk_widget_get_window(GTK_WIDGET(window));

	gtk_window_resize(GTK_WINDOW(window), 400,400);

//      gtk_window_move(GTK_WINDOW(pgm_window), 1, 1);

//      gtk_window_resize(GTK_WINDOW(pgm_window), 299,300);

//-----------------------------
// load main panel title text
//-----------------------------

		{
		char tmp[2048];
		sprintf(tmp, "%s/title.txt", Code_Home);
		s1 = fopen(tmp, "r");
		if (s1) {
			fgets(tmp, 100, s1);
			tmp[strlen(tmp)-1] = 0;

//--------------------------------------------------
//                      overwrites default title
//--------------------------------------------------

			gtk_label_set_text(GTK_LABEL(sgrStudio), tmp);
			fclose(s1);
			}
		}


//------------------------------------------------------------
//      enable window display - placement of this is important
//------------------------------------------------------------

	gtk_widget_show_all(window);

	for (int i=0; i<12; i++) AlbumButton[i] = -1;

	LoadAlbums(Album_List); // load the album names

	if (SP->acount)  { // we have albums?
		AlbumBegin = 0;
		AlbumBtnLoad();
		}

	style = VERY_NARROW_SPECTRUM; // narrow freqeuncy spectrum

	GtkTargetEntry targs[1] = {"target5", GTK_TARGET_SAME_APP, 1};

//------------------------`
// targs structure:
//      gchar *target;
//      guint  flags;
//      guint  info;
//------------------------`

#define P_BUTTON_DRAG_SETUP(NBR) \
        gtk_drag_source_set(p ##NBR, GDK_BUTTON1_MASK, targs, 1, GDK_ACTION_COPY); \
        gtk_drag_dest_set(p##NBR, GTK_DEST_DEFAULT_ALL, targs, 1, GDK_ACTION_COPY);

	P_BUTTON_DRAG_SETUP(1) P_BUTTON_DRAG_SETUP(2)
	P_BUTTON_DRAG_SETUP(3)  P_BUTTON_DRAG_SETUP(4)
	P_BUTTON_DRAG_SETUP(5) P_BUTTON_DRAG_SETUP(6)
	P_BUTTON_DRAG_SETUP(7)  P_BUTTON_DRAG_SETUP(8)
	P_BUTTON_DRAG_SETUP(9) P_BUTTON_DRAG_SETUP(10)
	P_BUTTON_DRAG_SETUP(11) P_BUTTON_DRAG_SETUP(12)

	P_BUTTON_DRAG_SETUP(22) P_BUTTON_DRAG_SETUP(23)
	P_BUTTON_DRAG_SETUP(24) P_BUTTON_DRAG_SETUP(25)

	gtk_drag_source_set(GTK_WIDGET(entry1), GDK_BUTTON1_MASK, targs,
	                    1, GDK_ACTION_COPY);

	gtk_drag_dest_set(GTK_WIDGET(entry1), GTK_DEST_DEFAULT_ALL, targs,
	                  1, GDK_ACTION_COPY);

	gtkSetCursor(GDK_TOP_LEFT_ARROW); // cursor appearance

	on_tooltips_toggled(tooltips); // turn on/off tooltips

	g_signal_connect (G_OBJECT (window), "key_press_event",
	                  G_CALLBACK (talkPush), NULL);

	g_signal_connect (G_OBJECT (window), "key_release_event",
	                  G_CALLBACK (talkRelease), NULL);

	if (which_meters == 1) {
		gtk_widget_hide(vumeter);       // vumeter background not used
		gtk_widget_hide(vumeter1);      // vumeter background not used
		}

	DisplayCover("default");

	DisplayCover("default");

	gtk_widget_hide(egg_image);
	gtk_widget_hide(programMode);
	gtk_widget_hide(programMode1);
	gtk_widget_hide(nextPlay);

//---------------------------
//	initialize Topgain
//---------------------------

	on_maxGain_value_changed(GTK_SPIN_BUTTON(maxGain));

//-------------------
//	init webkit
//-------------------

	WebKitWindowProperties *web_properties;
	web_properties = webkit_web_view_get_window_properties (WEBKIT_WEB_VIEW(webkit));

//	web_properties->locationbar_visible = TRUE;

//        strcpy(tmp, "https://forecast.weather.gov/MapClick.php?lat=34.4984&lon=-82.0186");

//        webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webkit), tmp);
//        webkit_web_view_load_html(WEBKIT_WEB_VIEW(webkit), tmp, NULL);

//        gtk_widget_set_size_request (webkit, 580, 550);
	gtk_widget_show(webkit);

	gtk_widget_hide(cam0_active);

//-----------------------------------------------------------------------------------
//	Wayland avoidance code
//	if (strcmp(session_type,"x11") != 0) {
//                gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(show_video), FALSE);
//		printf("*** x11 manager not detected - Video checkbox turned off\n");
//		}
//-----------------------------------------------------------------------------------

	video_init = 1;

//-----------------------------------------------------
//	From here on, it's all callbacks - main loop
//-----------------------------------------------------


	gtk_main(); // here we go!


	/*********************** exit sound reset code not in use **********************
	        pa_cvolume vol = {2, 65000, 65000}; // tw channels

		mic_volume = mic_max;

	        vol.values[0] = (mic_volume / 100.0) * 65535;
	        vol.values[1] = (mic_volume / 100.0) * 65535;
		vol.channels = source_channels;

	        if (context_source) { // Mcontext pointer must be non-zero
			pa_operation *x  = pa_context_set_source_volume_by_name(context_source,
				default_source, &vol, NULL, NULL);
			}

	//	outVolume(INIT_VOLUME); // reset volume when done
	**********************************************************************************/

	return EXIT_SUCCESS; // bye-bye
	}

