/*
 * rplaytool_stubs.c - Notify and event callback function stubs.
 * This file was generated by `gxv' from `rplaytool.G'.
 */

/* 
 * Copyright (C) 1995 Mark Boyns <boyns@sdsu.edu>
 *
 * This file is part of rplaytool.
 *
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <xview/xview.h>
#include <xview/panel.h>
#include <xview/textsw.h>
#include <xview/xv_xrect.h>
#include <xview/scrollbar.h>
#include "rplaytool_ui.h"
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <dirent.h>
#include <unistd.h>
#include "rptp.h"
#include "misc.h"
#include "getopt.h"

static char *rplaytool_version = "1.1";

#define SOUNDLIST_MESSAGE "Retrieving sound list..."

void talk ();
Notify_value process ();
static Notify_value timer_update (/* client, which */);

/*
 * Global object definitions.
 */
rplaytool_w_objects	*Rplaytool_w;
rplaytool_s_objects	*Rplaytool_s;
rplaytool_f_objects	*Rplaytool_f;

typedef struct
{
    int id;
    int playlist;
}
SPOOL;

static int spool_size = 0;
static int soundlist_size = 0;
static int disklist_size = 0;
static Xv_opaque curr_soundlist;

static char *rptp_host = NULL;
static char *playlist1_file = NULL;
static char *playlist2_file = NULL;
static char *playlist3_file = NULL;
static char *playlist4_file = NULL;
static int show_sounds = 0;
static int use_disk_sounds = 0;
static int use_server_sounds = 1;
static int scan_playlist_files = 1;
static int scan_playlist_interval = 5;	/* seconds */
static int countdown = 0;
int initial_delay = -1;

static struct option longopts[] =
{
    {"delay", required_argument, NULL, 4},
    {"disk-sounds", no_argument, NULL, 3},
    {"dir", required_argument, NULL, 'd'},
    {"help", no_argument, NULL, 1},
    {"host", required_argument, NULL, 'h'},
    {"playlist1", required_argument, NULL, '1'},
    {"playlist2", required_argument, NULL, '2'},
    {"playlist3", required_argument, NULL, '3'},
    {"playlist4", required_argument, NULL, '4'},
    {"server-sounds", no_argument, NULL, 2},
    {"sounds", no_argument, &show_sounds, 1},
    {"version", no_argument, NULL, 'v'},
    {NULL, 0, NULL, 0}
};

#ifdef MAIN

/*
 * Instance XV_KEY_DATA key.  An instance is a set of related
 * user interface objects.  A pointer to an object's instance
 * is stored under this key in every object.  This must be a
 * global variable.
 */
Attr_attribute	INSTANCE;

