Merge lp:~bidossessi-sodonon/synapse-project/mpc-plugin into lp:synapse-project

Proposed by Bidossessi Sodonon
Status: Needs review
Proposed branch: lp:~bidossessi-sodonon/synapse-project/mpc-plugin
Merge into: lp:synapse-project
Diff against target: 667 lines (+641/-0)
3 files modified
src/plugins/Makefile.am (+1/-0)
src/plugins/mpc-plugin.vala (+639/-0)
src/ui/synapse-main.vala (+1/-0)
To merge this branch: bzr merge lp:~bidossessi-sodonon/synapse-project/mpc-plugin
Reviewer Review Type Date Requested Status
Bidossessi Sodonon (community) Needs Resubmitting
Alberto Aldegheri Needs Fixing
Michal Hruby Needs Fixing
Review via email: mp+62308@code.launchpad.net

This proposal supersedes a proposal from 2011-05-25.

Description of the change

Changed MpcEngine's methods to static to avoid unnecessary instantiation.

To post a comment you must log in.
Revision history for this message
Alberto Aldegheri (albyrock87) wrote : Posted in a previous version of this proposal

First of all, thank you for your contribution! :)

Some comments:
1)
MpcEngine class is instantiated each time I execute an action.
But MpcEngine doesn't have "attributes" that needs to be instantiated.
So I suggest to turn each method and attribute of MpcEnginge into a static one.
In example:
private static string bin = "mpc"; //this can be also "const"
public static void play_pause ()...

In this way you can call directly:
MpcEngine.play_pause ();

2) what's the meaning of
 >>search the database for a "type" and turn results to uris on the fly<< ?

3) Synapse's configuration capabilities will come asap (mhr3 and I are very busy in this moment)

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote : Posted in a previous version of this proposal

Thanks for your prompt reply.

About 1), blame my lack of programming experience with compiled code. I will update this asap.

Now, for 2), from man mpc:

search <type> <query> [<type> <query>]...
              Searches for songs where all of the given tag <type>s match the given <query>s. Any number of tag type and query combinations can be specified. Possible tag
              types are: artist, album, title, track, name, genre, date, composer, performer, comment, disc, filename, or any (to match any tag).

Here is a sample of the list returned:

[b_sodonon@sysadmin synapse-project]$ mpc search genre world
Ali Farka Toure & Toumani Diabate/In the Heart of the Moon/02. Kala.mp3
Ali Farka Toure & Toumani Diabate/In the Heart of the Moon/03. Mamadou Boutiquier.mp3

The resulting file paths are relative to mpd's "musid_dir" configuration.

what needs to happen is the following (python):

abs_path = music_dir + rel_path
uri = 'file://' + str(urllib.quote(mpd_path, safe='/~'))

I use that code to create uris I feed into zeitgeist.

I have no idea how to do that in vala.
Not to mention that, to enqueue files in mpd, I have to provide relative_path as an argument, which means going from uri to relative path. No idea how I could do that either. So until I become a bit more conversant with vala, I'll stick to the basic functionality.

Once again, thanks for the reply. It feels good be finally giving back to the community. :)

Cheers.

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote :

I hope this is the right way to go about updating my merge proposal.
If not, I'm sorry.

Cheers

Revision history for this message
Alberto Aldegheri (albyrock87) wrote :

:) Do not resubmit the proposal (I made the same mistake the first time I used Launchpad :P).
Just add a comment an I (or mhr3) will come here and look at changes.

I'll look at your merge proposal asap!

443. By Bidossessi Sodonon

Forgot to add the "stop" command

444. By Bidossessi Sodonon

Forgot some strings to make Stop appear

445. By Bidossessi Sodonon

Fixed unreachable catch issues

446. By Bidossessi Sodonon

Feature-complete code, as compared to banshee-plugin

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote :

Plugin is now feature-complete, using banshee as a feature basis.

It does the following actions:
- start, stop, pause and resume playback
- enqueue a uri in mpd
- play a track, clearing the playlist

I reinstated instantiation in prevision of Synapse's configuration capabilities.
That way, (almost) no refactoring will be needed.

I'm sure the code is not optimized, but, that's my level, for now.

Cheers

447. By Bidossessi Sodonon

Fixed the location for this file.

448. By Bidossessi Sodonon

