Merge lp:~davidgomes/noise/code-style-fix into lp:~elementary-apps/noise/trunk

Proposed by David Gomes
Status: Merged
Approved by: Victor Martinez
Approved revision: 1063
Merged at revision: 1071
Proposed branch: lp:~davidgomes/noise/code-style-fix
Merge into: lp:~elementary-apps/noise/trunk
Diff against target: 629 lines (+282/-286)
1 file modified
src/GStreamer/GStreamerTagger.vala (+282/-286)
To merge this branch: bzr merge lp:~davidgomes/noise/code-style-fix
Reviewer Review Type Date Requested Status
Victor Martinez (community) Approve
Review via email: mp+128361@code.launchpad.net

Description of the change

Fixed lots of awful code.

To post a comment you must log in.
lp:~davidgomes/noise/code-style-fix updated
1063. By David Gomes

More fixes.

Revision history for this message
David Gomes (davidgomes) wrote :

Also, I think all that commented code in the end should be removed, it just looks bad.

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

might be better to use a namespace like

namespace Noise {

    public class GStreamerTagger : GLib.Object {

    ...

    }

}

Revision history for this message
Victor Martinez (victored) wrote :

Thanks for your work David.

I'm not a big fan of Noise's code, and I don't particularly like how all these classes (LibraryManager.vala, FileOperator.vala, GStreamerTagger.vala) were put together in the first place, and because of that I started a rewrite some months ago but put in on hold as it would be impossible to finish it on time for Luna: http://bazaar.launchpad.net/~victored/noise/core-refactor/files/head:/core/GStreamer/Metadata/

Essentially, the problem here is that Noise lacks modularity and doesn't make full use of polymorphism and data hiding (among other problems, like code duplication, etc.) Modifying a single public variable in one class leads you to rewrite a bunch of other classes you'd never imagined were tied together by a public field.

That's why I told you on IRC that a code cleanup might not be worth it. All this will be rewritten after Luna, and that rewrite already started. This class in particular has been already rewritten in the files linked above.

review: Approve
Revision history for this message
Victor Martinez (victored) wrote :

Rico, you bring up an interesting suggestion there. Personally, I'm finding it hard to decide whether I prefer a visually encapsulating namespace ("namespace Noise { ... }") style over simply connecting the dots ("Noise.ClassName")

