1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
/*
* XMMS Crossfade Plugin
* Copyright (C) 2000-2001 Peter Eisenlohr <p.eisenlohr@gmx.net>
*
* based on the original OSS Output Plugin
* Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
*
* 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.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gtk/gtk.h>
#include "monitor.h"
#include "crossfade.h"
#include "interface.h"
#include "support.h"
static GtkWidget *monitor_win;
static GtkWidget *monitor_display_drawingarea;
static GtkProgress *monitor_output_progress;
static gboolean monitor_active = FALSE;
static guint monitor_tag;
static gint monitor_output_max;
static gint monitor_closing;
#define RUNNING 0
#define CLOSING 1
#define CLOSED 2
#define SMOD(x,n) (((x)<0)?((n)-(x))%(n):((x)%(n)))
static void draw_wrapped(GtkWidget *widget, gint pos, gint width, GdkGC *gc)
{
GdkDrawable *win = widget->window;
gint ww = widget->allocation.width;
gint wh = widget->allocation.height;
if(width <= 0) return;
if(width < ww) {
gint x = SMOD(pos, ww);
if((x+width) >= ww) {
gdk_draw_rectangle(win, gc, TRUE, x, 0, ww-x, wh);
gdk_draw_rectangle(win, gc, TRUE, 0, 0, width-(ww-x), wh);
}
else gdk_draw_rectangle(win, gc, TRUE, x, 0, width, wh);
}
else gdk_draw_rectangle(win, gc, TRUE, 0, 0, ww, wh);
}
gboolean on_monitor_display_drawingarea_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
{
if(buffer && buffer->size && output_opened) {
gint ww = widget->allocation.width;
gint x1 = 0;
gint x2 = buffer->used;
gint x3 = buffer->used + buffer->mix;
gint x4 = buffer->size;
x1 = (gint64)(x1 + buffer->rd_index) * ww / buffer->size;
x2 = (gint64)(x2 + buffer->rd_index) * ww / buffer->size;
x3 = (gint64)(x3 + buffer->rd_index) * ww / buffer->size;
x4 = (gint64)(x4 + buffer->rd_index) * ww / buffer->size;
draw_wrapped(widget, x1, x2-x1, widget->style->fg_gc[GTK_STATE_NORMAL]);
draw_wrapped(widget, x2, x3-x2, widget->style->white_gc);
draw_wrapped(widget, x3, x4-x3, widget->style->bg_gc[GTK_STATE_NORMAL]);
}
else
gdk_window_clear_area(widget->window,
event->area.x, event->area.y,
event->area.width, event->area.height);
return TRUE;
}
gboolean on_monitor_win_delete_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
/* V0.1.1 20000618: removed, didn't make much sense since it wasn't saved */
/* if(config) config->enable_monitor = FALSE; */
return(FALSE); /* FALSE: destroy window */
}
void xfade_check_monitor_win()
{
if(config->enable_monitor) {
if(!monitor_win && !(monitor_win = create_monitor_win())) {
DEBUG(("[crossfade] check_monitor_win: error creating window!\n"));
return;
}
/* automatically set config_win to NULL when window is destroyed */
gtk_signal_connect(GTK_OBJECT(monitor_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &monitor_win);
/* show window */
gtk_widget_show(monitor_win);
/* get pointers to widgets (used by crossfade.c to update the monitor) */
monitor_display_drawingarea = lookup_widget(monitor_win, "monitor_display_drawingarea");
monitor_output_progress = GTK_PROGRESS(lookup_widget(monitor_win, "monitor_output_progress"));
/* force gtk_progress_configure */
monitor_output_max = 0;
}
else
if(monitor_win) gtk_widget_destroy(monitor_win);
}
gint xfade_update_monitor(gpointer userdata)
{
/* HACK: (see xfade_stop_monitor() below) */
if(monitor_closing == CLOSED)
return TRUE;
if(monitor_closing == CLOSING)
monitor_closing = CLOSED;
/* lock buffer */
pthread_mutex_lock(&buffer_mutex);
if(monitor_win) {
if(monitor_display_drawingarea) {
GdkRectangle update_rect;
update_rect.x = 0;
update_rect.y = 0;
update_rect.width = monitor_display_drawingarea->allocation.width;
update_rect.height = monitor_display_drawingarea->allocation.height;
if(monitor_closing == CLOSED)
gdk_window_clear_area(monitor_display_drawingarea->window,
update_rect.x, update_rect.y,
update_rect.width, update_rect.height);
else
gtk_widget_draw(monitor_display_drawingarea, &update_rect);
}
if(monitor_output_progress) {
if(monitor_closing == CLOSED) {
gtk_progress_configure(monitor_output_progress, 0, 0, 0);
monitor_output_max = 0;
}
else {
if(output_opened) {
gint output_used = the_op->written_time() - the_op->output_time();
if(output_used > monitor_output_max) {
monitor_output_max = output_used;
gtk_progress_configure(monitor_output_progress,
output_used, 0, monitor_output_max);
}
else
gtk_progress_set_value(monitor_output_progress, output_used);
}
else {
gtk_progress_configure(monitor_output_progress, 0, 0, 0);
monitor_output_max = 0;
}
}
}
}
/* unlock buffer */
pthread_mutex_unlock(&buffer_mutex);
return TRUE; /* continue calling this function */
}
void xfade_start_monitor()
{
if(monitor_active) return;
monitor_output_max = 0;
monitor_closing = RUNNING;
monitor_active = TRUE;
monitor_tag = gtk_timeout_add(33L, xfade_update_monitor, NULL);
}
void xfade_stop_monitor()
{
gint max_wait = 10;
if(!monitor_active) return;
/* HACK, ugly HACK: force a final call of xfade_update_monitor */
monitor_closing = CLOSING;
while((monitor_closing == CLOSING) && (--max_wait > 0))
xmms_usleep(10000);
if(max_wait <= 0)
DEBUG(("[crossfade] stop_monitor: timeout!\n"));
/* stop calling xfade_update_monitor() */
gtk_timeout_remove(monitor_tag);
monitor_active = FALSE;
}
|