main(argc, argv)
	int	argc;
	char	**argv;
{
	int i, c;
	char title[32];
	char *disk_dir = NULL;
	struct itimerval timer;
	extern char *optarg;
	extern int optind, opterr;
	
	/*
	 * Initialize XView.
	 */
	xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
	INSTANCE = xv_unique_key();

	rptp_host = rplay_default_host ();

	while ((c = getopt_long (argc, argv, "h:1:2:3:4:", longopts, 0)) != -1)
	{
	    switch (c)
	    {
	    case 0:
		/* getopt has processed a long-named option -- do nothing */
		break;

	    case 1: /* --help */
		usage ();

	    case 2: /* --server-sounds */
		use_server_sounds++;
		use_disk_sounds = 0;
		break;
		
	    case 3: /* --disk-sounds */
		use_server_sounds = 0;
		use_disk_sounds++;
		break;

	    case 4: /* --delay */
		initial_delay = atoi (optarg);
		break;
		
	    case 'd':
		disk_dir = optarg;
		use_server_sounds = 0;
		use_disk_sounds++;
		show_sounds++;
		break;

	    case 'h':
		rptp_host = optarg;
		break;

	    case '1':
		playlist1_file = optarg;
		break;

	    case '2':
		playlist2_file = optarg;
		break;

	    case '3':
		playlist3_file = optarg;
		break;

	    case '4':
		playlist4_file = optarg;
		break;

	    case 'v':
		printf ("rplaytool %s\n", rplaytool_version);
		exit (0);

	    default:
		fprintf (stderr, "Try `rplaytool --help' for more information.\n");
		exit (1);
	    }
	}
	
	/*
	 * Initialize user interface components.
	 * Do NOT edit the object initializations by hand.
	 */
	Rplaytool_w = rplaytool_w_objects_initialize(NULL, NULL);
	Rplaytool_s = rplaytool_s_objects_initialize(NULL, Rplaytool_w->w);
	Rplaytool_f = rplaytool_f_objects_initialize(NULL, Rplaytool_w->w);
	
	/* Initialize the playlists. */
	for (i = 0; i < NUMBER_OF_PLAYLISTS; i++)
	{
	    do_playlist_init (i);
	}
	playlist[0].list = Rplaytool_s->playlist1;
	playlist[1].list = Rplaytool_s->playlist2;
	playlist[2].list = Rplaytool_s->playlist3;
	playlist[3].list = Rplaytool_s->playlist4;
	if (playlist1_file)
	{
	    curr_playlist = 0;
	    file_load_file (playlist1_file);
	}
	if (playlist2_file)
	{
	    curr_playlist = 1;
	    file_load_file (playlist2_file);
	}
	if (playlist3_file)
	{
	    curr_playlist = 2;
	    file_load_file (playlist3_file);
	}
	if (playlist4_file)
	{
	    curr_playlist = 3;
	    file_load_file (playlist4_file);
	}

	curr_playlist = 0;
	curr_soundlist = Rplaytool_s->soundlist;

	/* Create the icons. */
	for (i = 0; i < NUMBER_OF_ICONS; i++)
	{
	    icons[i].image = (Server_image) xv_create (NULL, SERVER_IMAGE,
						       XV_WIDTH, 16,
						       XV_HEIGHT, 16,
						       SERVER_IMAGE_BITS, icons[i].bits,
						       NULL);
	}

	/* Update the frame title. */
	sprintf (title, "rplaytool %s", rplaytool_version);
	xv_set (Rplaytool_w->w, XV_LABEL, title, NULL);

	/* Connect to the default RPTP server. */
	client_id = getpid ();
	talk (rptp_host);

	/* Automatically show the "Sounds" popup. */
	if (show_sounds)
	{
		if (use_server_sounds)
		{
			load_soundlist ();
		}
		else if (use_disk_sounds)
		{
			load_disklist (disk_dir ? disk_dir : 0);
		}
		xv_set(Rplaytool_s->s, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
		xv_set(Rplaytool_s->s, XV_SHOW, TRUE, NULL);
		xv_set(Rplaytool_s->soundsource, PANEL_VALUE, use_server_sounds ? 0 : 1, NULL);
	}


	/* */
	timer.it_value.tv_sec = 1;
	timer.it_value.tv_usec = 0;
	timer.it_interval.tv_sec = 1;
	timer.it_interval.tv_usec = 0;
	notify_set_itimer_func (Rplaytool_w->w, timer_update, ITIMER_REAL, &timer, NULL);
	
	/*
	 * Turn control over to XView.
	 */
	xv_main_loop(Rplaytool_w->w);

	exit(0);
}

#endif

static Notify_value
timer_update (client, which)
    Notify_client client;
    int which;
{
    static int count;
    int i;
    
    count++;

    if (scan_playlist_files)
    {
	if ((count % scan_playlist_interval) == 0)
	{
	    playlist_scan ();
	}
    }

    for (i = 0; i < NUMBER_OF_PLAYLISTS; i++)
    {
	if (playlist[i].delay >= 0)
	{
	    if (playlist[i].delay == 0)
	    {
		play_playlist (i, FALSE);
	    }
	    else
	    {
		if (countdown)
		{
		    char line[RPTP_MAX_LINE];
		    sprintf (line, "%d.au", playlist[i].delay);
		    do_rptp_play (line, NULL);
		}
	    }
			    
	    playlist[i].delay--;
	}
    }
}

usage ()
{
    printf ("\nrplaytool %s\n\n", rplaytool_version);
    printf ("usage: rplaytool [options]\n");

    printf ("--delay=N\n");
    printf ("\tDelay N seconds before playing each sound in a playlist.\n");
    printf ("\n");
    
    printf ("--dir=DIR\n");
    printf ("\tUse DIR as the default disk sounds directory.\n");
    printf ("\tThis option implies `--disk-sounds' and `--sounds'.\n");
    printf ("\n");

    printf ("--disk-sounds\n");
    printf ("\tDisplay disk sounds by default in the `Sounds' popup.\n");
    printf ("\tThe default is server sounds.\n");
    printf ("\n");

    printf ("--help\n");
    printf ("\tDisplay helpful information.\n");
    printf ("\n");

    printf ("--host=HOST, -h HOST\n");
    printf ("\tSpecify the rplay host, default = %s.\n", rptp_host);
    printf ("\n");

    printf ("--playlist1=FILE, -1 FILE\n");
    printf ("\tFILE used for playlist1.\n");
    printf ("\n");
    
    printf ("--playlist2=FILE, -2 FILE\n");
    printf ("\tFILE used for playlist2.\n");
    printf ("\n");
    
    printf ("--playlist3=FILE, -3 FILE\n");
    printf ("\tFILE used for playlist3.\n");
    printf ("\n");
    
    printf ("--playlist4=FILE, -4 FILE\n");
    printf ("\tFILE used for playlist4.\n");
    printf ("\n");

    printf ("--server-sounds\n");
    printf ("\tDisplay server sounds by default in the `Sounds' popup.\n");
    printf ("\tThe is the default.\n");
    printf ("\n");

    printf ("--sounds\n");
    printf ("\tAutomatically show the `Sounds' popup.\n");
    printf ("\n");
    
    printf ("--version\n");
    printf ("\tPrint the rplaytool version and exit.\n");
    printf ("\n");
    
    exit (0);
}

Notify_value
process_write (client, fd)
    Notify_client client;
    int fd;
{
    rptp_async_process (fd, RPTP_ASYNC_WRITE);
    return NOTIFY_DONE;
}

Notify_value
process_read (client, fd)
    Notify_client client;
    int fd;
{
    rptp_async_process (fd, RPTP_ASYNC_READ);
    return NOTIFY_DONE;
}

Notify_client input_client = (Notify_client) 10101;
Notify_client output_client = (Notify_client) 20202;

void
enable_notify_write (fd)
    int fd;
{
    notify_set_output_func(output_client, process_write, fd);
}

void
disable_notify_write (fd)
    int fd;
{
    notify_set_output_func(output_client, NOTIFY_FUNC_NULL, fd);
}

void
talk (host)
	char *host;
{
    static int talking;
    char buf[1024];

    if (talking)
    {
	talking = 0;
	notify_set_input_func(input_client, NOTIFY_FUNC_NULL, rptp_fd);
	notify_set_output_func(output_client, NOTIFY_FUNC_NULL, rptp_fd);
	rptp_close (rptp_fd);
	rptp_fd = -1;
    }

    if (!host)
    {
	host = rplay_default_host ();
    }

    xv_set (Rplaytool_w->host, PANEL_VALUE, host, NULL);

    sprintf (buf, "Connecting to %s...", host);
    xv_set (Rplaytool_w->w, FRAME_LEFT_FOOTER, buf, NULL);

    busy (Rplaytool_w->w, TRUE);
    do_rptp_open (host);
    busy (Rplaytool_w->w, FALSE);
    if (rptp_fd < 0)
    {
	rptp_fd = -1;
	notice (Rplaytool_w->w, NULL, NULL, "Connection to %s failed", host);
	xv_set (Rplaytool_w->w, FRAME_LEFT_FOOTER, "Not Connected", NULL);
    }
    else
    {
	notify_set_input_func(input_client, process_read, rptp_fd);
	talking++;
	sprintf (buf, "Connected to %s", host);
	xv_set (Rplaytool_w->w, FRAME_LEFT_FOOTER, buf, NULL);
    }
}

void
process_input (fd, event, line)
    int fd;
    int event;
    char *line;
{
    int  i, n, id, data_index = -1, data_id = -1, state = -1;
    char buf[RPTP_MAX_LINE], *p, *client_data;
    SPOOL *sp;

    rptp_parse (line, 0);
    p = rptp_parse (0, "id");
    if (p)
    {
	id = atoi (p+1);
    }
    
    client_data = rptp_parse (0, "client-data");
    if (client_data && *client_data)
    {
	n = sscanf (client_data, "%d %d %d", &state, &data_id, &data_index);
	if (n != 3)
	{
	    state = -1;
	    data_id = -1;
	    data_index = -1;
	}
    }
	    
    switch (event)
    {
    case RPTP_EVENT_CLOSE:
	rptp_async_register (rptp_fd, RPTP_ASYNC_READ, NULL);
	talk (NULL);
	break;
	
    case RPTP_EVENT_OK:
	/* A playlist-play OK response. */
	if (state == STATE_PLAY && data_index >= 0)
	{
	    playlist[data_index].id = id;
	    busy (Rplaytool_s->s, FALSE);
	}
	break;
	
    case RPTP_EVENT_ERROR:
	/* A playlist-play ERROR response. */
	if (state == STATE_PLAY && data_index >= 0)
	{
	    busy (Rplaytool_s->s, FALSE);
	}
	
	switch (state)
	{
	case STATE_PLAY:
	case STATE_PAUSE:
	case STATE_CONTINUE:
	    notice (Rplaytool_w->w, NULL, NULL, rptp_parse (0, "error"));
	    break;
	    
	case STATE_STOP:
	    /* Stops may fail since the sound may finish before the command
	       arrives.  Therefore, stop errors are ignored. */
	    break;
	}
	break;

    case RPTP_EVENT_PLAY:
    case RPTP_EVENT_PAUSE:
    case RPTP_EVENT_CONTINUE:
	{
	    char *sound_name;
	    int found = 0;
	    int use_icon;
	    
	    sound_name = rptp_parse (0, "sound");
	    p = strrchr (sound_name, '/');
	    sound_name = p ? p+1 : sound_name;
	    
	    if (event == RPTP_EVENT_CONTINUE || event == RPTP_EVENT_PLAY)
	    {
		use_icon = ICON_PLAY + ((data_index >= 0) ? data_index+1 : 0);
	    }
	    else
	    {
		use_icon = ICON_PAUSE + ((data_index >= 0) ? data_index+1 : 0);
	    }
	    
	    sprintf (buf, "%s", sound_name);

	    n = (int) xv_get (Rplaytool_w->spool, PANEL_LIST_NROWS);
	    for (i = 0; i < n; i++)
	    {
		sp = (SPOOL *) xv_get(Rplaytool_w->spool, PANEL_LIST_CLIENT_DATA, i);
		if (sp->id == id)
		{
		    xv_set (Rplaytool_w->spool,
			    PANEL_LIST_STRING, i, buf,
			    PANEL_LIST_GLYPH, i, icons[use_icon].image,
			    NULL);
		    found++;
		    break;
		}
	    }

	    /* Insert a new sound. */
	    if (!found)
	    {
		sp = (SPOOL *) malloc (sizeof (SPOOL));
		sp->id = id;
		sp->playlist = data_index;

		xv_set (Rplaytool_w->spool,
			PANEL_LIST_INSERT, spool_size,
			PANEL_LIST_STRING, spool_size, buf,
			PANEL_LIST_CLIENT_DATA, spool_size, sp,
			PANEL_LIST_GLYPH, spool_size, icons[use_icon].image,
			NULL);
		spool_size++;
	    }

	    if (data_index >= 0)
	    {
		playlist_update_icons (data_index);
	    }
	}
	break;

    case RPTP_EVENT_DONE:
	n = (int) xv_get (Rplaytool_w->spool, PANEL_LIST_NROWS);
	for (i = 0; i < n; i++)
	{
	    sp = (SPOOL *) xv_get(Rplaytool_w->spool, PANEL_LIST_CLIENT_DATA, i);
	    if (sp->id == id)
	    {
		xv_set (Rplaytool_w->spool, PANEL_LIST_DELETE, i, NULL);
		spool_size--;

		if (data_id == client_id
		    && sp->playlist >= 0
		    && playlist[sp->playlist].id == id)
		{
		    playlist[sp->playlist].id = -1;
		    if (playlist[sp->playlist].auto_play)
		    {
			playlist[sp->playlist].curr++;
		    	play_playlist (sp->playlist, TRUE);
		    }
		}
		    
		free ((char *) sp);
		break;
	    }
	}
	break;

    case RPTP_EVENT_STATE:
	{
	    int curr_volume, new_volume;
	    int nplaying, npaused;

	    curr_volume = (int) xv_get (Rplaytool_w->volume, PANEL_VALUE);
	    new_volume = atoi (rptp_parse (0, "volume"));
	    if (curr_volume != new_volume)
	    {
		xv_set (Rplaytool_w->volume, PANEL_VALUE, new_volume, NULL);
	    }

	    nplaying = atoi (rptp_parse (0, "play"));
	    npaused = atoi (rptp_parse (0, "pause"));

	    if (nplaying && !npaused)
	    {
		xv_set (Rplaytool_w->pause, PANEL_INACTIVE, FALSE, NULL); 
		xv_set (Rplaytool_w->cont, PANEL_INACTIVE, TRUE, NULL); 
		xv_set (Rplaytool_w->stop, PANEL_INACTIVE, FALSE, NULL); 
	    }
	    else if (!nplaying && npaused)
	    {
		xv_set (Rplaytool_w->pause, PANEL_INACTIVE, TRUE, NULL); 
		xv_set (Rplaytool_w->cont, PANEL_INACTIVE, FALSE, NULL); 
		xv_set (Rplaytool_w->stop, PANEL_INACTIVE, FALSE, NULL); 
	    }
	    else if (nplaying && npaused)
	    {
		xv_set (Rplaytool_w->pause, PANEL_INACTIVE, FALSE, NULL); 
		xv_set (Rplaytool_w->cont, PANEL_INACTIVE, FALSE, NULL); 
		xv_set (Rplaytool_w->stop, PANEL_INACTIVE, FALSE, NULL); 
	    }
	    else
	    {
		xv_set (Rplaytool_w->pause, PANEL_INACTIVE, TRUE, NULL); 
		xv_set (Rplaytool_w->cont, PANEL_INACTIVE, TRUE, NULL); 
		xv_set (Rplaytool_w->stop, PANEL_INACTIVE, TRUE, NULL); 
	    }
	}
	break;

    case RPTP_EVENT_OTHER:
	if (strcmp (line, ".") == 0)
	{
	    xv_set (Rplaytool_s->soundlist, XV_SHOW, TRUE, NULL);
	    xv_set (Rplaytool_s->s, FRAME_LEFT_FOOTER, "", NULL);
	    busy (Rplaytool_s->s, FALSE);
	}
	else
	{
	    xv_set (Rplaytool_s->soundlist,
		    PANEL_LIST_INSERT, soundlist_size,
		    PANEL_LIST_STRING, soundlist_size, rptp_parse (0, "sound"),
		    PANEL_LIST_GLYPH, soundlist_size, icons[ICON_SOUND].image,
		    NULL);
	    soundlist_size++;

	    if ((soundlist_size % 50) == 0)
	    {
	    	sprintf (buf, "%s%d", SOUNDLIST_MESSAGE, soundlist_size);
	    	xv_set (Rplaytool_s->s, FRAME_LEFT_FOOTER, buf, NULL);
	    }
	}
	break;
    }
}

load_soundlist ()
{
    busy (Rplaytool_s->s, TRUE);
    xv_set (Rplaytool_s->s, FRAME_LEFT_FOOTER, SOUNDLIST_MESSAGE, NULL);
    xv_set (Rplaytool_s->soundlist,
	    PANEL_LIST_DELETE_ROWS, 0,
	    (int) xv_get (Rplaytool_s->soundlist, PANEL_LIST_NROWS), NULL);
    xv_set (Rplaytool_s->soundlist, XV_SHOW, FALSE, NULL);
    soundlist_size = 0;
    do_rptp_sounds ();

    xv_set(Rplaytool_s->controls9, XV_SHOW, TRUE, NULL); /* hack */
    curr_soundlist = Rplaytool_s->soundlist;

}

load_disklist (newdir)
    char *newdir;
{
    char cwd[MAXPATHLEN];
    char *p;
    DIR *dir;
    struct dirent *dp;
    struct stat st;
    int n;
    Scrollbar scrollbar;

    busy (Rplaytool_s->s, TRUE);

    if (newdir)
    {
	chdir (newdir);
    }

    getcwd (cwd, sizeof (cwd));

    dir = opendir (".");
    if (dir == NULL)
    {
	exit (1);
    }

    xv_set (Rplaytool_s->disklist,
	    PANEL_LIST_DELETE_ROWS, 0,
	    (int) xv_get (Rplaytool_s->disklist, PANEL_LIST_NROWS),
	    NULL);

    xv_set (Rplaytool_s->disklist, XV_SHOW, FALSE, NULL);

    disklist_size = 0;
    /* Put `..' first. */
    xv_set (Rplaytool_s->disklist,
	    PANEL_LIST_INSERT, disklist_size,
	    PANEL_LIST_STRING, disklist_size, "..",
	    PANEL_LIST_CLIENT_DATA, disklist_size, 1, /* a directory */
	    PANEL_LIST_GLYPH, disklist_size, icons[ICON_DIRECTORY].image,
	    NULL);
    disklist_size++;

    for (;;)
    {
	dp = readdir (dir);
	if (dp == NULL)
	{
	    closedir (dir);
	    break;
	}
	else if (strcmp (dp->d_name, ".") == 0
		 || strcmp (dp->d_name, "..") == 0)
	{
	    continue;
	}
	else
	{
	    p = strrchr (dp->d_name, '.'); 
	    stat (dp->d_name, &st);

	    if (S_ISDIR (st.st_mode))
	    {
		xv_set (Rplaytool_s->disklist,
			PANEL_LIST_INSERT, disklist_size,
			PANEL_LIST_STRING, disklist_size, dp->d_name,
			PANEL_LIST_CLIENT_DATA, disklist_size, 1, /* a directory */
			PANEL_LIST_GLYPH, disklist_size, icons[ICON_DIRECTORY].image,
			NULL);
		disklist_size++;
	    }
	    else if (p && (strcmp (p, ".au") == 0 
			   || strcmp (p, ".snd") == 0
			   || strcmp (p, ".wav") == 0
			   || strcmp (p, ".aiff") == 0
			   || strcmp (p, ".voc") == 0
			   || strcmp (p, ".ub") == 0
			   || strcmp (p, ".ul") == 0
			   || strcmp (p, ".g721") == 0
			   || strcmp (p, ".g723_3") == 0
			   || strcmp (p, ".g723_5") == 0))
	    {
		xv_set (Rplaytool_s->disklist,
			PANEL_LIST_INSERT, disklist_size,
			PANEL_LIST_STRING, disklist_size, dp->d_name,
			PANEL_LIST_CLIENT_DATA, disklist_size, 0, /* a file */
			PANEL_LIST_GLYPH, disklist_size, icons[ICON_SOUND].image,
			NULL);
		disklist_size++;
	    }
	}
    }

    scrollbar = (Scrollbar) xv_get (Rplaytool_s->disklist, PANEL_LIST_SCROLLBAR);
    xv_set (scrollbar, SCROLLBAR_VIEW_START, 0, NULL);

    xv_set (Rplaytool_s->disklist, XV_SHOW, TRUE, NULL);

    xv_set (Rplaytool_s->directory, PANEL_VALUE, cwd, NULL);

    xv_set(Rplaytool_s->controls7, XV_SHOW, TRUE, NULL); /* hack */

    curr_soundlist = Rplaytool_s->disklist;
	
    busy (Rplaytool_s->s, FALSE);
}

/*
 * Notify callback function for `volume'.
 */
void
do_volume(item, value, event)
    Panel_item	item;
    int		value;
    Event		*event;
{
    rplaytool_w_objects *ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
    do_rptp_volume ((int) xv_get (ip->volume, PANEL_VALUE));
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Menu handler for `file_menu (Quit)'.
 */
Menu_item
do_quit(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		if (notice (ip->w, "Yes", "No", "Really Quit?") == 1)
		{
			xv_destroy_safe (ip->w);
			exit (0);
		}
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Notify callback function for `host'.
 */
Panel_setting
do_host(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_w_objects *ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	char *	value = (char *) xv_get(item, PANEL_VALUE);
	
	xv_set (ip->spool, PANEL_LIST_DELETE_ROWS, 0, (int) xv_get (ip->spool, PANEL_LIST_NROWS) - 1, NULL);
	talk (value);
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return panel_text_notify(item, event);
}

/*
 * Menu handler for `file_menu (Sounds...)'.
 */
Menu_item
rplaytool_file_menu_item0_callback(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		
		if (use_server_sounds)
		{
			load_soundlist ();
		}
		else if (use_disk_sounds)
		{
			load_disklist (0);
		}

		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		xv_set(Rplaytool_s->s, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
		xv_set(Rplaytool_s->s, XV_SHOW, TRUE, NULL);
		
		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Notify callback function for `soundlist'.
 */
int
do_soundlist(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	static long prev_click_time = 0;
	static int prev_row = -1;
	struct timeval tv;
	long click_time;

	if (op == PANEL_LIST_OP_DESELECT
	    || op == PANEL_LIST_OP_SELECT)
	{
	    gettimeofday (&tv, 0);
	    click_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
	
	    if (prev_row == row && (click_time - prev_click_time < 400))
	    {
		do_rptp_play (string, NULL);
		prev_click_time = 0;
		prev_row = -1;
	    }
	    else
	    {
		prev_click_time = click_time;
		prev_row = row;
	    }
	}
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
	    xv_set (ip->add, PANEL_INACTIVE, TRUE, NULL);
	    break;

	case PANEL_LIST_OP_SELECT:
	    xv_set (ip->add, PANEL_INACTIVE, FALSE, NULL);
	    break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `close'.
 */
void
rplaytool_s_close_notify_callback(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);

	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	xv_set(Rplaytool_s->s, FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
	xv_set(Rplaytool_s->s, XV_SHOW, FALSE, NULL);
	
	/* gxv_end_connections */

}

/*
 * Menu handler for `cont_menu (Selected sounds)'.
 */
Menu_item
do_cont_selected(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	SPOOL *sp;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    for (i = (int) xv_get (ip->spool, PANEL_LIST_FIRST_SELECTED);
		 i != -1;
		 i = (int) xv_get (ip->spool, PANEL_LIST_NEXT_SELECTED, i))
	    {
		sp = (SPOOL *) xv_get(ip->spool, PANEL_LIST_CLIENT_DATA, i);
		do_rptp_cont (sp->id, "");
	    }
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `cont_menu (All sounds)'.
 */
Menu_item
do_cont_all(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    do_rptp_cont (0, "");
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `pause_menu (Selected sounds)'.
 */
Menu_item
do_pause_selected(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	SPOOL *sp;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    for (i = (int) xv_get (ip->spool, PANEL_LIST_FIRST_SELECTED);
		 i != -1;
		 i = (int) xv_get (ip->spool, PANEL_LIST_NEXT_SELECTED, i))
	    {
		sp = (SPOOL *) xv_get(ip->spool, PANEL_LIST_CLIENT_DATA, i);
		do_rptp_pause (sp->id, "");
	    }
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `pause_menu (All sounds)'.
 */
Menu_item
do_pause_all(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    do_rptp_pause (0, "");
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `stop_menu (Selected sounds)'.
 */
Menu_item
do_stop_selected(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	SPOOL *sp;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    for (i = (int) xv_get (ip->spool, PANEL_LIST_FIRST_SELECTED);
		 i != -1;
		 i = (int) xv_get (ip->spool, PANEL_LIST_NEXT_SELECTED, i))
	    {
		sp = (SPOOL *) xv_get(ip->spool, PANEL_LIST_CLIENT_DATA, i);
		do_rptp_stop (sp->id, "");
	    }
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `stop_menu (All sounds)'.
 */
Menu_item
do_stop_all(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_w_objects * ip = (rplaytool_w_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    do_rptp_stop (0, "");
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}



/*
 * Notify callback function for `whichlist'.
 */
void
switch_playlist(item, value, event)
	Panel_item	item;
	int		value;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	curr_playlist = value;

	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	if (value == 0)
	{
		xv_set(Rplaytool_s->controls2, XV_SHOW, TRUE, NULL);
	}
	
	if (value == 1)
	{
		xv_set(Rplaytool_s->controls3, XV_SHOW, TRUE, NULL);
	}
	
	if (value == 2)
	{
		xv_set(Rplaytool_s->controls4, XV_SHOW, TRUE, NULL);
	}
	
	if (value == 3)
	{
		xv_set(Rplaytool_s->controls5, XV_SHOW, TRUE, NULL);
	}
	
	/* gxv_end_connections */

}

/*
 * Notify callback function for `playit'.
 */
void
do_playit(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);

	playlist[curr_playlist].auto_play = 1;
	if (playlist[curr_playlist].curr == -1)
	{
	    playlist[curr_playlist].curr = 0;
	}
	play_playlist (curr_playlist, TRUE);
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Notify callback function for `disklist'.
 */
int
do_disklist(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	static long prev_click_time = 0;
	static int prev_row = -1;
	struct timeval tv;
	long click_time;

	if (op == PANEL_LIST_OP_DESELECT
	    || op == PANEL_LIST_OP_SELECT)
	{
	    gettimeofday (&tv, 0);
	    click_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;

	    if (prev_row == row && (click_time - prev_click_time < 400))
	    {
		/* See if it's a directory */
		if ((int) xv_get(ip->disklist, PANEL_LIST_CLIENT_DATA, row))
		{
		    load_disklist (string);
		}
		else
		{
		    /* Play the sound */
		    char buf[RPTP_MAX_LINE];
		    char *cwd = (char *) xv_get (ip->directory, PANEL_VALUE);
		    sprintf (buf, "%s/%s", cwd, string);
		    do_rptp_play (buf, NULL);
		}
		prev_click_time = 0;
		prev_row = -1;
	    }
	    else
	    {
		prev_click_time = click_time;
		prev_row = row;
	    }
	}
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
	    xv_set (ip->add, PANEL_INACTIVE, TRUE, NULL);
	    break;

	case PANEL_LIST_OP_SELECT:
	    xv_set (ip->add, PANEL_INACTIVE, FALSE, NULL);
	    break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `playlist3'.
 */
int
do_playlist3(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, TRUE, NULL);
		break;

	case PANEL_LIST_OP_SELECT:
		xv_set (ip->delete, PANEL_INACTIVE, FALSE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, FALSE, NULL);
		break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `playlist4'.
 */
int
do_playlist4(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, TRUE, NULL);
		break;

	case PANEL_LIST_OP_SELECT:
		xv_set (ip->delete, PANEL_INACTIVE, FALSE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, FALSE, NULL);
		break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `playlist1'.
 */
int
do_playlist1(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, TRUE, NULL);
		break;

	case PANEL_LIST_OP_SELECT:
		xv_set (ip->delete, PANEL_INACTIVE, FALSE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, FALSE, NULL);
		break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `playlist2'.
 */
int
do_playlist2(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, TRUE, NULL);
		break;

	case PANEL_LIST_OP_SELECT:
		xv_set (ip->delete, PANEL_INACTIVE, FALSE, NULL);
		xv_set (ip->move, PANEL_INACTIVE, FALSE, NULL);
		break;

	case PANEL_LIST_OP_VALIDATE:
		break;

	case PANEL_LIST_OP_DELETE:
		break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `soundsource'.
 */
void
rplaytool_s_soundsource_notify_callback(item, value, event)
	Panel_item	item;
	int		value;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	if (value == 0)
	{
		curr_soundlist = Rplaytool_s->soundlist;
		load_soundlist ();
	}
	else if (value == 1)
	{
		curr_soundlist = Rplaytool_s->disklist;
		load_disklist (0);
	}

	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	if (value == 0)
	{
		xv_set(Rplaytool_s->controls9, XV_SHOW, TRUE, NULL);
	}
	
	if (value == 1)
	{
		xv_set(Rplaytool_s->controls7, XV_SHOW, TRUE, NULL);
	}
	
	/* gxv_end_connections */

}

/*
 * Notify callback function for `directory'.
 */
Panel_setting
do_cd(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	char *	value = (char *) xv_get(item, PANEL_VALUE);
	
	if (value && *value)
	{
		load_disklist (value);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return panel_text_notify(item, event);
}

/*
 * Menu handler for `delete_menu (Selected sounds)'.
 */
Menu_item
playlist_delete(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	char *p;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		for (i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_FIRST_SELECTED);
		     i != -1;
		     i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_NEXT_SELECTED, i))
		{
		    do_playlist_delete (curr_playlist, i);
		}
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `delete_menu (All sounds)'.
 */
Menu_item
playlist_delete_all(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	char *p;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		xv_set (playlist[curr_playlist].list, XV_SHOW, FALSE, NULL);

		do_playlist_delete_all (curr_playlist);
		
		xv_set (ip->delete, PANEL_INACTIVE, TRUE, NULL);

		xv_set (playlist[curr_playlist].list, XV_SHOW, TRUE, NULL);
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `add_menu (Select sound)'.
 */
Menu_item
add_sounds(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	char *sound, *cwd, *p;
	char buf[RPTP_MAX_LINE];
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		i = (int) xv_get (curr_soundlist, PANEL_LIST_FIRST_SELECTED);
		sound = (char *) xv_get (curr_soundlist, PANEL_LIST_STRING, i);

		if (curr_soundlist == Rplaytool_s->disklist)
		{
			if ((int) xv_get(curr_soundlist, PANEL_LIST_CLIENT_DATA, i) == 0) /* a file */
			{
			    cwd = (char *) xv_get (ip->directory, PANEL_VALUE);
			    sprintf (buf, "%s", sound);
			}
			else
			{
			    /* ignore directories */
			    return item;
			}
		}
		else
		{
		    cwd = "";
		    sprintf (buf, "%s", sound);
		}

		do_playlist_append (curr_playlist, cwd, buf);
		
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `add_menu (All sounds)'.
 */
Menu_item
add_all_sounds(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i, n;
	char *sound, *cwd, *p;
	char buf[RPTP_MAX_LINE];
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
		busy (Rplaytool_s->s, TRUE);
		xv_set (playlist[curr_playlist].list, XV_SHOW, FALSE, NULL);
		n = (int) xv_get (curr_soundlist, PANEL_LIST_NROWS);
		for (i = 0; i < n; i++)
		{
			sound = (char *) xv_get (curr_soundlist, PANEL_LIST_STRING, i);

			if (curr_soundlist == Rplaytool_s->disklist)
			{
				if ((int) xv_get(curr_soundlist, PANEL_LIST_CLIENT_DATA, i) == 0) /* a file */
				{
				    cwd = (char *) xv_get (ip->directory, PANEL_VALUE);
				    sprintf (buf, "%s", sound);
				}
				else
				{
				    /* ignore directories */
				    continue;
				}
			}
			else
			{
			    cwd = "";
			    sprintf (buf, "%s", sound);
			}

			do_playlist_append (curr_playlist, cwd, buf);
		}
		
		xv_set (playlist[curr_playlist].list, XV_SHOW, TRUE, NULL);
		busy (Rplaytool_s->s, FALSE);
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Notify callback function for `stopit'.
 */
void
do_stopit(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);

	if (playlist[curr_playlist].id > 0)
	{
	    do_playlist_stop (curr_playlist);
	
	    playlist[curr_playlist].id = -1;
	    playlist[curr_playlist].auto_play = 0;
	    playlist[curr_playlist].curr++;
	    if (playlist[curr_playlist].curr >= playlist[curr_playlist].size)
	    {
		playlist[curr_playlist].curr = 0;
	    }
	
	    playlist_update_icons (curr_playlist);
	}
	else if (playlist[curr_playlist].delay > 0)
	{
	    playlist[curr_playlist].delay = -1;

	    playlist[curr_playlist].id = -1;
	    playlist[curr_playlist].auto_play = 0;
	    playlist[curr_playlist].curr++;
	    if (playlist[curr_playlist].curr >= playlist[curr_playlist].size)
	    {
		playlist[curr_playlist].curr = 0;
	    }
	    
	    playlist_update_icons (curr_playlist);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Notify callback function for `sort'.
 */
void
do_soundsort(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	busy (ip->s, TRUE);
	sort_list (curr_soundlist);
	busy (ip->s, FALSE);
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Notify callback function for `reload'.
 */
void
do_reload(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	if (curr_soundlist == Rplaytool_s->disklist)
	{
	    load_disklist (0);
	}
	else
	{
	    load_soundlist ();
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/* Load a file into curr_playlist. */
int
file_load_file (file)
    char *file;
{
    FILE *fp;
    
    fp = fopen (file, "r");
    if (fp == NULL)
    {
	notice (Rplaytool_f->f, NULL, NULL, "Can't read %s", file);
	return -1;
    }

    /* Make sure playlist files are stored with complete pathnames. */
    if (file[0] != '/')
    {
        char cwd[MAXPATHLEN];

        getcwd (cwd, sizeof (cwd));
        sprintf (playlist[curr_playlist].filename, "%s/%s", cwd, file);
    }
    else
    {
        strcpy (playlist[curr_playlist].filename, file);
    }

    busy (Rplaytool_f->f, TRUE);
    xv_set (playlist[curr_playlist].list, XV_SHOW, FALSE, NULL);

    do_playlist_delete_all (curr_playlist);
    do_playlist_load (curr_playlist, fp);
    fclose (fp);
    
    xv_set (playlist[curr_playlist].list, XV_SHOW, TRUE, NULL);
    busy (Rplaytool_f->f, FALSE);

    return 0;
}

/* Save curr_playlist in a file. */
file_save_file (file)
    char *file;
{
    FILE *fp;
    INFO *info;
    int i;

    if (access (file, R_OK) == 0)
    {
	if (notice (Rplaytool_f->f, "Yes", "No", "Overwrite %s?", file) == 2)
	{
	    return;
	}
    }
    
    fp = fopen (file, "w");
    if (fp == NULL)
    {
	notice (Rplaytool_f->f, NULL, NULL, "Can't create %s", file);
	return;
    }

    busy (Rplaytool_f->f, TRUE);

    do_playlist_save (curr_playlist, fp);
    fclose (fp);

    busy (Rplaytool_f->f, FALSE);
}
    
/* Load a directory into the filelist popup. */
file_load_dir (new_dir)
    char *new_dir;
{
    char cwd[MAXPATHLEN];
    DIR *dir;
    struct dirent *dp;
    struct stat st;
    int row;
    Scrollbar scrollbar;

    busy (Rplaytool_f->f, TRUE);

    if (new_dir)
    {
	chdir (new_dir);
    }

    getcwd (cwd, sizeof (cwd));

    dir = opendir (".");
    if (dir == NULL)
    {
	exit (1);
    }

    xv_set (Rplaytool_f->filelist,
	    PANEL_LIST_DELETE_ROWS, 0,
	    (int) xv_get (Rplaytool_f->filelist, PANEL_LIST_NROWS),
	    NULL);

    xv_set (Rplaytool_f->filelist, XV_SHOW, FALSE, NULL);
    
    row = 0;
    xv_set (Rplaytool_f->filelist,
	    PANEL_LIST_INSERT, row,
	    PANEL_LIST_STRING, row, "..",
	    PANEL_LIST_CLIENT_DATA, row, 1, /* a directory */
	    PANEL_LIST_GLYPH, row, icons[ICON_DIRECTORY].image,
	    NULL);
    row++;

    for (;;)
    {
	dp = readdir (dir);
	if (dp == NULL)
	{
	    closedir (dir);
	    break;
	}
	else if (strcmp (dp->d_name, ".") == 0
		 || strcmp (dp->d_name, "..") == 0)
	{
	    continue;
	}
	else
	{
	    stat (dp->d_name, &st);

	    if (S_ISDIR (st.st_mode))
	    {
		xv_set (Rplaytool_f->filelist,
			PANEL_LIST_INSERT, row,
			PANEL_LIST_STRING, row, dp->d_name,
			PANEL_LIST_CLIENT_DATA, row, 1, /* a directory */
			PANEL_LIST_GLYPH, row, icons[ICON_DIRECTORY].image,
			NULL);
	    }
	    else
	    {
		xv_set (Rplaytool_f->filelist,
			PANEL_LIST_INSERT, row,
			PANEL_LIST_STRING, row, dp->d_name,
			PANEL_LIST_CLIENT_DATA, row, 0, /* a file */
			PANEL_LIST_GLYPH, row, icons[ICON_FILE].image,
			NULL);
	    }
	    row++;
	}
	
    }

    scrollbar = (Scrollbar) xv_get (Rplaytool_f->filelist, PANEL_LIST_SCROLLBAR);
    xv_set (scrollbar, SCROLLBAR_VIEW_START, 0, NULL);
    
    xv_set (Rplaytool_f->filelist, XV_SHOW, TRUE, NULL);

    xv_set (Rplaytool_f->filedir, PANEL_VALUE, cwd, NULL);

    busy (Rplaytool_f->f, FALSE);
}

/*
 * Notify callback function for `filedir'.
 */
Panel_setting
filedir_notify(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_f_objects *ip = (rplaytool_f_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	char *	value = (char *) xv_get(item, PANEL_VALUE);

	file_load_dir (value);
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return panel_text_notify(item, event);
}

/*
 * Notify callback function for `filelist'.
 */
int
filelist_notify(item, string, client_data, op, event, row)
	Panel_item	item;
	char		*string;
	Xv_opaque	client_data;
	Panel_list_op	op;
	Event		*event;
	int		row;
{
	rplaytool_f_objects *ip = (rplaytool_f_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	static long prev_click_time;
	struct timeval tv;
	long click_time;

	gettimeofday (&tv, 0);
	click_time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
	
	switch(op) {
	case PANEL_LIST_OP_DESELECT:
	    if (click_time - prev_click_time < 400)
	    {
		/* See if it's a directory */
		if ((int) xv_get(ip->filelist, PANEL_LIST_CLIENT_DATA, row))
		{
		    file_load_dir (string);
		}
		prev_click_time = 0;
	    }
	    break;

	case PANEL_LIST_OP_SELECT:
	    if ((int) xv_get(ip->filelist, PANEL_LIST_CLIENT_DATA, row) == 0) /* a file */
	    {
		xv_set (ip->filename, PANEL_VALUE, string, NULL);
	    }
	    prev_click_time = click_time;
	    break;

	case PANEL_LIST_OP_VALIDATE:
	    break;

	case PANEL_LIST_OP_DELETE:
	    break;
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return XV_OK;
}

/*
 * Notify callback function for `filename'.
 */
Panel_setting
filename_notify(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_f_objects *ip = (rplaytool_f_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	char *value = (char *) xv_get(item, PANEL_VALUE);
	char *dir = (char *) xv_get (ip->filedir, PANEL_VALUE);
	char *label;
	char filename[MAXPATHLEN];

	sprintf (filename, "%s/%s", dir, value);
	
	label = (char *) xv_get (ip->filedoit, PANEL_LABEL_STRING, NULL);
	if (strcmp (label, "Load") == 0)
	{
	    file_load_file (filename);
	}
	else if (strcmp (label, "Save") == 0)
	{
	    file_save_file (filename);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

	return panel_text_notify(item, event);
}

/*
 * Notify callback function for `filedoit'.
 */
void
filedoit_notify(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_f_objects *ip = (rplaytool_f_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	char *value = (char *) xv_get (ip->filename, PANEL_VALUE);
	char *dir = (char *) xv_get (ip->filedir, PANEL_VALUE);
	char *label;
	char filename[MAXPATHLEN];

	sprintf (filename, "%s/%s", dir, value);
	
	label = (char *) xv_get (ip->filedoit, PANEL_LABEL_STRING, NULL);
	if (strcmp (label, "Load") == 0)
	{
	    file_load_file (filename);
	}
	else if (strcmp (label, "Save") == 0)
	{
	    file_save_file (filename);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Notify callback function for `fileclose'.
 */
void
rplaytool_f_fileclose_notify_callback(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_f_objects *ip = (rplaytool_f_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	xv_set(Rplaytool_f->f, FRAME_CMD_PUSHPIN_IN, FALSE, NULL);
	xv_set(Rplaytool_f->f, XV_SHOW, FALSE, NULL);
	
	/* gxv_end_connections */

}

/*
 * Menu handler for `playlistfile_menu (Load...)'.
 */
Menu_item
playlistfile_load(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    if (playlist[curr_playlist].filename[0] == '\0')
	    {
		file_load_dir (NULL);
	    }
	    else
	    {
		char *p, filename[MAXPATHLEN];

		strcpy (filename, playlist[curr_playlist].filename);
		p = strrchr (filename, '/');
		if (p && p[1])
		{
		    *p++ = '\0';
		    xv_set (Rplaytool_f->filename, PANEL_VALUE, p);
		    file_load_dir (filename);
		}
		else
		{
		    file_load_dir (NULL);
		}
	    }
	    
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		xv_set(Rplaytool_f->f, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
		xv_set(Rplaytool_f->f, XV_SHOW, TRUE, NULL);
		
		xv_set(Rplaytool_f->f, XV_LABEL, "Load a Play List", NULL);
		
		xv_set(Rplaytool_f->filedoit, PANEL_LABEL_STRING, "Load", NULL);
		
		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `playlistfile_menu (Save...)'.
 */
Menu_item
playlistfile_save(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    if (playlist[curr_playlist].filename[0] == '\0')
	    {
		file_load_dir (NULL);
	    }
	    else
	    {
		char *p, filename[MAXPATHLEN];

		strcpy (filename, playlist[curr_playlist].filename);
		p = strrchr (filename, '/');
		if (p && p[1])
		{
		    *p++ = '\0';
		    xv_set (Rplaytool_f->filename, PANEL_VALUE, p);
		    file_load_dir (filename);
		}
		else
		{
		    file_load_dir (NULL);
		}
	    }
	    
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		xv_set(Rplaytool_f->f, FRAME_CMD_PUSHPIN_IN, TRUE, NULL);
		xv_set(Rplaytool_f->f, XV_SHOW, TRUE, NULL);
		
		xv_set(Rplaytool_f->f, XV_LABEL, "Save a Play List", NULL);
		
		xv_set(Rplaytool_f->filedoit, PANEL_LABEL_STRING, "Save", NULL);
		
		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `move_menu (Up)'.
 */
Menu_item
move_up(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;

	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_FIRST_SELECTED);
	    if (i > 0)
	    {
		do_playlist_move (curr_playlist, i, i-1);
		xv_set (playlist[curr_playlist].list, PANEL_LIST_SELECT, i-1, TRUE, NULL);
	    }
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `move_menu (Down)'.
 */
Menu_item
move_down(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_FIRST_SELECTED);
	    if (i < playlist[curr_playlist].size - 1)
	    {
		do_playlist_move (curr_playlist, i, i+1);
		xv_set (playlist[curr_playlist].list, PANEL_LIST_SELECT, i+1, TRUE, NULL);
	    }
		
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `move_menu (Top)'.
 */
Menu_item
move_top(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    xv_set (playlist[curr_playlist].list, XV_SHOW, FALSE, NULL);
	    
	    i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_FIRST_SELECTED);
	    while (i > 0)
	    {
		do_playlist_move (curr_playlist, i, i-1);
		i--;
	    }
	    xv_set (playlist[curr_playlist].list, PANEL_LIST_SELECT, 0, TRUE, NULL);

	    xv_set (playlist[curr_playlist].list, XV_SHOW, TRUE, NULL);
	    
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Menu handler for `move_menu (Bottom)'.
 */
Menu_item
move_bottom(item, op)
	Menu_item	item;
	Menu_generate	op;
{
	rplaytool_s_objects * ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);
	int i;
	
	switch (op) {
	case MENU_DISPLAY:
		break;

	case MENU_DISPLAY_DONE:
		break;

	case MENU_NOTIFY:
	    xv_set (playlist[curr_playlist].list, XV_SHOW, FALSE, NULL);	    	    

	    i = (int) xv_get (playlist[curr_playlist].list, PANEL_LIST_FIRST_SELECTED);
	    while (i < playlist[curr_playlist].size-1)
	    {
		do_playlist_move (curr_playlist, i, i+1);
		i++;
	    }
	    xv_set (playlist[curr_playlist].list,
		    PANEL_LIST_SELECT, playlist[curr_playlist].size-1, TRUE, NULL);
		
	    xv_set (playlist[curr_playlist].list, XV_SHOW, TRUE, NULL);
	    
		/* gxv_start_connections DO NOT EDIT THIS SECTION */

		/* gxv_end_connections */

		break;

	case MENU_NOTIFY_DONE:
		break;
	}
	return item;
}

/*
 * Notify callback function for `next'.
 */
void
do_next(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);

	if (playlist[curr_playlist].id > 0
	    || playlist[curr_playlist].delay > 0)
	{
	    do_playlist_stop (curr_playlist);
	    playlist[curr_playlist].auto_play = 1;
	    playlist[curr_playlist].curr++;
	    if (playlist[curr_playlist].curr >= playlist[curr_playlist].size)
	    {
		playlist[curr_playlist].curr = 0;
	    }
	    play_playlist (curr_playlist, TRUE);
	}
	else
	{
	    if (playlist[curr_playlist].curr == -1)
	    {
		playlist[curr_playlist].curr = 0;
	    }
	    playlist[curr_playlist].curr++;
	    if (playlist[curr_playlist].curr >= playlist[curr_playlist].size)
	    {
		playlist[curr_playlist].curr = 0;
	    }
	    playlist_update_icons (curr_playlist);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}

/*
 * Notify callback function for `prev'.
 */
void
do_prev(item, event)
	Panel_item	item;
	Event		*event;
{
	rplaytool_s_objects *ip = (rplaytool_s_objects *) xv_get(item, XV_KEY_DATA, INSTANCE);

	if (playlist[curr_playlist].id > 0
	    || playlist[curr_playlist].delay > 0)
	{
	    do_playlist_stop (curr_playlist);
	    playlist[curr_playlist].auto_play = 1;
	    playlist[curr_playlist].curr--;
	    if (playlist[curr_playlist].curr < 0)
	    {
		playlist[curr_playlist].curr = playlist[curr_playlist].size - 1;
	    }
	    play_playlist (curr_playlist, TRUE);
	}
	else
	{
	    playlist[curr_playlist].curr--;
	    if (playlist[curr_playlist].curr < 0)
	    {
		playlist[curr_playlist].curr = playlist[curr_playlist].size - 1;
	    }
	    playlist_update_icons (curr_playlist);
	}
	
	/* gxv_start_connections DO NOT EDIT THIS SECTION */

	/* gxv_end_connections */

}
