Merge lp:~jeremy-munsch/synapse-project/steam-plugin into lp:synapse-project

Proposed by Jeremy Munsch
Status: Needs review
Proposed branch: lp:~jeremy-munsch/synapse-project/steam-plugin
Merge into: lp:synapse-project
Diff against target: 265 lines (+239/-0)
3 files modified
src/plugins/Makefile.am (+1/-0)
src/plugins/steam-plugin.vala (+237/-0)
src/ui/synapse-main.vala (+1/-0)
To merge this branch: bzr merge lp:~jeremy-munsch/synapse-project/steam-plugin
Reviewer Review Type Date Requested Status
Rico Tzschichholz Pending
Review via email: mp+278256@code.launchpad.net

Description of the change

add steam plugin for games search and action providers
no dependencies

To post a comment you must log in.
634. By Rico Tzschichholz

ui/controller: Some optimization accessing model.query[] in search*()

635. By Rico Tzschichholz

core/query: Cache and reuse Regex.escape_string (query)

636. By Rico Tzschichholz

debian: Bump build-deps accordingly

637. By Rico Tzschichholz

plugins: Add suport for MATE Screensaver

638. By Rico Tzschichholz

po: Update translations

639. By Rico Tzschichholz

desktop-file-plugin: correct ApplicationsMatch to DesktopFileMatch

640. By Rico Tzschichholz

src: Drop "using Gee;"

641. By Rico Tzschichholz

src: Drop "using Json;"

642. By Rico Tzschichholz

src: Drop "using Zeitgeist;"

643. By Rico Tzschichholz

src: Drop "using Gtk;"

644. By Rico Tzschichholz

src: Drop "using Cairo;"

645. By Rico Tzschichholz

src: Drop last usages of "using *;"

646. By Rico Tzschichholz

ui: Show release-name in about-dialog only

647. By Rico Tzschichholz

ui: Bump to 2016

648. By Rico Tzschichholz

Release 0.2.99.2

649. By Rico Tzschichholz

ui: Set and update client-window of Gtk.IMMulticontext

650. By Rico Tzschichholz

main: Properly construct OptionEntry

Stop using an empty string where is getting treated as translateable.

651. By Michael Aquilina

Add pass plugin

652. By Rico Tzschichholz

Fix non-matching generic types

653. By Rico Tzschichholz

Fix non-matching generic types of interface implementations

654. By Jeremy Munsch

add steam plugin

Unmerged revisions

654. By Jeremy Munsch

