/*
    GDAM - Geoff & Dave's Audio Mixer
    Copyright (C) 1999    Dave Benson, Geoff Matters.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
        geoff@ugcs.caltech.edu <Geoff Matters>
*/
#ifndef __GDAM_TOPLEVEL_H_
#define __GDAM_TOPLEVEL_H_

#include <gtk/gtkobject.h>
#include "gdammodel.h"

GtkType gdam_toplevel_get_type();
#define GDAM_TYPE_TOPLEVEL              (gdam_toplevel_get_type ())
#define GDAM_TOPLEVEL(obj)              (GTK_CHECK_CAST ((obj), GDAM_TYPE_TOPLEVEL, GdamToplevel))
#define GDAM_TOPLEVEL_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GDAM_TYPE_TOPLEVEL, GdamToplevelClass))
#define GDAM_IS_TOPLEVEL(obj)           (GTK_CHECK_TYPE ((obj), GDAM_TYPE_TOPLEVEL))
#define GDAM_IS_TOPLEVEL_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GDAM_TYPE_TOPLEVEL))

typedef struct _GdamToplevel GdamToplevel;
typedef struct _GdamToplevelClass GdamToplevelClass;
typedef struct _GdamToplevelDevice GdamToplevelDevice;

/*
 *                         Toplevel
 *
 * Controls any number of devices (with their toplevel mixer)
 * on a single GdamChannel.
 *
 * This makes device-switching easy...
 */
struct _GdamToplevelClass {
	GdamModelClass	        model_class;
	void                  (*device_list_changed)(GdamToplevel* toplevel);
};

struct _GdamToplevelDevice {
	int			ref_count;
	GdamToplevel*		toplevel;

	char*                   device_name;

	/* These may be zero if we are still acquiring their ids. */
	int			device_id;

	/* The mixer which is feeding that device. */
	int			mixer_id;

	int			recorder_id;

	/* This is only used if the mixer isn't available but
	 * a source has been added
	 * (ie this should be == NULL whenever mixer_id != 0)*/
	GSList*			waiting_requests;
};

struct _GdamToplevel {
	GdamModel		base;

	/* Map from model pointers to an info structure. */
	GHashTable*		model_to_info;

	/* This is the device used when creating new generic
	 * sources.  (Perhaps relegate this to launcher). */
	GdamToplevelDevice*	default_device;

	/* List of available devices. */
	GSList*			devices;

	/* Device name -> GdamToplevelMix mapping. */
	GHashTable*		devices_by_name;
};

GdamToplevel* gdam_toplevel_new         (GdamChannel*           channel);
GdamToplevel* gdam_toplevel_get_global  (GdamChannel*           channel);

/* Whether the device was already open.
 * If this returns TRUE, it means the device has been opened or if
 *                       mixer_id is FALSE is permanently closed.
 *     ****     In other words, TRUE means "result is immediate"
 *                      **NOT**            "device open succeeded"
 */
typedef void   (*GdamToplevelOpened)    (guint                  device_id,
                                         guint                  mixer_id,
					 gpointer               user_data);
typedef void   (*GdamToplevelOpenFailed)(gpointer               user_data);

void          gdam_toplevel_open_device (GdamToplevel*          toplevel,
                                         const char*            device_name,
					 GdamToplevelOpened     succeeded,
					 GdamToplevelOpenFailed failed,
					 gpointer               user_data);
gboolean      gdam_toplevel_is_device_open
                                        (GdamToplevel*          toplevel,
					 const char*            device_name);

void          gdam_toplevel_add_device  (GdamToplevel*          toplevel,
                                         const char*            device_name,
					 guint                  device_id,
					 guint                  mixer_id);

/* Returns whether the device exists-- the device open might
 * still fail for device permissions reasons... */
gboolean      gdam_toplevel_reopen_device(GdamToplevel*         toplevel,
                                         const char*            device_name);
                                     

void          gdam_toplevel_add_child   (GdamToplevel*   toplevel,
                                         GdamModel*      model);
void          gdam_toplevel_remove_child(GdamToplevel*   toplevel,
                                         GdamModel*      model);
void          gdam_toplevel_set_child_device
				        (GdamToplevel*   toplevel,
					 GdamModel*      model,
					 const char*     device_name);
void          gdam_toplevel_set_misses_data
				        (GdamToplevel*   toplevel,
					 GdamModel*      model,
					 gboolean        misses_data);

void          gdam_toplevel_set_recorder(GdamToplevel*   toplevel,
                                         const char*     device_name,
					 int             recorder_id);
/* Private functions.*/

/* Notify things that device list has changed. */
void          gdam_toplevel_device_list_changed(GdamToplevel*);
                           
extern const char* gdam_toplevel_server_mix_class_name;
#endif
