Logo Search packages:      
Sourcecode: lash version File versions  Download package

interface.c

/*
 *   LASH 
 *    
 *   Copyright (C) 2002 Robert Ham <rah@bash.sh>
 *    
 *   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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"

#ifdef HAVE_GTK2

#  define _GNU_SOURCE

#  include <unistd.h>

#  include <gtk/gtk.h>

#  include "interface.h"
#  include "synth.h"
#  include "lash.h"

#  define GAIN_UPPER       10.0
#  define MODULATION_UPPER 50.0
#  define ENVELOPE_UPPER   1.0

static gboolean show_toolbar = TRUE;
GtkWidget *adsr_display = NULL;

GtkWidget *modulation_range;
GtkWidget *attack_range;
GtkWidget *decay_range;
GtkWidget *sustain_range;
GtkWidget *release_range;
GtkWidget *gain_range;
GtkWidget *harmonic_spin;
GtkWidget *subharmonic_spin;
GtkWidget *transpose_spin;

int interface_up = 0;

gboolean
quit_cb()
{
      quit = 1;
      gtk_main_quit();
      return TRUE;
}

gboolean
idle_cb(void *data)
{
      if (quit) {
            gtk_main_quit();
            return FALSE;
      }

      if (lash_enabled(lash_client))
            lash_main();

      gtk_range_set_value(GTK_RANGE(modulation_range), modulation);
      gtk_range_set_value(GTK_RANGE(attack_range), attack);
      gtk_range_set_value(GTK_RANGE(decay_range), decay);
      gtk_range_set_value(GTK_RANGE(sustain_range), sustain);
      gtk_range_set_value(GTK_RANGE(release_range), release);
      gtk_range_set_value(GTK_RANGE(gain_range), gain);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(harmonic_spin), harmonic);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(subharmonic_spin), subharmonic);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(transpose_spin), transpose);

      usleep(1000);

      return TRUE;
}

void
save_cb()
{
      lash_event_t *event;

      event = lash_event_new_with_type(LASH_Save);
      lash_send_event(lash_client, event);
}

gboolean
toggle_button_bar_cb(GtkWidget * widget, GdkEventButton * event,
                               gpointer data)
{
      GtkWidget *handle;

      handle = GTK_WIDGET(data);

      show_toolbar = !show_toolbar;
      if (show_toolbar)
            gtk_widget_show(handle);
      else
            gtk_widget_hide(handle);

      return TRUE;
}

void
range_cb(GtkRange * range, gpointer data)
{
      double *val;

      val = (double *)data;
      *val = gtk_range_get_value(range);

      gtk_widget_queue_draw_area(adsr_display, 0, 0,
                                             adsr_display->allocation.width,
                                             adsr_display->allocation.height);
}

void
spin_cb(GtkSpinButton * spinbutton, gpointer data)
{
      int *val;

      val = (int *)data;
      *val = gtk_spin_button_get_value(spinbutton);
}

gboolean
envelope_display_expose_cb(GtkWidget * widget, GdkEventExpose * event,
                                       gpointer data)
{
      GdkDrawable *window;
      GdkGC *gc;
      gint envelope_width;
      gint envelope_height;
      gint attack_width;
      gint attack_height;
      gint decay_width;
      gint sustain_width;
      gint sustain_height;
      gint release_width;
      gdouble total;

      /* get all the drawing bits */
      window = widget->window;
      gc = widget->style->fg_gc[GTK_WIDGET_STATE(widget)];

      envelope_height = widget->allocation.height;
      envelope_width = widget->allocation.width;

      /* calculate the display variables */
      total = attack + decay + release;
      total += (total / 3);
      attack_width = (envelope_width / total) * attack;
      decay_width = (envelope_width / total) * decay;
      release_width = (envelope_width / total) * release;
      sustain_width =
            (envelope_width / total) * (total - attack - decay - release);

      attack_height = 0;
      sustain_height = envelope_height - envelope_height * sustain;

      /* do the drawing */
      gdk_draw_line(window, gc,
                          0, envelope_height, attack_width, attack_height);

      gdk_draw_line(window, gc,
                          attack_width, attack_height,
                          attack_width + decay_width, sustain_height);

      gdk_draw_line(window, gc,
                          attack_width + decay_width, sustain_height,
                          attack_width + decay_width + sustain_width, sustain_height);

      gdk_draw_line(window, gc,
                          attack_width + decay_width + sustain_width, sustain_height,
                          envelope_width, envelope_height);

      return TRUE;
}