add steam plugin

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 2016-04-01 05:58:51 +0000
+++ src/plugins/Makefile.am 2016-12-16 20:48:59 +0000
@@ -53,6 +53,7 @@
53 test-slow-plugin.vala \53 test-slow-plugin.vala \
54 xnoise-media-player-plugin.vala \54 xnoise-media-player-plugin.vala \
55 system-management.vala \55 system-management.vala \
56 steam-plugin.vala \
56 zeal-plugin.vala \57 zeal-plugin.vala \
57 $(NULL)58 $(NULL)
5859
5960
=== added file 'src/plugins/steam-plugin.vala'
--- src/plugins/steam-plugin.vala 1970-01-01 00:00:00 +0000
+++ src/plugins/steam-plugin.vala 2016-12-16 20:48:59 +0000
@@ -0,0 +1,237 @@
1/*
2 * Copyright (C) 2015 Jérémy Munsch <jeremy.munsch@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 */
19
20namespace Synapse
21{
22 public class SteamPlugin : Object, Activatable, ItemProvider, ActionProvider
23 {
24 public bool enabled { get; set; default = true; }
25
26 public static string steam_games_dir { get; private set; default = ".steam/SteamApps"; }
27
28 private Gee.List<SteamGameMatch> games;
29 private Gee.List<SteamAction> actions;
30
31 public void activate ()
32 {
33 parse_steam_games.begin ();
34 }
35
36 public void deactivate ()
37 {
38 }
39
40 static void register_plugin ()
41 {
42 PluginRegistry.get_default ().register_plugin (
43 typeof (SteamPlugin),
44 _("Steam"),
45 _("Browse and launch your steam games"),
46 "steam",
47 register_plugin,
48 Environment.find_program_in_path ("steam") != null,
49 _("Unable to find \"steam\" program")
50 );
51 }
52
53 static construct
54 {
55 register_plugin ();
56 steam_games_dir = Path.build_filename (Environment.get_home_dir (), steam_games_dir);
57 }
58
59 construct
60 {
61 games = new Gee.ArrayList<SteamGameMatch> ();
62 actions = new Gee.ArrayList<SteamAction> ();
63 actions.add (new SteamAction (_("Start game"), _("Launch the game through Steam"), "steam steam://rungameid/%s", MatchScore.HIGHEST));
64 actions.add (new SteamAction (_("Open store"), _("Go to the game store"), "steam steam://store/%s"));
65 actions.add (new SteamAction (_("Open newspage"), _("Go to the game newspage"), "steam steam://appnews/%s"));
66 actions.add (new SteamAction (_("Check system requirement"), _("Check if the system meets the game requirement"), "steam steam://checksysreqs/%s"));
67 actions.add (new SteamAction (_("Backup"), _("Launch the backup wizard"), "steam steam://backup/%s"));
68 }
69
70 public bool handles_query (Query query)
71 {
72 return (QueryFlags.APPLICATIONS in query.query_type);
73 }
74
75 public async ResultSet? search (Query q) throws SearchError
76 {
77 var results = new ResultSet ();
78
79 var matchers = Query.get_matchers_for_query (q.query_string, MatcherFlags.NO_FUZZY, RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
80 foreach (var matcher in matchers)
81 {
82 foreach (var game in games)
83 {
84 q.check_cancellable ();
85 if (matcher.key.match (game.title))
86 results.add (game, matcher.value);
87 }
88 }
89 return results;
90 }
91
92 public ResultSet? find_for_match (ref Query q, Match match)
93 {
94 if (!actions[0].valid_for_match (match))
95 return null;
96
97 var matchers = Query.get_matchers_for_query (q.query_string, 0, RegexCompileFlags.OPTIMIZE | RegexCompileFlags.CASELESS);
98
99 var results = new ResultSet ();
100 foreach (var matcher in matchers)
101 {
102 foreach (var action in actions)
103 {
104 if (matcher.key.match (action.title))
105 results.add (action, matcher.value + action.default_relevancy);
106 }
107 }
108 return results;
109 }
110
111
112 /**
113 * Actions
114 */
115
116 private class SteamAction : Action
117 {
118 public string command { get; set; }
119
120 public SteamAction (string title, string description, string command, int default_relevancy = MatchScore.AVERAGE)
121 {
122 Object (title: title,
123 description: description,
124 icon_name: "steam",
125 has_thumbnail: false);
126 this.command = command;
127 this.default_relevancy = default_relevancy;
128 }
129
130 public override bool valid_for_match (Match match)
131 {
132 return (match is SteamGameMatch);
133 }
134
135 public override void do_execute (Match match, Match? target = null)
136 {
137 string cmd = command.printf (((SteamGameMatch)match).app_id);
138 try
139 {
140 AppInfo ai = AppInfo.create_from_commandline (cmd, "steam", 0);
141 if (!ai.launch (null, null))
142 warning ("Could not launch Steam %s".printf (cmd));
143 }
144 catch (Error err)
145 {
146 warning ("Could not launch %s %s", cmd, err.message);
147 }
148 }
149 }
150
151
152 /**
153 * Match
154 */
155
156 private class SteamGameMatch : Match
157 {
158 public string app_id { get; set; }
159 public string name { get; set; }
160
161 public SteamGameMatch (string app_id, string name)
162 {
163 Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
164 Gtk.IconInfo? icon_info = icon_theme.lookup_icon ("steam_icon_%s".printf (app_id), 48, 0);
165
166 Object (title: "Steam %s".printf (name),
167 description : "",
168 icon_name: icon_info != null ? "steam_icon_%s".printf (app_id) : "steam",
169 has_thumbnail: false);
170 this.app_id = app_id;
171 this.name = name;
172 }
173 }
174
175
176 /**
177 * private methods
178 */
179
180 private async void parse_steam_games ()
181 {
182 try
183 {
184 File steam_apps = File.new_for_path (steam_games_dir);
185
186 FileEnumerator enumerator = steam_apps.enumerate_children (
187 "standard::*",
188 FileQueryInfoFlags.NOFOLLOW_SYMLINKS);
189
190 FileInfo info = null;
191 while ((info = enumerator.next_file ()) != null)
192 {
193 Idle.add_full (Priority.DEFAULT_IDLE, parse_steam_games.callback);
194 yield;
195 if (info.get_file_type () == FileType.REGULAR && Regex.match_simple ("appmanifest_[0-9]*.acf", info.get_name ()))
196 {
197 try
198 {
199 string app_id = null, app_name = null;
200
201 File file = File.new_for_path (Path.build_filename (steam_games_dir, info.get_name ()));
202
203 FileInputStream @is = file.read ();
204 DataInputStream dis = new DataInputStream (@is);
205 string line;
206
207 while ((line = dis.read_line ()) != null) {
208 if (null == app_id && -1 != line.index_of ("\"appid\""))
209 app_id = (new Regex ("(?:\t* *\"[a-zA-Z]+\"\t)|\"|\t")).replace (line, line.length, 0, "").strip ();
210 if (null == app_name && -1 != line.index_of ("\"name\""))
211 app_name = (new Regex ("(?:\t* *\"[a-zA-Z]+\"\t)|\"|\t")).replace (line, line.length, 0, "").strip ();
212 if (null != app_id && null != app_name)
213 break;
214 }
215
216 if (null == app_id && null == app_name)
217 {
218 message ("Was not able to parse Steam app manifest %s".printf (Path.build_filename (steam_games_dir, info.get_name ())));
219 break;
220 }
221
222 games.add (new SteamGameMatch (app_id, app_name));
223 }
224 catch (Error e)
225 {
226 warning ("%s", e.message);
227 }
228 }
229 }
230 }
231 catch (Error e)
232 {
233 warning ("%s".printf (e.message));
234 }
235 }
236 }
237}
0238
=== modified file 'src/ui/synapse-main.vala'
--- src/ui/synapse-main.vala 2016-04-01 05:58:51 +0000
+++ src/ui/synapse-main.vala 2016-12-16 20:48:59 +0000
@@ -176,6 +176,7 @@
176 typeof (PidginPlugin),176 typeof (PidginPlugin),
177 typeof (PassPlugin),177 typeof (PassPlugin),
178 typeof (ChatActions),178 typeof (ChatActions),
179 typeof (SteamPlugin),
179 typeof (ZealPlugin),180 typeof (ZealPlugin),
180#if HAVE_ZEITGEIST181#if HAVE_ZEITGEIST
181 typeof (ZeitgeistPlugin),182 typeof (ZeitgeistPlugin),