Remove some debug output.
[gmpc.git] / src / vala / gmpc-favorites.vala
blobaf19d5fdfaa67d5be700cf60c9b4e040d4d06c42
2 /* Gnome Music Player Client (GMPC)
3 * Copyright (C) 2004-2011 Qball Cow <qball@gmpclient.org>
4 * Project homepage: http://gmpclient.org/
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 using Config;
21 using GLib;
22 using Gtk;
23 using Gdk;
24 using MPD;
26 /* trick to get config.h included */
27 static const string some_unique_name_fav = Config.VERSION;
28 private const bool use_transition_fav = Gmpc.use_transition;
29 static Gmpc.Favorites.List favorites = null;
31 namespace Gmpc.Favorites{
32 /**
33 * This class is created, and stays active until the last GmpcFavoritesButton gets removed
35 private class List : GLib.Object {
36 private MPD.Data.Item? list = null;
37 construct {
38 gmpcconn.connection_changed.connect(con_changed);
39 gmpcconn.status_changed.connect(status_changed);
42 /**
43 * If disconnected from mpd, clear the list.
44 * On connect fill
46 private
47 void
48 con_changed(Gmpc.Connection conn, MPD.Server server, int connect)
50 if(connect == 1){
51 list = MPD.Database.get_playlist_content(server, _("Favorites"));
52 this.updated();
53 }else{
54 list = null;
57 /**
58 * If playlist changed update the list
60 private
61 void
62 status_changed(Gmpc.Connection conn, MPD.Server server, MPD.Status.Changed what)
64 if((what&MPD.Status.Changed.STORED_PLAYLIST) == MPD.Status.Changed.STORED_PLAYLIST)
66 list = MPD.Database.get_playlist_content(server, _("Favorites"));
67 this.updated();
70 /****************************************************************************************
71 * "Public" api.
72 ****************************************************************************************/
73 /**
74 * Signal for the widget using the list to see if it needs to recheck status
76 public signal void updated();
78 /**
79 * Check if the song (specified by path) is favored
81 public
82 bool
83 is_favorite(string path)
85 unowned MPD.Data.Item iter = this.list.get_first();
86 while(iter != null)
88 if(iter.type == MPD.Data.Type.SONG)
90 if(iter.song.file == path){
91 return true;
94 iter.next(false);
96 return false;
98 /**
99 * Favor, or unfavor a song
101 public
102 void
103 set_favorite(string path, bool favorite)
105 bool current = this.is_favorite(path);
106 /* Do nothing if state does not change */
107 if(current != favorite)
109 if(favorite){
110 /* Add it */
111 MPD.Database.playlist_list_add(server, _("Favorites"), path);
112 }else{
113 /* Remove it */
114 /* To be able to remove it we have to first lookup the position */
115 /* This needs libmpd 0.18.1 */
116 unowned MPD.Data.Item iter = this.list.get_first();
117 while(iter != null)
119 if(iter.type == MPD.Data.Type.SONG)
121 if(iter.song.file == path){
122 MPD.Database.playlist_list_delete(server, _("Favorites"), iter.song.pos);
123 return;
126 iter.next(false);
133 * The actual favorite button
135 public class Button : Gtk.EventBox {
136 /* the song the button show show the state for */
137 private MPD.Song? song;
138 /* The image displaying the state */
139 private Gtk.Image image;
140 /* The current state */
141 private bool fstate = false;
142 /* The pixbuf holding the unmodified image */
143 private Gdk.Pixbuf pb = null;
146 * Creation of the object
148 construct {
149 this.no_show_all = true;
150 this.visible_window = false;
151 var it = Gtk.IconTheme.get_default();
152 try {
153 pb = it.load_icon("emblem-favorite",24, 0);
154 }catch(Error e) {
155 GLib.error("error: %s\n", e.message);
157 if(favorites == null){
158 favorites = new List();
159 /* make sure favorites is set to NULL again when destroyed */
160 favorites.add_weak_pointer(&favorites);
161 } else {
162 favorites.ref();
164 favorites.updated.connect(update);
165 this.image = new Gtk.Image();
166 this.update(favorites);
167 this.add(this.image);
168 this.button_press_event.connect(button_press_event_callback);
169 this.enter_notify_event.connect(enter_notify_event_callback);
170 this.leave_notify_event.connect(leave_notify_event_callback);
173 ~Button() {
174 if(favorites != null)
175 favorites.unref();
177 private
178 bool
179 button_press_event_callback(Gtk.Widget button,Gdk.EventButton event)
181 if(event.button == 1 && this.song != null) {
182 favorites.set_favorite(this.song.file, !this.fstate);
183 this.fstate = !this.fstate;
185 else if (event.button == 3 && this.song != null) {
186 var menu = new Gtk.Menu();
187 int items = 0;
188 MPD.Data.Item ? item = MPD.Database.get_playlist_list(server);
189 while(item != null)
191 string pp = item.playlist.path;
192 var entry = new Gtk.ImageMenuItem.with_label(pp);
193 if(pp == _("Favorites")) {
194 entry.set_image(new Gtk.Image.from_icon_name("emblem-favorite", Gtk.IconSize.MENU));
195 }else{
196 entry.set_image(new Gtk.Image.from_icon_name("media-playlist", Gtk.IconSize.MENU));
198 entry.activate.connect((source) => {
199 MPD.Database.playlist_list_add(server,pp, this.song.file);
201 menu.append(entry);
202 item.next_free();
203 items++;
205 if(items > 0)
207 menu.show_all();
208 menu.popup(null, null, null, event.button, event.time);
210 else menu.destroy();
211 return true;
213 return false;
216 /* on mouse over, do some pre-highlighting */
217 private
218 bool
219 enter_notify_event_callback(Gtk.Widget button, Gdk.EventCrossing motion)
221 var pb2 = pb.copy();
222 if(this.fstate){
223 Gmpc.Misc.colorshift_pixbuf(pb2, pb, 10);
224 }else{
225 Gmpc.Misc.colorshift_pixbuf(pb2, pb,-50);
227 this.image.set_from_pixbuf(pb2);
228 return false;
230 /* Reset default highlighting */
231 private
232 bool
233 leave_notify_event_callback(Gtk.Widget button, Gdk.EventCrossing motion)
235 this.update(favorites);
236 return false;
238 /* Update the icon according to state */
239 private
240 void
241 update(Gmpc.Favorites.List list)
243 if(this.song != null){
244 this.fstate = favorites.is_favorite(this.song.file);
245 }else{
246 /* Hide the widget and do nothing */
247 this.hide();
248 return;
250 /* Copy the pixbuf */
251 var pb2 = pb.copy();
252 /* Depending on the state colorshift the pixbuf */
253 if(this.fstate) {
254 Gmpc.Misc.colorshift_pixbuf(pb2, pb, 30);
255 }else{
256 Gmpc.Misc.colorshift_pixbuf(pb2, pb, -80);
258 this.image.set_from_pixbuf(pb2);
259 this.image.show();
260 this.show();
262 /**********************************************************************
263 * Public api
264 *********************************************************************/
265 /* Set the song the button should watch. or NULL to watch non */
266 public
267 void
268 set_song(MPD.Song? song)
270 if(this.song == null && song == null ) return;
271 if(this.song != null && song != null && this.song.file == song.file) return;
272 this.song = song;
273 this.update(favorites);