I think David has the final say on that topic, since it's currently not defined in the current coding style guidelines.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/GStreamer/GStreamerTagger.vala'
2--- src/GStreamer/GStreamerTagger.vala 2012-10-06 03:06:08 +0000
3+++ src/GStreamer/GStreamerTagger.vala 2012-10-06 18:22:21 +0000
4@@ -25,149 +25,147 @@
5
6 public class Noise.GStreamerTagger : GLib.Object {
7
8- LibraryManager lm;
9- static int DISCOVER_SET_SIZE = 50;
10- Gst.Discoverer d;
11- HashMap<string, int> uri_to_id;
12- LinkedList<string> path_queue;
13-
14- public signal void media_imported(Media m);
15- public signal void import_error(string file);
16- public signal void queue_finished();
17-
18- bool cancelled;
19-
20- public GStreamerTagger(LibraryManager lm) {
21- this.lm = lm;
22+ LibraryManager lm;
23+ static int DISCOVER_SET_SIZE = 50;
24+ Gst.Discoverer d;
25+ HashMap<string, int> uri_to_id;
26+ LinkedList<string> path_queue;
27+
28+ public signal void media_imported (Media m);
29+ public signal void import_error (string file);
30+ public signal void queue_finished();
31+
32+ bool cancelled;
33+
34+ public GStreamerTagger (LibraryManager library_manager) {
35+ this.lm = library_manager;
36
37 d = create_discoverer ();
38
39-
40- uri_to_id = new HashMap<string, int>();
41- path_queue = new LinkedList<string>();
42- }
43+ uri_to_id = new HashMap<string, int> ();
44+ path_queue = new LinkedList<string> ();
45+ }
46
47 private Gst.Discoverer? create_discoverer () {
48 Gst.Discoverer? discoverer = null;
49
50- try {
51- discoverer = new Gst.Discoverer ((ClockTime)(30*Gst.SECOND));
52- }
53- catch (Error err) {
54- critical ("Metadata reader could not create discoverer object: %s\n", err.message);
55- }
56+ try {
57+ discoverer = new Gst.Discoverer ((ClockTime) (30 * Gst.SECOND));
58+ } catch (Error err) {
59+ critical ("Metadata reader could not create discoverer object: %s\n", err.message);
60+ }
61
62- discoverer.discovered.connect (import_media);
63- discoverer.finished.connect (finished);
64+ discoverer.discovered.connect (import_media);
65+ discoverer.finished.connect (finished);
66
67 return discoverer;
68 }
69
70- void finished() {
71- if(!cancelled && path_queue.size > 0) {
72- d = create_discoverer ();
73-
74- d.start();
75- for(int i = 0; i < DISCOVER_SET_SIZE && i < path_queue.size; ++i) {
76- d.discover_uri_async("file://" + path_queue.get(i));
77- }
78- }
79- else {
80- debug("queue finished\n");
81- queue_finished();
82- }
83- }
84-
85- public void cancel_operations() {
86- cancelled = true;
87- }
88-
89- public void discoverer_import_media (LinkedList<string> files) {
90- int size = 0;
91- cancelled = false;
92- path_queue.clear();
93-
94- foreach(string s in files) {
95- path_queue.add(s);
96-
97- d.start();
98- if(size < DISCOVER_SET_SIZE) {
99- ++size;
100- d.discover_uri_async("file://" + s);
101- }
102- }
103- }
104-
105- private async void import_media(DiscovererInfo info, Error err) {
106- path_queue.remove(info.get_uri().replace("file://",""));
107+ void finished () {
108+ if (!cancelled && path_queue.size > 0) {
109+ d = create_discoverer ();
110+
111+ d.start ();
112+ for (int i = 0; i < DISCOVER_SET_SIZE && i < path_queue.size; ++i) {
113+ d.discover_uri_async ("file://" + path_queue.get (i));
114+ }
115+ } else {
116+ debug ("queue finished\n");
117+ queue_finished ();
118+ }
119+ }
120+
121+ public void cancel_operations () {
122+ cancelled = true;
123+ }
124+
125+ public void discoverer_import_media (LinkedList<string> files) {
126+ int size = 0;
127+ cancelled = false;
128+ path_queue.clear ();
129+
130+ foreach (string s in files) {
131+ path_queue.add (s);
132+
133+ d.start ();
134+ if (size < DISCOVER_SET_SIZE) {
135+ ++size;
136+ d.discover_uri_async ("file://" + s);
137+ }
138+ }
139+ }
140+
141+ private async void import_media (DiscovererInfo info, Error err) {
142+ path_queue.remove (info.get_uri ().replace ("file://", ""));
143
144 Media? s = null;
145
146- if(info != null && info.get_tags() != null) {
147- s = new Media(info.get_uri());
148-
149- string title = "";
150- string artist, composer, album_artist, album, grouping, genre, comment, lyrics;
151- uint track, track_count, album_number, album_count, bitrate, rating;
152- double bpm;
153- GLib.Date? date = GLib.Date();
154-
155- // get title, artist, album artist, album, genre, comment, lyrics strings
156- if(info.get_tags().get_string(TAG_TITLE, out title))
157- s.title = title;
158- if(info.get_tags().get_string(TAG_ARTIST, out artist))
159- s.artist = artist;
160- if(info.get_tags().get_string(TAG_COMPOSER, out composer))
161- s.composer = composer;
162-
163- if(info.get_tags().get_string(TAG_ALBUM_ARTIST, out album_artist))
164- s.album_artist = album_artist;
165- else
166- s.album_artist = s.artist;
167-
168- if(info.get_tags().get_string(TAG_ALBUM, out album))
169- s.album = album;
170- if(info.get_tags().get_string(TAG_GROUPING, out grouping))
171- s.grouping = grouping;
172- if(info.get_tags().get_string(TAG_GENRE, out genre))
173- s.genre = genre;
174- if(info.get_tags().get_string(TAG_COMMENT, out comment))
175- s.comment = comment;
176- if(info.get_tags().get_string(TAG_LYRICS, out lyrics))
177- s.lyrics = lyrics;
178-
179- // get the year
180- if(info.get_tags().get_date(TAG_DATE, out date)) {
181- if(date != null)
182- s.year = (int)date.get_year();
183- }
184- // get track/album number/count, bitrating, rating, bpm
185- if(info.get_tags().get_uint(TAG_TRACK_NUMBER, out track))
186- s.track = (int)track;
187- if(info.get_tags().get_uint(TAG_TRACK_COUNT, out track_count))
188- s.track_count = track_count;
189-
190- if(info.get_tags().get_uint(TAG_ALBUM_VOLUME_NUMBER, out album_number))
191- s.album_number = album_number;
192- if(info.get_tags().get_uint(TAG_ALBUM_VOLUME_COUNT, out album_count))
193- s.album_count = album_count;
194-
195- if(info.get_tags().get_uint(TAG_BITRATE, out bitrate))
196- s.bitrate = (int)(bitrate/1000);
197- if(info.get_tags().get_uint(TAG_USER_RATING, out rating))
198- s.rating = (int)((rating > 0 && rating <= 5) ? rating : 0);
199- if(info.get_tags().get_double(TAG_BEATS_PER_MINUTE, out bpm))
200- s.bpm = (int)bpm;
201-
202-
203- // get length
204+ if (info != null && info.get_tags () != null) {
205+ s = new Media (info.get_uri ());
206+
207+ string title = "";
208+ string artist, composer, album_artist, album, grouping, genre, comment, lyrics;
209+ uint track, track_count, album_number, album_count, bitrate, rating;
210+ double bpm;
211+ GLib.Date? date = GLib.Date ();
212+
213+ // get title, artist, album artist, album, genre, comment, lyrics strings
214+ if (info.get_tags ().get_string (TAG_TITLE, out title))
215+ s.title = title;
216+ if (info.get_tags ().get_string (TAG_ARTIST, out artist))
217+ s.artist = artist;
218+ if (info.get_tags ().get_string (TAG_COMPOSER, out composer))
219+ s.composer = composer;
220+
221+ if (info.get_tags ().get_string (TAG_ALBUM_ARTIST, out album_artist))
222+ s.album_artist = album_artist;
223+ else
224+ s.album_artist = s.artist;
225+
226+ if (info.get_tags ().get_string (TAG_ALBUM, out album))
227+ s.album = album;
228+ if (info.get_tags ().get_string (TAG_GROUPING, out grouping))
229+ s.grouping = grouping;
230+ if (info.get_tags ().get_string (TAG_GENRE, out genre))
231+ s.genre = genre;
232+ if (info.get_tags ().get_string (TAG_COMMENT, out comment))
233+ s.comment = comment;
234+ if (info.get_tags ().get_string (TAG_LYRICS, out lyrics))
235+ s.lyrics = lyrics;
236+
237+ /* Get the year */
238+ if (info.get_tags ().get_date (TAG_DATE, out date)) {
239+ if (date != null)
240+ s.year = (int) date.get_year ();
241+ }
242+
243+ /* get track/album number/count, bitrating, rating, bpm */
244+ if (info.get_tags ().get_uint (TAG_TRACK_NUMBER, out track))
245+ s.track = (int)track;
246+ if (info.get_tags ().get_uint (TAG_TRACK_COUNT, out track_count))
247+ s.track_count = track_count;
248+
249+ if (info.get_tags ().get_uint (TAG_ALBUM_VOLUME_NUMBER, out album_number))
250+ s.album_number = album_number;
251+ if (info.get_tags ().get_uint (TAG_ALBUM_VOLUME_COUNT, out album_count))
252+ s.album_count = album_count;
253+
254+ if (info.get_tags ().get_uint (TAG_BITRATE, out bitrate))
255+ s.bitrate = (int) (bitrate / 1000);
256+ if (info.get_tags ().get_uint (TAG_USER_RATING, out rating))
257+ s.rating = (int) ((rating > 0 && rating <= 5) ? rating : 0);
258+ if (info.get_tags ().get_double (TAG_BEATS_PER_MINUTE, out bpm))
259+ s.bpm = (int) bpm;
260+
261+
262+ /* Get length */
263 uint64 duration = info.get_duration ();
264
265 if (duration == 0)
266- info.get_tags ().get_uint64 (TAG_DURATION, out duration);
267+ info.get_tags ().get_uint64 (TAG_DURATION, out duration);
268
269- // we convert from nanoseconds (10E-9) to miliseconds (10E-3);
270- s.length = (uint)((duration * Numeric.MILI_INV) / Numeric.NANO_INV);
271+ /* Convert from nanoseconds (10E-9) to miliseconds (10E-3) */
272+ s.length = (uint) ((duration * Numeric.MILI_INV) / Numeric.NANO_INV);
273
274 foreach (var audio_stream in info.get_audio_streams ()) {
275 if (audio_stream == null)
276@@ -182,70 +180,68 @@
277 if (s.bitrate == 0) {
278 debug ("Getting bitrate from stream info");
279 s.bitrate = audio_stream.get_bitrate ();
280- debug ("Bitrate = %s", s.bitrate.to_string());
281+ debug ("Bitrate = %s", s.bitrate.to_string ());
282 }
283
284 break;
285 }
286
287- // Get cover art
288- import_art_async.begin (s, info);
289- }
290- else {
291- s = taglib_import_media(info.get_uri());
292-
293- if (s == null) {
294- import_error (info.get_uri().replace("file://", ""));
295- return;
296- }
297- }
298-
299- // get the size
300- s.file_size = yield FileUtils.get_size_async (s.file);
301- s.date_added = (int)time_t();
302-
303- media_imported(s);
304- }
305-
306- public Media? taglib_import_media(string uri) {
307- Media s = new Media(uri);
308- TagLib.File tag_file;
309-
310- tag_file = new TagLib.File(uri.replace("file://",""));
311-
312- if(tag_file != null && tag_file.tag != null && tag_file.audioproperties != null) {
313- try {
314- s.title = tag_file.tag.title;
315- s.artist = tag_file.tag.artist;
316- s.album = tag_file.tag.album;
317- s.genre = tag_file.tag.genre;
318- s.comment = tag_file.tag.comment;
319- s.year = (int)tag_file.tag.year;
320- s.track = (int)tag_file.tag.track;
321- s.bitrate = tag_file.audioproperties.bitrate;
322-
323- s.length = (uint)(tag_file.audioproperties.length * Numeric.MILI_INV);
324- s.samplerate = tag_file.audioproperties.samplerate;
325- }
326- finally {
327- if(s.title == null || s.title == "") {
328- string[] paths = uri.split("/", 0);
329- s.title = paths[paths.length - 1];
330- }
331- if(s.artist == null || s.artist == "") s.artist = Media.UNKNOWN_ARTIST;
332-
333- s.album_artist = s.artist;
334- s.album_number = 1;
335- }
336- }
337- else {
338- return null;
339- }
340-
341- return s;
342- }
343-
344- private async void import_art_async (Media m, DiscovererInfo info) {
345+ /* Get cover art */
346+ import_art_async.begin (s, info);
347+ } else {
348+ s = taglib_import_media (info.get_uri ());
349+
350+ if (s == null) {
351+ import_error (info.get_uri ().replace ("file://", ""));
352+ return;
353+ }
354+ }
355+
356+ /* Get the size */
357+ s.file_size = yield FileUtils.get_size_async (s.file);
358+ s.date_added = (int) time_t ();
359+
360+ media_imported (s);
361+ }
362+
363+ public Media? taglib_import_media (string uri) {
364+ Media s = new Media (uri);
365+ TagLib.File tag_file;
366+
367+ tag_file = new TagLib.File (uri.replace ("file://",""));
368+
369+ if (tag_file != null && tag_file.tag != null && tag_file.audioproperties != null) {
370+ try {
371+ s.title = tag_file.tag.title;
372+ s.artist = tag_file.tag.artist;
373+ s.album = tag_file.tag.album;
374+ s.genre = tag_file.tag.genre;
375+ s.comment = tag_file.tag.comment;
376+ s.year = (int) tag_file.tag.year;
377+ s.track = (int) tag_file.tag.track;
378+ s.bitrate = tag_file.audioproperties.bitrate;
379+
380+ s.length = (uint) (tag_file.audioproperties.length * Numeric.MILI_INV);
381+ s.samplerate = tag_file.audioproperties.samplerate;
382+ } finally {
383+ if (s.title == null || s.title == "") {
384+ string[] paths = uri.split ("/", 0);
385+ s.title = paths[paths.length - 1];
386+ }
387+
388+ if (s.artist == null || s.artist == "") s.artist = Media.UNKNOWN_ARTIST;
389+
390+ s.album_artist = s.artist;
391+ s.album_number = 1;
392+ }
393+ } else {
394+ return null;
395+ }
396+
397+ return s;
398+ }
399+
400+ private async void import_art_async (Media m, DiscovererInfo info) {
401 var cache = CoverartCache.instance;
402
403 if (cache.has_image (m))
404@@ -257,7 +253,7 @@
405 yield cache.cache_image_async (m, pix);
406 else
407 warning ("import_art: null pixbuf");
408- }
409+ }
410
411 private static Gdk.Pixbuf? get_image (Gst.TagList tag) {
412 Gst.Buffer? buffer = null;
413@@ -275,14 +271,14 @@
414 continue;
415
416 int image_type;
417- structure.get_enum ("image-type", typeof (Gst.TagImageType), out image_type);
418+ structure.get_enum ("image-type", typeof (Gst.TagImageType), out image_type);
419
420- if (image_type == Gst.TagImageType.FRONT_COVER) {
421- buffer = loop_buffer;
422- break;
423- } else if (image_type == Gst.TagImageType.UNDEFINED || buffer == null) {
424- buffer = loop_buffer;
425- }
426+ if (image_type == Gst.TagImageType.FRONT_COVER) {
427+ buffer = loop_buffer;
428+ break;
429+ } else if (image_type == Gst.TagImageType.UNDEFINED || buffer == null) {
430+ buffer = loop_buffer;
431+ }
432 }
433
434 if (buffer == null) {
435@@ -308,99 +304,99 @@
436 return pix;
437 }
438
439- public bool save_media(Media s) {
440- return false;
441-
442- /*Gst.Pipeline pipe = new Pipeline("pipe");
443- Element src = Element.make_from_uri(URIType.SRC, "file://" + s.file, null);
444- Element decoder = ElementFactory.make("decodebin", "decoder");
445-
446- GLib.Signal.connect(decoder, "new-decoded-pad", (GLib.Callback)newDecodedPad, this);
447-
448- if(!((Gst.Bin)pipe).add_many(src, decoder)) {
449- message ("Could not add src and decoder to pipeline to save metadata\n");
450- return false;
451- }
452-
453- if(!src.link_many(decoder)) {
454- message ("Could not link src to decoder to save metadata\n");
455- return false;
456- }
457-
458-
459- Gst.Element queue = ElementFactory.make("queue", "queue");
460- Gst.Element queue2 = ElementFactory.make("queue", "queue2");
461-
462- if(queue == null || queue2 == null) {
463- message ("could not add create queues to save metadata\n");
464- return false;
465- }
466-
467- if(!((Gst.Bin)pipe).add_many(queue, queue2)) {
468- warning ("Could not add queue's to save metadata\n");
469- return false;
470- }
471-
472- queue.set("max-size-time", 120 * Gst.SECOND);
473-
474-
475-
476-
477- //Element encoder = new_element_from_uri(URIType.SINK, "file://" + s.file, null);
478-
479- Gst.TagList tags;
480- bool rv = true;
481- //long day;
482-
483- tags = new TagList();
484- tags.add(TagMergeMode.REPLACE, TAG_TITLE, s.title,
485- TAG_ARTIST, s.artist,
486- TAG_COMPOSER, s.composer,
487- TAG_ALBUM_ARTIST, s.album_artist,
488- TAG_ALBUM, s.album,
489- TAG_GROUPING, s.grouping,
490- TAG_GENRE, s.genre,
491- TAG_COMMENT, s.comment,
492- TAG_LYRICS, s.lyrics,
493- TAG_TRACK_NUMBER, s.track,
494- TAG_TRACK_COUNT, s.track_count,
495- TAG_ALBUM_VOLUME_NUMBER, s.album_number,
496- TAG_ALBUM_VOLUME_COUNT, s.album_count,
497- TAG_USER_RATING, s.rating);
498-
499- /* fetch date, set new year to s.year, set date */
500-
501- // now find a tag setter interface and use it
502- /*Gst.Iterator iter;
503- bool done;
504-
505- iter = ((Gst.Bin)pipeline).iterate_all_by_interface(typeof(Gst.TagSetter));
506- done = false;
507- while (!done) {
508- Gst.TagSetter tagger = null;
509-
510- switch (iter.next(out tagger) {
511- case GST_ITERATOR_OK:
512- tagger.merge_tags (tags, GST_TAG_MERGE_REPLACE_ALL);
513- break;
514- case GST_ITERATOR_RESYNC:
515- iter.resync();
516- break;
517- case GST_ITERATOR_ERROR:
518- warning("Could not update metadata on media\n");
519- rv = false;
520- done = true;
521- break;
522- case GST_ITERATOR_DONE:
523- done = true;
524- break;
525- }
526- }
527-
528- return rv; */
529- }
530-
531- public bool save_embeddeart_d(Gdk.Pixbuf pix) {
532- return false;
533- }
534+ public bool save_media (Media s) {
535+ return false;
536+
537+ /*Gst.Pipeline pipe = new Pipeline("pipe");
538+ Element src = Element.make_from_uri(URIType.SRC, "file://" + s.file, null);
539+ Element decoder = ElementFactory.make("decodebin", "decoder");
540+
541+ GLib.Signal.connect(decoder, "new-decoded-pad", (GLib.Callback)newDecodedPad, this);
542+
543+ if(!((Gst.Bin)pipe).add_many(src, decoder)) {
544+ message ("Could not add src and decoder to pipeline to save metadata\n");
545+ return false;
546+ }
547+
548+ if(!src.link_many(decoder)) {
549+ message ("Could not link src to decoder to save metadata\n");
550+ return false;
551+ }
552+
553+
554+ Gst.Element queue = ElementFactory.make("queue", "queue");
555+ Gst.Element queue2 = ElementFactory.make("queue", "queue2");
556+
557+ if(queue == null || queue2 == null) {
558+ message ("could not add create queues to save metadata\n");
559+ return false;
560+ }
561+
562+ if(!((Gst.Bin)pipe).add_many(queue, queue2)) {
563+ warning ("Could not add queue's to save metadata\n");
564+ return false;
565+ }
566+
567+ queue.set("max-size-time", 120 * Gst.SECOND);
568+
569+
570+
571+
572+ //Element encoder = new_element_from_uri(URIType.SINK, "file://" + s.file, null);
573+
574+ Gst.TagList tags;
575+ bool rv = true;
576+ //long day;
577+
578+ tags = new TagList();
579+ tags.add(TagMergeMode.REPLACE, TAG_TITLE, s.title,
580+ TAG_ARTIST, s.artist,
581+ TAG_COMPOSER, s.composer,
582+ TAG_ALBUM_ARTIST, s.album_artist,
583+ TAG_ALBUM, s.album,
584+ TAG_GROUPING, s.grouping,
585+ TAG_GENRE, s.genre,
586+ TAG_COMMENT, s.comment,
587+ TAG_LYRICS, s.lyrics,
588+ TAG_TRACK_NUMBER, s.track,
589+ TAG_TRACK_COUNT, s.track_count,
590+ TAG_ALBUM_VOLUME_NUMBER, s.album_number,
591+ TAG_ALBUM_VOLUME_COUNT, s.album_count,
592+ TAG_USER_RATING, s.rating);
593+
594+ /* fetch date, set new year to s.year, set date */
595+
596+ // now find a tag setter interface and use it
597+ /*Gst.Iterator iter;
598+ bool done;
599+
600+ iter = ((Gst.Bin)pipeline).iterate_all_by_interface(typeof(Gst.TagSetter));
601+ done = false;
602+ while (!done) {
603+ Gst.TagSetter tagger = null;
604+
605+ switch (iter.next(out tagger) {
606+ case GST_ITERATOR_OK:
607+ tagger.merge_tags (tags, GST_TAG_MERGE_REPLACE_ALL);
608+ break;
609+ case GST_ITERATOR_RESYNC:
610+ iter.resync();
611+ break;
612+ case GST_ITERATOR_ERROR:
613+ warning("Could not update metadata on media\n");
614+ rv = false;
615+ done = true;
616+ break;
617+ case GST_ITERATOR_DONE:
618+ done = true;
619+ break;
620+ }
621+ }
622+
623+ return rv; */
624+ }
625+
626+ public bool save_embeddeart_d (Gdk.Pixbuf pix) {
627+ return false;
628+ }
629 }

Subscribers

People subscribed via source and target branches