Updated the pot file.

Revision history for this message
Michal Hruby (mhr3) wrote :

A few notes:

- please revert the changes to hybrid-search-plugin
- line 210-217 and others - why do you catch the error, if you only re-throw it?

Other than that it looks ok...

review: Needs Fixing
449. By Bidossessi Sodonon

* reverted hybrid-search-plugin to previous code
* stopped catching errors in public methods in mpc-plugin (no real need)
* updated synapse.pot to

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote :

> A few notes:
>
> - please revert the changes to hybrid-search-plugin
> - line 210-217 and others - why do you catch the error, if you only re-throw
> it?
>
> Other than that it looks ok...
Well, I kept catching until vala stopped giving me unhandled error messages. They were kind of scary. But I admint there's no real need to do that.

I believe that with 449, this plugin is ready.

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote :

Please check if more needs to be done for this plugin.
Thank you.

review: Needs Resubmitting
Revision history for this message
Alberto Aldegheri (albyrock87) wrote :

Please, enter in Synapse's folder, and execute:
bzr revert --revision 440 src/plugins/hybrid-search-plugin.vala

And:

bzr revert --revision 440 po/synapse.pot

(we'll update translations later)

At this point: return path[music_root.length:path.length]; (line 411 of the diff)
Are you sure that music_root is a prefix of path ?

review: Needs Fixing
450. By Bidossessi Sodonon

Don't try to play files that are not in MPD's music root (since it will fail anyway).

451. By Bidossessi Sodonon

Reverted pot file and hybrid-search-plugin to rev 440.

Revision history for this message
Bidossessi Sodonon (bidossessi-sodonon) wrote :

> Please, enter in Synapse's folder, and execute:
> bzr revert --revision 440 src/plugins/hybrid-search-plugin.vala
>
> And:
>
> bzr revert --revision 440 po/synapse.pot
>
> (we'll update translations later)
>
Done, and sorry about that.
> At this point: return path[music_root.length:path.length]; (line 411 of the
> diff)
> Are you sure that music_root is a prefix of path ?
Got it: files not in mpd's music_root are now handled.

review: Needs Resubmitting
Revision history for this message
Antono Vasiljev (antono) wrote :

Any updates here?

Unmerged revisions

451. By Bidossessi Sodonon

Reverted pot file and hybrid-search-plugin to rev 440.

450. By Bidossessi Sodonon

Don't try to play files that are not in MPD's music root (since it will fail anyway).

449. By Bidossessi Sodonon

* reverted hybrid-search-plugin to previous code
* stopped catching errors in public methods in mpc-plugin (no real need)
* updated synapse.pot to

448. By Bidossessi Sodonon

Updated the pot file.

447. By Bidossessi Sodonon

Fixed the location for this file.

446. By Bidossessi Sodonon

Feature-complete code, as compared to banshee-plugin

445. By Bidossessi Sodonon

Fixed unreachable catch issues

444. By Bidossessi Sodonon

Forgot some strings to make Stop appear

443. By Bidossessi Sodonon

Forgot to add the "stop" command

442. By Bidossessi Sodonon

Turned MpcEngine instance method to class methods (static)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/plugins/Makefile.am'
--- src/plugins/Makefile.am 2011-04-18 14:49:45 +0000
+++ src/plugins/Makefile.am 2011-05-31 10:31:30 +0000
@@ -46,6 +46,7 @@
46 hybrid-search-plugin.vala \46 hybrid-search-plugin.vala \
47 launchpad-plugin.vala \47 launchpad-plugin.vala \
48 locate-plugin.vala \48 locate-plugin.vala \
49 mpc-plugin.vala \
49 opensearch.vala \50 opensearch.vala \
50 pastebin-plugin.vala \51 pastebin-plugin.vala \
51 pidgin-plugin.vala \52 pidgin-plugin.vala \
5253
=== added file 'src/plugins/mpc-plugin.vala'
--- src/plugins/mpc-plugin.vala 1970-01-01 00:00:00 +0000
+++ src/plugins/mpc-plugin.vala 2011-05-31 10:31:30 +0000
@@ -0,0 +1,639 @@
1/*
2 * Copyright (C) 2011 Bidossessi Sodonon <stanislas.sodonon at gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Authored by Bidossessi Sodonon <stanislas.sodonon at gmail.com>
19 *
20 */
21
22namespace Synapse
23{
24 public class MpcEngine: Object
25 {
26 // our executable string array
27 private const string bin = "mpc";
28 // mpd paths are relative to this directory
29 public string music_root {get;construct;}
30 // if these default values are given, use them
31 public string host {get;construct;} // localhost by defaut
32 public string port {get;construct;} // 6600 by default
33 public string passwd {get;construct;}// no pasword by default
34
35 // constructor
36 public MpcEngine (string? host = "localhost",
37 string? port = "6600", string? passwd = null,
38 string? music_root = null)
39 {
40 // mpc is called like this: mpc [-h [_passwd@]_host] [-p _port] <command> [arguments]
41 Object(host: host, port: port, passwd: passwd, music_root: music_root);
42 }
43 construct {
44 //make sure we find the music_dir if it wasn't given.
45 music_root = find_music_root(music_root);
46 }
47
48 /* Public operations (pass errors to caller)*/
49 public void stop () throws IOError
50 {
51 run_command("stop");
52 }
53 public void play_pause () throws IOError
54 {
55 run_command("toggle");
56 }
57 public void play_now (string uri) throws IOError
58 {
59 string rel_path = path_from_uri(uri);
60 run_command ("clear");
61 run_command ("add", rel_path);
62 run_command ("play");
63 }
64 public void enqueue (string uri) throws IOError
65 {
66 string rel_path = path_from_uri(uri);
67 run_command("add", rel_path);
68 }
69 public void next () throws IOError
70 {
71 run_command("next");
72 }
73 public void previous () throws IOError
74 {
75 run_command("prev");
76 }
77
78 /* Engine Internals */
79 // convenience function
80 protected string turn_abs(string user_path)
81 {
82 //this shouldn't affect absolute paths
83 try
84 {
85 MatchInfo info;
86 Regex regex = new Regex("^~");
87 string user_dir = Environment.get_home_dir();
88 if (regex.match(user_path, 0, out info))
89 {
90 string abs_path = regex.replace (user_path, -1, 0, user_dir);
91 //make sure it exists
92 var u = File.new_for_path(abs_path);
93 if (u.query_exists ())
94 {
95 return abs_path;
96 }
97 }
98 }
99 // ouch, what happened?
100 catch (Error e)
101 {
102 Utils.Logger.warning (this,"Failed to turn %s to absolute path: %s", user_path, e.message);
103 }
104 return user_path;
105 }
106
107 protected File? get_mpd_conf ()
108 {
109 // try ~/.mpdconf
110 string user_conf = turn_abs("~/.mpdconf");
111 var ufile = File.new_for_path (user_conf);
112 if (ufile.query_exists ())
113 {
114 return ufile;
115 }
116 // try /etc/mpd.conf
117 else
118 {
119 Utils.Logger.warning (this,"File '%s' doesn't exist", user_conf);
120 //not found, trying the other, hoping it's world-readable
121 var sfile = File.new_for_path ("/etc/mpd.conf");
122 if (sfile.query_exists ())
123 {
124 return sfile;
125 }
126 }
127 Utils.Logger.warning (this,"File '/etc/mpd.conf' doesn't exist");
128 return null;
129 }
130
131 protected string? find_music_root (string? given_root)
132 {
133 try
134 {
135 if (given_root != null)
136 {
137 var g = File.new_for_path(given_root);
138 if (g.query_exists ())
139 {
140 return given_root;
141 }
142 }
143 // the given path didn't check out
144 else
145 {
146 File file = get_mpd_conf();
147 if (file != null)
148 {
149 var dis = new DataInputStream (file.read ());
150 string line;
151 while ((line = dis.read_line (null)) != null)
152 {
153 //find the right line
154 Regex tag = new Regex("^music_directory.*$");
155 if (tag.match (line))
156 {
157 //capture the dir between the quotation marks
158 MatchInfo info;
159 Regex dir = new Regex("(?<=\")(.*?)(?=\")");
160 if (dir.match (line, 0, out info))
161 {
162 string found_root = turn_abs(info.fetch(0)) + "/";
163 //make sure it exists
164 var r = File.new_for_path(found_root);
165 if (r.query_exists ())
166 {
167 return found_root;
168 }
169 }
170 }
171 }
172 }
173 }
174 }
175 catch (Error e)
176 {
177 Utils.Logger.warning (this,"Music root not found: %s", e.message);
178 }
179 return null;
180 }
181
182 // convert uri to relative path
183 private string? path_from_uri (string uri) throws IOError
184 {
185 try
186 {
187 string path = Filename.from_uri(uri);
188 //make sure it exists
189 var p = File.new_for_path(path);
190 if (p.query_exists ())
191 {
192 if (music_root != null)
193 {
194 if (music_root in path)
195 {
196 //strip music_root
197 return path[music_root.length:path.length];
198 }
199 else
200 {
201 throw new IOError.NOT_FOUND("File not in mpd's music root");
202 }
203 }
204 else
205 {
206 throw new IOError.NOT_FOUND("Music root not found");
207 }
208 }
209 else
210 {
211 throw new IOError.NOT_FOUND("File %s not found", path);
212 }
213 }
214 catch (Error e)
215 {
216 Utils.Logger.warning (this,"Couldn't convert URI to filename: %s", e.message);
217 }
218 return null;
219 }
220
221 // run command
222 protected void run_command (string command,
223 string? qtype = null, string? sarg = null) throws IOError
224 {
225 Pid pid;
226 string complete_output = "";
227 bool error_found = false;
228 string[] argv = {bin};
229 if (host != null)
230 {
231 var s = new StringBuilder();
232 if (passwd != null)
233 {
234 s.append_printf("%s@", passwd);
235 }
236 s.append_printf("%s", host);
237 argv += "-h";
238 argv += s.str;
239 }
240 if (port != null)
241 {
242 argv += "-p";
243 argv += port;
244 }
245 argv += command;
246 if (qtype != null)
247 {
248 argv += qtype;
249 if (sarg != null)
250 {
251 argv += sarg;
252 }
253 }
254
255 try
256 {
257 int read_fd;
258 // FIXME: probably a better way to do this
259 Process.spawn_async_with_pipes (null, argv, null,
260 SpawnFlags.SEARCH_PATH,
261 null, out pid, null, out read_fd);
262 UnixInputStream read_stream = new UnixInputStream (read_fd, true);
263 DataInputStream mpd_output = new DataInputStream (read_stream);
264
265 string? line = null;
266 do
267 {
268 line = mpd_output.read_line (null);
269 if (line != null)
270 {
271 complete_output += line;
272 }
273 } while (line != null);
274 // try and catch any 'error' line from mpc
275 Regex error = new Regex ("error:.*$");
276 if (error.match (complete_output))
277 {
278 error_found = true;
279 }
280 }
281 catch (Error err)
282 {
283 Utils.Logger.warning (this,"MPD is not available: %s", err.message);
284 }
285 if (error_found == true)
286 {
287 throw new IOError.CONNECTION_REFUSED (complete_output);
288 }
289 }
290 }//end of MpcEngine
291
292
293 /* SYNAPSE side (finally :p) */
294 public class MpcActions: Object, Activatable, ItemProvider, ActionProvider
295 {
296 public bool enabled { get; set; default = true; }
297
298 public void activate ()
299 {
300 }
301
302 public void deactivate ()
303 {
304 }
305
306 static void register_plugin ()
307 {
308 DataSink.PluginRegistry.get_default ().register_plugin (
309 typeof (MpcActions),
310 _ ("Mpc"),
311 _ ("Control the Music Player Daemon."),
312 "mpc",
313 register_plugin,
314 Environment.find_program_in_path ("mpc") != null,
315 _ ("mpc is not installed")
316 );
317 }
318
319 static construct
320 {
321 register_plugin ();
322 }
323
324 private abstract class MpcAction: Object, Match
325 {
326 // from Match interface
327 public string title { get; construct set; }
328 public string description { get; set; }
329 public string icon_name { get; construct set; }
330 public bool has_thumbnail { get; construct set; }
331 public string thumbnail_path { get; construct set; }
332 public MatchType match_type { get; construct set; }
333
334 public int default_relevancy { get; set; }
335
336 public abstract bool valid_for_match (Match match);
337
338 public abstract void execute_internal (Match? match);
339 public void execute (Match? match)
340 {
341 execute_internal (match);
342 }
343 public virtual int get_relevancy ()
344 {
345 return default_relevancy + Match.Score.INCREMENT_LARGE;
346 }
347 }
348
349 private abstract class MpcControlMatch: Object, Match
350 {
351 // for Match interface
352 public string title { get; construct set; }
353 public string description { get; set; default = ""; }
354 public string icon_name { get; construct set; default = ""; }
355 public bool has_thumbnail { get; construct set; default = false; }
356 public string thumbnail_path { get; construct set; }
357 public MatchType match_type { get; construct set; }
358
359 public void execute (Match? match)
360 {
361 this.do_action ();
362 }
363
364 public abstract void do_action ();
365
366 }
367
368 /* MATCHES of Type.ACTION */
369 private class Play: MpcControlMatch
370 {
371 public Play ()
372 {
373 Object (title: _ ("Play"),
374 description: _ ("Start playback in MPD"),
375 icon_name: "media-playback-start", has_thumbnail: false,
376 match_type: MatchType.ACTION);
377 }
378 public override void do_action ()
379 {
380 try
381 {
382 var player = new MpcEngine ();
383 player.play_pause ();
384 }
385 catch (IOError e) {
386 Utils.Logger.warning (this,"MPD is not available: %s", e.message);
387 }
388 }
389 }
390
391 private class Pause: Play
392 {
393 public Pause ()
394 {
395 Object (title: _ ("Pause"),
396 description: _ ("Pause playback in MPD"),
397 icon_name: "media-playback-pause", has_thumbnail: false,
398 match_type: MatchType.ACTION);
399 }
400 }
401
402 private class Next: MpcControlMatch
403 {
404 public Next ()
405 {
406 Object (title: _ ("Next"),
407 description: _ ("Plays the next song in MPD's playlist"),
408 icon_name: "media-skip-forward", has_thumbnail: false,
409 match_type: MatchType.ACTION);
410 }
411
412 public override void do_action ()
413 {
414 try
415 {
416 var player = new MpcEngine ();
417 player.next ();
418 }
419 catch (IOError e) {
420 Utils.Logger.warning (this,"MPD is not available: %s", e.message);
421 }
422 }
423
424 }
425 private class Previous: MpcControlMatch
426 {
427 public Previous ()
428 {
429 Object (title: _ ("Previous"),
430 description: _ ("Plays the previous song in MPD's playlist"),
431 icon_name: "media-skip-backward", has_thumbnail: false,
432 match_type: MatchType.ACTION);
433 }
434
435 public override void do_action ()
436 {
437 try
438 {
439 var player = new MpcEngine ();
440 player.previous ();
441 }
442 catch (IOError e) {
443 Utils.Logger.warning (this,"MPD is not available: %s", e.message);
444 }
445 }
446 }
447
448 private class Stop: MpcControlMatch
449 {
450 public Stop ()
451 {
452 Object (title: _ ("Stop"),
453 description: _ ("Stop playback in MPD"),
454 icon_name: "media-stop", has_thumbnail: false,
455 match_type: MatchType.ACTION);
456 }
457
458 public override void do_action ()
459 {
460 try
461 {
462 var player = new MpcEngine ();
463 player.stop ();
464 }
465 catch (IOError e) {
466 Utils.Logger.warning (this, "MPD is not available: %s", e.message);
467 }
468 }
469 }
470
471 /* ACTIONS FOR Music files */
472 private class AddToPlaylist: MpcAction
473 {
474 public AddToPlaylist ()
475 {
476 Object (title: _ ("Enqueue in MPD"),
477 description: _ ("Add the song to MPD's playlist"),
478 icon_name: "media-playback-start", has_thumbnail: false,
479 match_type: MatchType.ACTION,
480 default_relevancy: Match.Score.AVERAGE);
481 }
482
483 public override void execute_internal (Match? match)
484 {
485 return_if_fail (match.match_type == MatchType.GENERIC_URI);
486 UriMatch uri = match as UriMatch;
487 return_if_fail ((uri.file_type & QueryFlags.AUDIO) != 0);
488
489 try
490 {
491 var player = new MpcEngine ();
492 player.enqueue (uri.uri);
493 }
494 catch (IOError e) {
495 Utils.Logger.warning (this, "MPD is not available: %s", e.message);
496 }
497
498 }
499
500 public override bool valid_for_match (Match match)
501 {
502 switch (match.match_type)
503 {
504 case MatchType.GENERIC_URI:
505 UriMatch uri = match as UriMatch;
506 if ((uri.file_type & QueryFlags.AUDIO) != 0)
507 return true;
508 else
509 return false;
510 default:
511 return false;
512 }
513 }
514 }
515 private class PlayNow: MpcAction
516 {
517 public PlayNow ()
518 {
519 Object (title: _ ("Play in MPD"),
520 description: _ ("Clears the current playlist and plays the song"),
521 icon_name: "media-playback-start", has_thumbnail: false,
522 match_type: MatchType.ACTION,
523 default_relevancy: Match.Score.ABOVE_AVERAGE);
524 }
525
526 public override void execute_internal (Match? match)
527 {
528 return_if_fail (match.match_type == MatchType.GENERIC_URI);
529 UriMatch uri = match as UriMatch;
530 return_if_fail ((uri.file_type & QueryFlags.AUDIO) != 0 );
531
532 try
533 {
534 var player = new MpcEngine ();
535 player.play_now (uri.uri);
536 }
537 catch (IOError e) {
538 Utils.Logger.warning (this, "MPD is not available: %s", e.message);
539 }
540 }
541
542 public override bool valid_for_match (Match match)
543 {
544 switch (match.match_type)
545 {
546 case MatchType.GENERIC_URI:
547 UriMatch uri = match as UriMatch;
548 if ((uri.file_type & QueryFlags.AUDIO) != 0)
549 return true;
550 else
551 return false;
552 default:
553 return false;
554 }
555 }
556 }
557
558 private Gee.List<MpcAction> actions;
559 private Gee.List<MpcControlMatch> matches;
560
561 construct
562 {
563 actions = new Gee.ArrayList<MpcAction> ();
564 matches = new Gee.ArrayList<MpcControlMatch> ();
565
566 actions.add (new PlayNow());
567 actions.add (new AddToPlaylist());
568
569 matches.add (new Play ());
570 matches.add (new Stop ());
571 matches.add (new Pause ());
572 matches.add (new Previous ());
573 matches.add (new Next ());
574 }
575
576 public async ResultSet? search (Query q) throws SearchError
577 {
578 // we only search for actions
579 if (!(QueryFlags.ACTIONS in q.query_type)) return null;
580
581 var result = new ResultSet ();
582
583 var matchers = Query.get_matchers_for_query (q.query_string, 0,
584 RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
585
586 foreach (var action in matches)
587 {
588 foreach (var matcher in matchers)
589 {
590 if (matcher.key.match (action.title))
591 {
592 result.add (action, matcher.value - Match.Score.INCREMENT_SMALL);
593 break;
594 }
595 }
596 }
597
598 q.check_cancellable ();
599
600 return result;
601 }
602
603 public ResultSet? find_for_match (Query query, Match match)
604 {
605 bool query_empty = query.query_string == "";
606 var results = new ResultSet ();
607
608 if (query_empty)
609 {
610 foreach (var action in actions)
611 {
612 if (action.valid_for_match (match))
613 {
614 results.add (action, action.get_relevancy ());
615 }
616 }
617 }
618 else
619 {
620 var matchers = Query.get_matchers_for_query (query.query_string, 0,
621 RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
622 foreach (var action in actions)
623 {
624 if (!action.valid_for_match (match)) continue;
625 foreach (var matcher in matchers)
626 {
627 if (matcher.key.match (action.title))
628 {
629 results.add (action, matcher.value);
630 break;
631 }
632 }
633 }
634 }
635
636 return results;
637 }
638 }
639}
0640
=== modified file 'src/ui/synapse-main.vala'
--- src/ui/synapse-main.vala 2011-05-05 00:07:47 +0000
+++ src/ui/synapse-main.vala 2011-05-31 10:31:30 +0000
@@ -178,6 +178,7 @@
178 // typeof (FileOpPlugin),178 // typeof (FileOpPlugin),
179 // typeof (PidginPlugin),179 // typeof (PidginPlugin),
180 // typeof (ChatActions),180 // typeof (ChatActions),
181 typeof (MpcActions),
181#if HAVE_ZEITGEIST182#if HAVE_ZEITGEIST
182 typeof (ZeitgeistPlugin),183 typeof (ZeitgeistPlugin),
183#endif184#endif