void *
interface_main(void *data)
{
      /* for misc ops */
      GtkWidget *label;
      GtkWidget *box;

      GtkWidget *window;
      GtkWidget *main_box;
      GtkWidget *button_bar_handle;
      GtkWidget *button_bar;
      GtkWidget *synthesis_frame;
      GtkWidget *synthesis_box;
      GtkWidget *envelope_frame;
      GtkWidget *envelope_table;

      /* window */
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
      gtk_window_set_title(GTK_WINDOW(window), alsa_client_name);
      gtk_window_set_default_size(GTK_WINDOW(window), 340, 370);
      g_signal_connect(G_OBJECT(window), "delete_event",
                               G_CALLBACK(quit_cb), NULL);

      /* main box */
      main_box = gtk_vbox_new(FALSE, 0);
      gtk_widget_show(main_box);
      gtk_container_add(GTK_CONTAINER(window), main_box);

      /* toolbar */

      button_bar_handle = gtk_handle_box_new();
      gtk_widget_show(button_bar_handle);
      gtk_box_pack_start(GTK_BOX(main_box), button_bar_handle, FALSE, TRUE, 0);

      button_bar = gtk_toolbar_new();
      gtk_widget_show(button_bar);
      gtk_container_add(GTK_CONTAINER(button_bar_handle), button_bar);

      gtk_toolbar_insert_stock(GTK_TOOLBAR(button_bar),
                                           GTK_STOCK_SAVE,
                                           "Tell the lash server to save the project",
                                           "Tell the lash server to save the project",
                                           G_CALLBACK(save_cb), NULL, -1);

      gtk_toolbar_insert_stock(GTK_TOOLBAR(button_bar),
                                           GTK_STOCK_QUIT,
                                           "Close the synth",
                                           "Close the synth",
                                           G_CALLBACK(quit_cb), NULL, -1);

      /* 
       * Synthesis frame
       */
      synthesis_frame = gtk_frame_new("Synthesis");
      gtk_widget_show(synthesis_frame);
      gtk_container_set_border_width(GTK_CONTAINER(synthesis_frame), 4);
      gtk_box_pack_start(GTK_BOX(main_box), synthesis_frame, FALSE, TRUE, 0);

      /* but the label into an event box to get the button clicks */
      label = gtk_label_new("Synthesis");
      gtk_widget_show(label);

      box = gtk_event_box_new();
      gtk_widget_show(box);
      gtk_container_add(GTK_CONTAINER(box), label);
      gtk_widget_add_events(box, GDK_BUTTON_PRESS_MASK);
      g_signal_connect(G_OBJECT(box), "button-press-event",
                               G_CALLBACK(toggle_button_bar_cb), button_bar_handle);
      gtk_frame_set_label_widget(GTK_FRAME(synthesis_frame), box);

      synthesis_box = gtk_vbox_new(FALSE, 0);
      gtk_widget_show(synthesis_box);
      gtk_container_add(GTK_CONTAINER(synthesis_frame), synthesis_box);

      box = gtk_hbox_new(FALSE, 0);
      gtk_widget_show(box);
      gtk_box_pack_start(GTK_BOX(synthesis_box), box, TRUE, TRUE, 0);

      /* modulation */
      box = gtk_hbox_new(FALSE, 0);
      gtk_widget_show(box);
      gtk_box_pack_start(GTK_BOX(synthesis_box), box, TRUE, TRUE, 4);

      label = gtk_label_new("Modulation");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);

      modulation_range =
            gtk_hscale_new_with_range(0.0, MODULATION_UPPER,
                                                  MODULATION_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(modulation_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(modulation_range), 5);
      gtk_range_set_value(GTK_RANGE(modulation_range), modulation);
      g_signal_connect(G_OBJECT(modulation_range), "value-changed",
                               G_CALLBACK(range_cb), &modulation);
      gtk_widget_show(modulation_range);
      gtk_box_pack_start(GTK_BOX(box), modulation_range, TRUE, TRUE, 0);

      box = gtk_hbox_new(FALSE, 4);
      gtk_widget_show(box);
      gtk_box_pack_start(GTK_BOX(synthesis_box), box, TRUE, TRUE, 0);

      /* harmonic */
      label = gtk_label_new("Harmonic");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);

      harmonic_spin = gtk_spin_button_new_with_range(1.0, 100.0, 1.0);
      gtk_spin_button_set_digits(GTK_SPIN_BUTTON(harmonic_spin), 0);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(harmonic_spin), harmonic);
      g_signal_connect(G_OBJECT(harmonic_spin), "value-changed",
                               G_CALLBACK(spin_cb), &harmonic);
      gtk_widget_show(harmonic_spin);
      gtk_box_pack_start(GTK_BOX(box), harmonic_spin, TRUE, TRUE, 0);

      /* subharmonic */
      label = gtk_label_new("Subharmonic");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);

      subharmonic_spin = gtk_spin_button_new_with_range(1.0, 100.0, 1.0);
      gtk_spin_button_set_digits(GTK_SPIN_BUTTON(subharmonic_spin), 0);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(subharmonic_spin), subharmonic);
      g_signal_connect(G_OBJECT(subharmonic_spin), "value-changed",
                               G_CALLBACK(spin_cb), &subharmonic);
      gtk_widget_show(subharmonic_spin);
      gtk_box_pack_start(GTK_BOX(box), subharmonic_spin, TRUE, TRUE, 0);

      /* transpose */
      label = gtk_label_new("Transpose");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);

      transpose_spin = gtk_spin_button_new_with_range(-144.0, 144.0, 1.0);
      gtk_spin_button_set_digits(GTK_SPIN_BUTTON(transpose_spin), 0);
      gtk_spin_button_set_value(GTK_SPIN_BUTTON(transpose_spin), transpose);
      g_signal_connect(G_OBJECT(transpose_spin), "value-changed",
                               G_CALLBACK(spin_cb), &transpose);
      gtk_widget_show(transpose_spin);
      gtk_box_pack_start(GTK_BOX(box), transpose_spin, TRUE, TRUE, 0);

      /* gain */
      box = gtk_hbox_new(FALSE, 0);
      gtk_widget_show(box);
      gtk_box_pack_start(GTK_BOX(synthesis_box), box, TRUE, TRUE, 4);

      label = gtk_label_new("Gain");
      gtk_widget_show(label);
      gtk_box_pack_start(GTK_BOX(box), label, FALSE, TRUE, 0);

      gain_range =
            gtk_hscale_new_with_range(0.0, GAIN_UPPER, GAIN_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(gain_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(gain_range), 5);
      gtk_range_set_value(GTK_RANGE(gain_range), gain);
      g_signal_connect(G_OBJECT(gain_range), "value-changed",
                               G_CALLBACK(range_cb), &gain);
      gtk_widget_show(gain_range);
      gtk_box_pack_start(GTK_BOX(box), gain_range, TRUE, TRUE, 0);

      /*
       * envelope frame
       */
      envelope_frame = gtk_frame_new("Envelope");
      gtk_widget_show(envelope_frame);
      gtk_container_set_border_width(GTK_CONTAINER(envelope_frame), 4);
      gtk_box_pack_start(GTK_BOX(main_box), envelope_frame, TRUE, TRUE, 0);

      box = gtk_vbox_new(FALSE, 0);
      gtk_widget_show(box);
      gtk_container_add(GTK_CONTAINER(envelope_frame), box);

      /* adsr display */
      adsr_display = gtk_drawing_area_new();
      gtk_widget_show(adsr_display);
/*  gtk_widget_set_size_request (adsr_display, 300, 130); */
      g_signal_connect(G_OBJECT(adsr_display), "expose_event",
                               G_CALLBACK(envelope_display_expose_cb), NULL);
      gtk_box_pack_start(GTK_BOX(box), adsr_display, TRUE, TRUE, 1);

      /* adsr controls */
      envelope_table = gtk_table_new(4, 2, FALSE);
      gtk_widget_show(envelope_table);
      gtk_box_pack_start(GTK_BOX(box), envelope_table, FALSE, TRUE, 0);

      /* attack */
      label = gtk_label_new("Attack");
      gtk_widget_show(label);
      gtk_table_attach(GTK_TABLE(envelope_table), label,
                               0, 1, 0, 1, GTK_FILL, GTK_FILL, 4, 0);

      attack_range =
            gtk_hscale_new_with_range(0.0, ENVELOPE_UPPER, ENVELOPE_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(attack_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(attack_range), 5);
      gtk_range_set_value(GTK_RANGE(attack_range), attack);
      g_signal_connect(G_OBJECT(attack_range), "value-changed",
                               G_CALLBACK(range_cb), &attack);
      gtk_widget_show(attack_range);
      gtk_table_attach(GTK_TABLE(envelope_table), attack_range,
                               1, 2, 0, 1,
                               GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 2);

      /* decay */
      label = gtk_label_new("Decay");
      gtk_widget_show(label);
      gtk_table_attach(GTK_TABLE(envelope_table), label,
                               0, 1, 1, 2, GTK_FILL, GTK_FILL, 4, 0);

      decay_range =
            gtk_hscale_new_with_range(0.0, ENVELOPE_UPPER, ENVELOPE_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(decay_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(decay_range), 5);
      gtk_range_set_value(GTK_RANGE(decay_range), decay);
      g_signal_connect(G_OBJECT(decay_range), "value-changed",
                               G_CALLBACK(range_cb), &decay);
      gtk_widget_show(decay_range);
      gtk_table_attach(GTK_TABLE(envelope_table), decay_range,
                               1, 2, 1, 2,
                               GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 2);

      /* sustain */
      label = gtk_label_new("Sustain");
      gtk_widget_show(label);
      gtk_table_attach(GTK_TABLE(envelope_table), label,
                               0, 1, 2, 3, GTK_FILL, GTK_FILL, 4, 0);

      sustain_range =
            gtk_hscale_new_with_range(0.0, ENVELOPE_UPPER, ENVELOPE_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(sustain_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(sustain_range), 5);
      gtk_range_set_value(GTK_RANGE(sustain_range), sustain);
      g_signal_connect(G_OBJECT(sustain_range), "value-changed",
                               G_CALLBACK(range_cb), &sustain);
      gtk_widget_show(sustain_range);
      gtk_table_attach(GTK_TABLE(envelope_table), sustain_range,
                               1, 2, 2, 3,
                               GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 2);

      /* release */
      label = gtk_label_new("Release");
      gtk_widget_show(label);
      gtk_table_attach(GTK_TABLE(envelope_table), label,
                               0, 1, 3, 4, GTK_FILL, GTK_FILL, 4, 0);

      release_range =
            gtk_hscale_new_with_range(0.0, ENVELOPE_UPPER, ENVELOPE_UPPER / 1000);
      gtk_scale_set_value_pos(GTK_SCALE(release_range), GTK_POS_RIGHT);
      gtk_scale_set_digits(GTK_SCALE(release_range), 5);
      gtk_range_set_value(GTK_RANGE(release_range), release);
      g_signal_connect(G_OBJECT(release_range), "value-changed",
                               G_CALLBACK(range_cb), &release);
      gtk_widget_show(release_range);
      gtk_table_attach(GTK_TABLE(envelope_table), release_range,
                               1, 2, 3, 4,
                               GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 1, 2);

      gtk_widget_show(window);

      gtk_idle_add(idle_cb, NULL);

      printf("Interface running\n");
      interface_up = 1;
      gtk_main();

      printf("Interface finished\n");
      return NULL;
}

#endif /* HAVE_GTK2 */

Generated by  Doxygen 1.6.0   Back to index