1 /* Copyright 2009-2010 Yorba Foundation
3 * This software is licensed under the GNU Lesser General Public License
4 * (version 2.1 or later). See the COPYING file in this distribution.
9 class TrackHeader : Gtk.EventBox {
10 protected weak Model.Track track;
11 protected weak HeaderArea header_area;
12 protected Gtk.Label track_label;
14 public const int width = 100;
16 public TrackHeader(Model.Track track, HeaderArea area, int height) {
18 this.header_area = area;
20 track.track_renamed.connect(on_track_renamed);
21 track.track_selection_changed.connect(on_track_selection_changed);
22 set_size_request(width, height);
23 modify_bg(Gtk.StateType.NORMAL, header_area.background_color);
24 modify_bg(Gtk.StateType.SELECTED, parse_color("#68a"));
26 track_label = new Gtk.Label(track.display_name);
27 track_label.modify_fg(Gtk.StateType.NORMAL, parse_color("#fff"));
30 void on_track_renamed() {
31 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_renamed");
32 track_label.set_text(track.display_name);
35 void on_track_selection_changed(Model.Track track) {
36 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_track_selection_changed");
37 set_state(track.get_is_selected() ? Gtk.StateType.SELECTED : Gtk.StateType.NORMAL);
40 public override bool button_press_event(Gdk.EventButton event) {
41 header_area.select(track);
45 public Model.Track get_track() {
50 public class SliderBase : Gtk.HScrollbar {
51 Gdk.Pixbuf slider_image;
55 slider_image = new Gdk.Pixbuf.from_file(
56 AppDirs.get_resources_dir().get_child("dot.png").get_path());
57 } catch (GLib.Error e) {
58 warning("Could not load resource for slider: %s", e.message);
62 public override bool expose_event (Gdk.EventExpose event) {
63 Gdk.GC gc = style.fg_gc[(int) Gtk.StateType.NORMAL];
64 int radius = (slider_end - slider_start) / 2;
65 int center = allocation.x + slider_start + radius;
66 int height = allocation.y + allocation.height / 2;
68 event.window.draw_rectangle(gc, false,
69 allocation.x + radius, height - 2, allocation.width - 2 * radius, 1);
71 event.window.draw_pixbuf(gc, slider_image, 0, 0, center - radius, allocation.y + 2,
72 slider_image.get_width(), slider_image.get_height(), Gdk.RgbDither.NORMAL, 0, 0);
77 class PanSlider : SliderBase {
82 public class VolumeSlider : SliderBase {
87 class AudioTrackHeader : TrackHeader {
88 public double panorama;
91 public AudioTrackHeader(Model.AudioTrack track, HeaderArea header, int height) {
92 base(track, header, height);
94 track_label.modify_font(Pango.FontDescription.from_string("Sans 10"));
95 track_label.set_padding(4, 2);
96 track_label.set_alignment(0,0);
98 track.parameter_changed.connect(on_parameter_changed);
100 volume = track.get_volume();
101 panorama = track.get_pan();
103 Gtk.VBox vbox = new Gtk.VBox(false, 0);
104 vbox.pack_start(track_label, true, true, 0);
105 Hildon.Button volpan_button = new Hildon.Button(Hildon.SizeType.AUTO_HEIGHT | Hildon.SizeType.AUTO_WIDTH, Hildon.ButtonArrangement.HORIZONTAL);
106 //volpan_button.set_text("Vol", "");
107 volpan_button.set_image(new Gtk.Image.from_icon_name("statusarea_volumelevel4", Gtk.IconSize.BUTTON));
108 volpan_button.set_image_position(Gtk.PositionType.LEFT);
109 volpan_button.clicked.connect(do_volpan_popup);
110 vbox.add(volpan_button);
112 //View.AudioMeter meter = new View.AudioMeter(track);
114 //vbox.add(volume_box);
119 void do_volpan_popup() {
120 IdWorks.VolumeAndPanPopUp dlg = new IdWorks.VolumeAndPanPopUp(this, "Volume / Pan: " + track.display_name);
121 //dlg.set_transient_for(this.get_transient_for());
122 dlg.set_volume(this.volume);
123 dlg.set_panorama(this.panorama);
124 dlg.volume_updated.connect(on_volume_updated);
125 dlg.panorama_updated.connect(on_panorama_updated);
131 void on_panorama_updated(double val) {
132 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed");
133 Model.AudioTrack audio_track = track as Model.AudioTrack;
134 if (audio_track != null) {
135 audio_track.set_pan(val);
139 /*void on_pan_value_changed() {
140 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_pan_value_changed");
141 Model.AudioTrack audio_track = track as Model.AudioTrack;
142 if (audio_track != null) {
143 Gtk.Adjustment adjustment = pan.get_adjustment();
144 audio_track.set_pan(adjustment.get_value());
148 void on_volume_updated(double val) {
149 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed");
150 Model.AudioTrack audio_track = track as Model.AudioTrack;
151 if (audio_track != null) {
152 audio_track.set_volume(val);
156 /*void on_volume_value_changed() {
157 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_volume_value_changed");
158 Model.AudioTrack audio_track = track as Model.AudioTrack;
159 if (audio_track != null) {
160 Gtk.Adjustment adjustment = volume.get_adjustment();
161 audio_track.set_volume(adjustment.get_value());
164 void on_parameter_changed(Model.Parameter parameter, double new_value) {
165 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed");
166 Model.AudioTrack audio_track = track as Model.AudioTrack;
167 assert(audio_track != null);
169 case Model.Parameter.VOLUME:
172 case Model.Parameter.PAN:
173 panorama = new_value;
177 /* void on_parameter_changed(Model.Parameter parameter, double new_value) {
178 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_parameter_changed");
179 Model.AudioTrack audio_track = track as Model.AudioTrack;
180 assert(audio_track != null);
182 case Model.Parameter.VOLUME:
183 volume.set_value(new_value);
185 case Model.Parameter.PAN:
186 pan.set_value(new_value);
192 class HeaderArea : Gtk.EventBox {
193 weak Model.Project project;
196 public Gdk.Color background_color = parse_color("#666");
198 public HeaderArea(Recorder recorder, Model.TimeSystem provider, int height) {
199 this.project = recorder.project;
200 recorder.timeline.trackview_removed.connect(on_trackview_removed);
201 recorder.timeline.trackview_added.connect(on_trackview_added);
203 set_size_request(TrackHeader.width, 0);
204 modify_bg(Gtk.StateType.NORMAL, background_color);
206 vbox = new Gtk.VBox(false, 0);
208 Gtk.DrawingArea status_bar = new View.StatusBar(project, provider, height);
210 vbox.pack_start(status_bar, false, false, 0);
212 vbox.pack_start(new TrackSeparator(), false, false, 0);
214 foreach (TrackView track in recorder.timeline.tracks) {
215 on_trackview_added(track);
219 public void on_trackview_added(TrackView trackview) {
220 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_added");
221 Model.AudioTrack audio_track = trackview.get_track() as Model.AudioTrack;
222 assert(audio_track != null);
223 //we are currently only supporting audio tracks. We'll probably have
224 //a separate method for adding video track, midi track, aux input, etc
226 TrackHeader header = new AudioTrackHeader(audio_track, this, trackview.get_track_height());
227 vbox.pack_start(header, false, false, 0);
228 vbox.pack_start(new TrackSeparator(), false, false, 0);
233 public void on_trackview_removed(TrackView trackview) {
234 emit(this, Facility.SIGNAL_HANDLERS, Level.INFO, "on_trackview_removed");
235 Model.Track track = trackview.get_track();
236 TrackHeader? my_track_header = null;
237 Gtk.HSeparator? my_separator = null;
238 foreach(Gtk.Widget widget in vbox.get_children()) {
239 if (my_track_header == null) {
240 TrackHeader? track_header = widget as TrackHeader;
241 if (track_header != null && track_header.get_track() == track) {
242 my_track_header = track_header;
245 my_separator = widget as Gtk.HSeparator;
250 if (my_track_header != null) {
251 vbox.remove(my_track_header);
254 if (my_separator != null) {
255 vbox.remove(my_separator);
258 if (project.tracks.size != 0) {
259 select(project.tracks[0]);
263 public void select(Model.Track track) {
264 foreach (Model.Track t in project.tracks)
265 t.set_selected(t == track);