/* Copyright 2009-2010 Yorba Foundation * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. */ using Logging; class TrackHeader : Gtk.EventBox { protected weak Model.Track track; protected weak HeaderArea header_area; protected Gtk.Label track_label; public const int width = 100; public TrackHeader(Model.Track track, HeaderArea area, int height) { this.track = track; this.header_area = area; track.track_renamed.connect(on_track_renamed); track.track_selection_changed.connect(on_track_selection_changed); set_size_request(width, height); modify_bg(Gtk.StateType.NORMAL, header_area.background_color); modify_bg(Gtk.StateType.SELECTED, parse_color("#68a")); track_label = new Gtk.Label(track.display_name); track_label.modify_fg(Gtk.StateType.NORMAL, parse_color("#fff")); } void on_track_renamed() { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_renamed"); track_label.set_text(track.display_name); } void on_track_selection_changed(Model.Track track) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_selection_changed"); set_state(track.get_is_selected() ? Gtk.StateType.SELECTED : Gtk.StateType.NORMAL); } public override bool button_press_event(Gdk.EventButton event) { header_area.select(track); return true; } public Model.Track get_track() { return track; } } public class SliderBase : Gtk.HScrollbar { Gdk.Pixbuf slider_image; construct { can_focus = true; try { slider_image = new Gdk.Pixbuf.from_file( AppDirs.get_resources_dir().get_child("dot.png").get_path()); } catch (GLib.Error e) { warning("Could not load resource for slider: %s", e.message); } } public override bool expose_event (Gdk.EventExpose event) { Gdk.GC gc = style.fg_gc[(int) Gtk.StateType.NORMAL]; int radius = (slider_end - slider_start) / 2; int center = allocation.x + slider_start + radius; int height = allocation.y + allocation.height / 2; event.window.draw_rectangle(gc, false, allocation.x + radius, height - 2, allocation.width - 2 * radius, 1); event.window.draw_pixbuf(gc, slider_image, 0, 0, center - radius, allocation.y + 2, slider_image.get_width(), slider_image.get_height(), Gdk.RgbDither.NORMAL, 0, 0); return true; } } class PanSlider : SliderBase { construct { } } public class VolumeSlider : SliderBase { construct { } } class AudioTrackHeader : TrackHeader { public double panorama; public double volume; public AudioTrackHeader(Model.AudioTrack track, HeaderArea header, int height) { base(track, header, height); track_label.modify_font(Pango.FontDescription.from_string("Sans 10")); track_label.set_padding(4, 2); track_label.set_alignment(0,0); track.parameter_changed.connect(on_parameter_changed); volume = track.get_volume(); panorama = track.get_pan(); Gtk.VBox vbox = new Gtk.VBox(false, 0); vbox.pack_start(track_label, true, true, 0); Hildon.Button volpan_button = new Hildon.Button(Hildon.SizeType.AUTO_HEIGHT | Hildon.SizeType.AUTO_WIDTH, Hildon.ButtonArrangement.HORIZONTAL); //volpan_button.set_text("Vol", ""); volpan_button.set_image(new Gtk.Image.from_icon_name("statusarea_volumelevel4", Gtk.IconSize.BUTTON)); volpan_button.set_image_position(Gtk.PositionType.LEFT); volpan_button.clicked.connect(do_volpan_popup); vbox.add(volpan_button); //View.AudioMeter meter = new View.AudioMeter(track); //vbox.add(meter); //vbox.add(volume_box); //vbox.add(pan_box); add(vbox); } void do_volpan_popup() { IdWorks.VolumeAndPanPopUp dlg = new IdWorks.VolumeAndPanPopUp(this, "Volume / Pan: " + track.display_name); //dlg.set_transient_for(this.get_transient_for()); dlg.set_volume(this.volume); dlg.set_panorama(this.panorama); dlg.volume_updated.connect(on_volume_updated); dlg.panorama_updated.connect(on_panorama_updated); dlg.run(); dlg.destroy(); dlg = null; } void on_panorama_updated(double val) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; if (audio_track != null) { audio_track.set_pan(val); } } /*void on_pan_value_changed() { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; if (audio_track != null) { Gtk.Adjustment adjustment = pan.get_adjustment(); audio_track.set_pan(adjustment.get_value()); } }*/ void on_volume_updated(double val) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; if (audio_track != null) { audio_track.set_volume(val); } } /*void on_volume_value_changed() { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; if (audio_track != null) { Gtk.Adjustment adjustment = volume.get_adjustment(); audio_track.set_volume(adjustment.get_value()); } }*/ void on_parameter_changed(Model.Parameter parameter, double new_value) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; assert(audio_track != null); switch(parameter) { case Model.Parameter.VOLUME: volume = new_value; break; case Model.Parameter.PAN: panorama = new_value; break; } } /* void on_parameter_changed(Model.Parameter parameter, double new_value) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed"); Model.AudioTrack audio_track = track as Model.AudioTrack; assert(audio_track != null); switch(parameter) { case Model.Parameter.VOLUME: volume.set_value(new_value); break; case Model.Parameter.PAN: pan.set_value(new_value); break; } }*/ } class HeaderArea : Gtk.EventBox { weak Model.Project project; Gtk.VBox vbox; public Gdk.Color background_color = parse_color("#666"); public HeaderArea(Recorder recorder, Model.TimeSystem provider, int height) { this.project = recorder.project; recorder.timeline.trackview_removed.connect(on_trackview_removed); recorder.timeline.trackview_added.connect(on_trackview_added); set_size_request(TrackHeader.width, 0); modify_bg(Gtk.StateType.NORMAL, background_color); vbox = new Gtk.VBox(false, 0); add(vbox); Gtk.DrawingArea status_bar = new View.StatusBar(project, provider, height); vbox.pack_start(status_bar, false, false, 0); vbox.pack_start(new TrackSeparator(), false, false, 0); foreach (TrackView track in recorder.timeline.tracks) { on_trackview_added(track); } } public void on_trackview_added(TrackView trackview) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_added"); Model.AudioTrack audio_track = trackview.get_track() as Model.AudioTrack; assert(audio_track != null); //we are currently only supporting audio tracks. We'll probably have //a separate method for adding video track, midi track, aux input, etc TrackHeader header = new AudioTrackHeader(audio_track, this, trackview.get_track_height()); vbox.pack_start(header, false, false, 0); vbox.pack_start(new TrackSeparator(), false, false, 0); vbox.show_all(); select(audio_track); } public void on_trackview_removed(TrackView trackview) { emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_removed"); Model.Track track = trackview.get_track(); TrackHeader? my_track_header = null; Gtk.HSeparator? my_separator = null; foreach(Gtk.Widget widget in vbox.get_children()) { if (my_track_header == null) { TrackHeader? track_header = widget as TrackHeader; if (track_header != null && track_header.get_track() == track) { my_track_header = track_header; } } else { my_separator = widget as Gtk.HSeparator; break; } } if (my_track_header != null) { vbox.remove(my_track_header); } if (my_separator != null) { vbox.remove(my_separator); } if (project.tracks.size != 0) { select(project.tracks[0]); } } public void select(Model.Track track) { foreach (Model.Track t in project.tracks) t.set_selected(t == track); } }