/*
    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>
*/

/*
 * A widget which draws samples graphically.
 *
 * That is, it draws the amplitude on the y-axis
 * and lets the user zoom in and scroll around.
 *
 * Used by the buffer editor and the beat calculator,
 * and serves as a general widget for inclusion
 * in other skins which need such a view.
 */

#ifndef __GDAM_BUFFER_VIEWPORT_H_
#define __GDAM_BUFFER_VIEWPORT_H_


typedef struct _GdamBufferViewport GdamBufferViewport;
typedef struct _GdamBufferViewportClass GdamBufferViewportClass;

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include "gdamskin.h"
#include "gdamcursor.h"

GtkType gdam_buffer_viewport_get_type();
#define GDAM_TYPE_BUFFER_VIEWPORT			(gdam_buffer_viewport_get_type ())
#define GDAM_BUFFER_VIEWPORT(obj)              (GTK_CHECK_CAST ((obj), GDAM_TYPE_BUFFER_VIEWPORT, GdamBufferViewport))
#define GDAM_BUFFER_VIEWPORT_CLASS(klass)      (GTK_CHECK_CLASS_CAST ((klass), GDAM_TYPE_BUFFER_VIEWPORT, GdamBufferViewportClass))
#define GDAM_IS_BUFFER_VIEWPORT(obj)           (GTK_CHECK_TYPE ((obj), GDAM_TYPE_BUFFER_VIEWPORT))
#define GDAM_IS_BUFFER_VIEWPORT_CLASS(klass)   (GTK_CHECK_CLASS_TYPE ((klass), GDAM_TYPE_BUFFER_VIEWPORT))

#include "gdambufferviewport-render.h"

struct _GdamBufferViewportClass
{
  GdamSkinClass	skin_class;
  void          (*selection_changed)(GdamBufferViewport *viewport);
  void          (*view_changed)     (GdamBufferViewport *viewport);
  void          (*length_changed)   (GdamBufferViewport *viewport);
  void          (*buffer_changed)   (GdamBufferViewport *viewport);
};
struct _GdamBufferViewport
{
  GdamSkin                skin;

  GdamCursorType          cursor;

  /* Buffer that we are viewing, if any. */
  guint                   buffer_id;

  /* Height and width of the buffer in pixels. */
  int                     draw_width, draw_height;

  /* Generic rendering */
  GdamBufferViewportRenderInitFunc render_init;
  GdamBufferViewportRenderFunc render_fg;
  GdamBufferViewportRenderFunc render_bg;
  GDestroyNotify render_state_destroy;

  gpointer                render_data;
  GDestroyNotify          render_data_destroy;

  /* small hack to make the rendering style available to the argument system */
  char                   *render_mode;

  /* to scroll the display on passing the end of the screen. */
  guint			  scroll_timeout;


  GdkPixmap              *backbuffer;

  /* list of adornments */
  GdamBufferViewportAdornment *first_adornment;
  GdamBufferViewportAdornment *last_adornment;

  /* Usually 44100 but the beat_calculator uses this... */
  int                     samples_per_second;

  /* Are we using the buffer manager for this buffer? */
  gboolean                use_buffer_manager;

  /* the connection from the buffer manager which will notify
   * us when the buffer changes. */
  int                     connection_id;

  /* Sample length, if not using the buffer manager. */
  gdouble                 sample_length;

  /* Start/end times for the view. */
  gdouble                 time_start;
  gdouble                 time_length;

  /* Where a selection is, if it exists. */
  gboolean                is_selectable;
  gboolean                has_selection;
  gdouble                 selection_start;
  gdouble                 selection_length;

  /* Whether a query of the server is outstanding. */
  gboolean                getting_profile;

  /* If a query is outstanding, don't query again if the size
   * changes -- instead set this flag to query the server
   * once the next query comes in.  This prevents backlogging.  */
  gboolean                redo_query;

  /* If nonzero, a redraw is pending. */
  guint                   redraw_idle_thread;
  guint                   redraw_x, redraw_y;
  guint                   redraw_width, redraw_height;

  /* whether to draw left/right/averaged */
  char                   *mode;

  /* data from the server */
  gboolean                last_samples_is_double;
  guint                   last_num_samples;
  guint                   last_num_channels;
  gpointer                last_samples;
  gint                    last_valid_output_start;
  gint                    last_valid_output_end;

  /* if is_dragging && dragging_adornment==NULL
   * then a selection is being highlighted. */
  gboolean                is_dragging;
  GdamBufferViewportAdornment *dragging_adornment;
  GdamBufferViewportDragInfo drag_info;

  /* Number of dots to capture per output pixel. */
  int                     density;
};

/* Create a new GdamBufferViewport -- you *must* use this function
 * to leave the viewport in a usable state. */
GdamBufferViewport* 
           gdam_buffer_viewport_new_shown     (GdamChannel        *channel);

void       gdam_buffer_viewport_set_buffer_id (GdamBufferViewport *viewport,
                                               guint               buffer_id);
void       gdam_buffer_viewport_set_view      (GdamBufferViewport *viewport,
                                               gdouble             start,
                                               gdouble             length);
void       gdam_buffer_viewport_set_selection (GdamBufferViewport *viewport,
                                               gdouble             start,
                                               gdouble             length);
void       gdam_buffer_viewport_set_mode      (GdamBufferViewport *viewport,
                                               const char         *mode);
const char*gdam_buffer_viewport_get_mode      (GdamBufferViewport *viewport);
void       gdam_buffer_viewport_set_zoom      (GdamBufferViewport *viewport,
                                               gdouble             zoom);
void       gdam_buffer_viewport_set_center    (GdamBufferViewport *viewport,
                                               gdouble             zoom);
void       gdam_buffer_viewport_maybe_uncache(GdamBufferViewport* viewport);

/* Maybe cause requeries of server -- possibly blocked by backlog
 * protection. */
void       gdam_buffer_viewport_buffer_changed(GdamBufferViewport *viewport);
void       gdam_buffer_viewport_changed       (GdamBufferViewport *viewport);

/* Snap the window to the exact length of the sample. */
void       gdam_buffer_viewport_whole_sample  (GdamBufferViewport *viewport);

/* Private: initialize the main_widget to the GtkEventBox.
 * (It doesn't get shown...). */
void       gdam_buffer_viewport_new_event_box (GdamBufferViewport *viewport);

void       gdam_buffer_viewport_queue_redraw  (GdamBufferViewport *viewport);
void       gdam_buffer_viewport_queue_redraw_part
                                              (GdamBufferViewport *viewport,
					       guint               x,
					       guint               y,
					       guint               width,
					       guint               height);

void       gdam_buffer_viewport_set_length    (GdamBufferViewport *viewport,
                                               gdouble             length);
void       gdam_buffer_viewport_set_beat_times(GdamBufferViewport *viewport,
                                               int                 num_times,
                                               const gdouble      *times);
void       gdam_buffer_viewport_remove_beat_times
                                              (GdamBufferViewport *viewport);
gdouble    gdam_buffer_viewport_get_sample_length
                                              (GdamBufferViewport *viewport);


/* private */
void        gdam_buffer_viewport_destroy_all_adornments (GdamBufferViewport *v);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif
