[gnome-games/wip/aplazas/run-uri: 4/4] Add GameSource.game_for_uri()
- From: Adrien Plazas <aplazas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games/wip/aplazas/run-uri: 4/4] Add GameSource.game_for_uri()
- Date: Wed, 12 Apr 2017 06:53:43 +0000 (UTC)
commit 9705143e5fd7d332920c3e85ef86f48ad4cd29ef
Author: Adrien Plazas <kekun plazas laposte net>
Date: Wed Mar 29 14:56:38 2017 +0200
Add GameSource.game_for_uri()
data/org.gnome.Games.desktop.in | 1 +
plugins/desktop/src/desktop-tracker-query.vala | 6 +++
plugins/libretro/src/Makefile.am | 1 +
plugins/libretro/src/libretro-error.vala | 6 +++
plugins/libretro/src/libretro-game-source.vala | 16 ++++++++
plugins/mame/src/mame-game-info.vala | 38 +++++++++++++++++-
plugins/mame/src/mame-game-uri-adapter.vala | 34 +++++++++++++++-
.../playstation/src/playstation-game-factory.vala | 4 ++
plugins/steam/src/steam-game-source.vala | 26 ++++++++++---
src/core/game-source.vala | 1 +
src/core/game-uri-adapter.vala | 3 +-
src/core/uri-game-factory.vala | 1 +
src/dummy/dummy-game-source.vala | 4 ++
src/dummy/dummy-game.vala | 2 +-
src/generic/generic-sync-game-uri-adapter.vala | 9 ++++-
src/generic/generic-uri-game-factory.vala | 20 +++++++---
src/tracker/mime-type-tracker-query.vala | 14 +++++++
src/tracker/tracker-game-source.vala | 12 ++++++
src/tracker/tracker-query.vala | 1 +
src/ui/application.vala | 41 +++++++++++++++++++-
20 files changed, 219 insertions(+), 21 deletions(-)
---
diff --git a/data/org.gnome.Games.desktop.in b/data/org.gnome.Games.desktop.in
index cfadc7f..c70e76b 100644
--- a/data/org.gnome.Games.desktop.in
+++ b/data/org.gnome.Games.desktop.in
@@ -9,3 +9,4 @@ Terminal=false
Type=Application
StartupNotify=true
Categories=GNOME;GTK;Player;Game;
+MimeType=application/vnd.nintendo.snes.rom;application/x-amiga-disk-format;application/x-atari-2600-rom;application/x-atari-7800-rom;application/x-cue;application/x-dc-rom;application/x-doom-wad;application/x-fds-disk;application/x-gameboy-color-rom;application/x-gameboy-rom;application/x-gamecube-rom;application/x-gamegear-rom;application/x-gba-rom;application/x-genesis-32x-rom;application/x-genesis-rom;application/x-love-game;application/x-mame-rom;application/x-n64-rom;application/x-neo-geo-pocket-rom;application/x-nes-rom;application/x-nintendo-ds-rom;application/x-pc-engine-rom;application/x-playstation-rom;application/x-saturn-rom;application/x-sega-cd-rom;application/x-sega-pico-rom;application/x-sg1000-rom;application/x-sms-rom;application/x-wii-rom;application/x-wii-wad;application/zip;
diff --git a/plugins/desktop/src/desktop-tracker-query.vala b/plugins/desktop/src/desktop-tracker-query.vala
index 174b44e..ccdfebd 100644
--- a/plugins/desktop/src/desktop-tracker-query.vala
+++ b/plugins/desktop/src/desktop-tracker-query.vala
@@ -39,6 +39,12 @@ private class Games.DesktopTrackerQuery : Object, TrackerQuery {
}
}
+ public Game game_for_uri (string uri) throws Error {
+ throw new GenericUriGameFactoryError.INVALID_URI ("Invalid URI: %s.", uri);
+
+ return new DummyGame ("Dummy desktop game");
+ }
+
public void process_uri (string uri) throws Error {
check_uri (uri);
diff --git a/plugins/libretro/src/Makefile.am b/plugins/libretro/src/Makefile.am
index a5dbff0..6bbb3f6 100644
--- a/plugins/libretro/src/Makefile.am
+++ b/plugins/libretro/src/Makefile.am
@@ -6,6 +6,7 @@ libgames_libretro_plugin_la_DEPENDENCIES = \
$(NULL)
libgames_libretro_plugin_la_SOURCES = \
+ libretro-error.vala \
libretro-game-source.vala \
libretro-icon.vala \
libretro-plugin.vala \
diff --git a/plugins/libretro/src/libretro-error.vala b/plugins/libretro/src/libretro-error.vala
new file mode 100644
index 0000000..a106ac7
--- /dev/null
+++ b/plugins/libretro/src/libretro-error.vala
@@ -0,0 +1,6 @@
+// This file is part of GNOME Games. License: GPLv3
+
+errordomain Games.LibretroError {
+ NOT_A_LIBRETRO_DESCRIPTOR,
+ NOT_A_GAME,
+}
diff --git a/plugins/libretro/src/libretro-game-source.vala b/plugins/libretro/src/libretro-game-source.vala
index 8432cd0..3ab9206 100644
--- a/plugins/libretro/src/libretro-game-source.vala
+++ b/plugins/libretro/src/libretro-game-source.vala
@@ -3,6 +3,22 @@
public class Games.LibretroGameSource : Object, GameSource {
private Game[] games;
+ public Game game_for_uri (string uri) throws Error {
+ if (!uri.has_prefix ("file:") || !uri.has_suffix (".libretro"))
+ throw new LibretroError.NOT_A_LIBRETRO_DESCRIPTOR ("This isn’t a Libretro core
descriptor: %s", uri);
+
+ var file = File.new_for_uri (uri);
+ if (!file.query_exists ())
+ throw new LibretroError.NOT_A_LIBRETRO_DESCRIPTOR ("This isn’t a Libretro core
descriptor: %s", uri);
+
+ var path = file.get_path ();
+ var core_descriptor = new Retro.CoreDescriptor (path);
+ if (!core_descriptor.get_is_game ())
+ throw new LibretroError.NOT_A_GAME ("This Libretro core descriptor doesn't isn’t a
game: %s", uri);
+
+ return game_for_core_descriptor (core_descriptor);
+ }
+
public async void each_game (GameCallback callback) {
if (games == null)
yield fetch_games ();
diff --git a/plugins/mame/src/mame-game-info.vala b/plugins/mame/src/mame-game-info.vala
index d8744bd..7e2dbb3 100644
--- a/plugins/mame/src/mame-game-info.vala
+++ b/plugins/mame/src/mame-game-info.vala
@@ -7,7 +7,39 @@ private struct Games.MameGameInfo {
public string id;
public string name;
- public static async HashTable<string, MameGameInfo?> get_supported_games () throws Error {
+ public static HashTable<string, MameGameInfo?> get_supported_games () throws Error {
+ if (supported_games != null)
+ return supported_games;
+
+ supported_games = new HashTable<string, MameGameInfo?> (str_hash, str_equal);
+
+ var bytes = resources_lookup_data ("/org/gnome/Games/plugins/mame/supported-games",
ResourceLookupFlags.NONE);
+ var text = (string) bytes.get_data ();
+
+ if (game_regex == null) {
+ // Data is of the form:
GAME[L](YEAR,NAME,PARENT,MACHINE,INPUT,CLASS,INIT,MONITOR,COMPANY,FULLNAME,FLAGS[,LAYOUT])
+ var simple = " *([^,]+) *";
+ var quoted = " *\" *(.*?) *\" *";
+ var pattern =
@"$simple,$simple,$simple,$simple,$simple,$simple,$simple,$simple,$quoted,$quoted,$simple(?:,$simple)?";
+ game_regex = new Regex ("^GAMEL?\\(" + pattern + "\\) *$");
+ }
+
+ foreach (var line in text.split ("\n")) {
+ MatchInfo match_info;
+ if (!game_regex.match (line, 0, out match_info))
+ continue;
+
+ var game_info = MameGameInfo() {
+ id = cleanup_string (match_info.fetch (2)), // NAME
+ name = cleanup_string (match_info.fetch (10)) // FULLNAME
+ };
+ supported_games[game_info.id] = game_info;
+ }
+
+ return supported_games;
+ }
+
+ public static async HashTable<string, MameGameInfo?> get_supported_games_async () throws Error {
if (supported_games != null)
return supported_games;
@@ -23,7 +55,7 @@ private struct Games.MameGameInfo {
var pattern =
@"$simple,$simple,$simple,$simple,$simple,$simple,$simple,$simple,$quoted,$quoted,$simple(?:,$simple)?";
game_regex = new Regex ("^GAMEL?\\(" + pattern + "\\) *$");
- Idle.add (get_supported_games.callback);
+ Idle.add (get_supported_games_async.callback);
yield;
}
@@ -38,7 +70,7 @@ private struct Games.MameGameInfo {
};
supported_games[game_info.id] = game_info;
- Idle.add (get_supported_games.callback);
+ Idle.add (get_supported_games_async.callback);
yield;
}
diff --git a/plugins/mame/src/mame-game-uri-adapter.vala b/plugins/mame/src/mame-game-uri-adapter.vala
index beea624..813ee4d 100644
--- a/plugins/mame/src/mame-game-uri-adapter.vala
+++ b/plugins/mame/src/mame-game-uri-adapter.vala
@@ -5,8 +5,8 @@ private class Games.MameGameUriAdapter : GameUriAdapter, Object {
private const string SPECIFIC_MIME_TYPE = "application/x-mame-rom";
private const string PLATFORM = "MAME";
- public async Game game_for_uri (string uri) throws Error {
- var supported_games = yield MameGameInfo.get_supported_games ();
+ public Game game_for_uri (string uri) throws Error {
+ var supported_games = MameGameInfo.get_supported_games ();
var file = File.new_for_uri (uri);
var game_id = file.get_basename ();
@@ -31,4 +31,34 @@ private class Games.MameGameUriAdapter : GameUriAdapter, Object {
return new GenericGame (title, icon, cover, runner);
}
+
+ public async Game game_for_uri_async (string uri) throws Error {
+ var supported_games = yield MameGameInfo.get_supported_games_async ();
+
+ var file = File.new_for_uri (uri);
+ var game_id = file.get_basename ();
+ game_id = /\.zip$/.replace (game_id, game_id.length, 0, "");
+
+ if (!supported_games.contains (game_id))
+ throw new MameError.INVALID_GAME_ID (_("Invalid MAME game id “%s” for “%s”."),
game_id, uri);
+
+ var uid_string = @"mame-$game_id".down ();
+ var uid = new GenericUid (uid_string);
+
+ var info = supported_games[game_id];
+ var title_string = info.name;
+ title_string = title_string.split ("(")[0];
+ title_string = title_string.strip ();
+ var title = new GenericTitle (title_string);
+
+ var icon = new DummyIcon ();
+ var cover = new LocalCover (uri);
+ var core_source = new RetroCoreSource (PLATFORM, { SEARCHED_MIME_TYPE, SPECIFIC_MIME_TYPE });
+ var runner = new RetroRunner (core_source, uri, uid, title);
+
+ Idle.add (this.game_for_uri_async.callback);
+ yield;
+
+ return new GenericGame (title, icon, cover, runner);
+ }
}
diff --git a/plugins/playstation/src/playstation-game-factory.vala
b/plugins/playstation/src/playstation-game-factory.vala
index 0979547..a7c033a 100644
--- a/plugins/playstation/src/playstation-game-factory.vala
+++ b/plugins/playstation/src/playstation-game-factory.vala
@@ -32,6 +32,10 @@ public class Games.PlayStationGameFactory : Object, UriGameFactory {
return file.query_exists ();
}
+ public Game game_for_uri (string uri) throws Error {
+ return new DummyGame ("Dummy playstation game");
+ }
+
public void add_uri (string uri) {
string disc_id;
diff --git a/plugins/steam/src/steam-game-source.vala b/plugins/steam/src/steam-game-source.vala
index 09db976..17cb43e 100644
--- a/plugins/steam/src/steam-game-source.vala
+++ b/plugins/steam/src/steam-game-source.vala
@@ -46,6 +46,18 @@ private class Games.SteamGameSource : Object, GameSource {
}
}
+ public Game game_for_uri (string uri) throws Error {
+ // TODO Check URI is file://
+ var file = File.new_for_uri (uri);
+ // if (!file.query_exists ())
+ // TODO throw Error
+
+ var path = file.get_path ();
+ string game_id;
+
+ return game_for_appmanifest_path (path, out game_id);
+ }
+
public async void each_game (GameCallback game_callback) {
if (games == null)
games = new HashTable<string, Game> (str_hash, str_equal);
@@ -76,7 +88,10 @@ private class Games.SteamGameSource : Object, GameSource {
var name = info.get_name ();
if (appmanifest_regex.match (name)) {
try {
- game_for_appmanifest_path (@"$directory/$name");
+ string game_id;
+ var game = game_for_appmanifest_path (@"$directory/$name", out game_id);
+ if (!(game_id in games))
+ games[game_id] = game;
Idle.add (this.game_for_file_info.callback);
yield;
@@ -87,7 +102,7 @@ private class Games.SteamGameSource : Object, GameSource {
}
}
- private void game_for_appmanifest_path (string appmanifest_path) throws Error {
+ private Game game_for_appmanifest_path (string appmanifest_path, out string id) throws Error {
var registry = new SteamRegistry (appmanifest_path);
var game_id = registry.get_data ({"AppState", "appid"});
/* The game_id sometimes is identified by appID
@@ -98,15 +113,14 @@ private class Games.SteamGameSource : Object, GameSource {
if (game_id == null)
throw new SteamError.NO_APPID (_("Couldn’t get Steam appid from manifest “%s”."),
appmanifest_path);
- if (game_id in games)
- return;
-
var title = new SteamTitle (registry);
var icon = new SteamIcon (game_id);
var cover = new SteamCover (game_id);
string[] args = { "steam", @"steam://rungameid/" + game_id };
var runner = new CommandRunner (args, false);
- games[game_id] = new GenericGame (title, icon, cover, runner);
+ id = game_id;
+
+ return new GenericGame (title, icon, cover, runner);
}
}
diff --git a/src/core/game-source.vala b/src/core/game-source.vala
index 1156b1d..9213d54 100644
--- a/src/core/game-source.vala
+++ b/src/core/game-source.vala
@@ -1,6 +1,7 @@
// This file is part of GNOME Games. License: GPL-3.0+.
public interface Games.GameSource : Object {
+ public abstract Game game_for_uri (string uri) throws Error;
public abstract async void each_game (GameCallback callback);
}
diff --git a/src/core/game-uri-adapter.vala b/src/core/game-uri-adapter.vala
index 65ae670..70a311e 100644
--- a/src/core/game-uri-adapter.vala
+++ b/src/core/game-uri-adapter.vala
@@ -1,5 +1,6 @@
// This file is part of GNOME Games. License: GPL-3.0+.
public interface Games.GameUriAdapter : Object {
- public abstract async Game game_for_uri (string uri) throws Error;
+ public abstract Game game_for_uri (string uri) throws Error;
+ public abstract async Game game_for_uri_async (string uri) throws Error;
}
diff --git a/src/core/uri-game-factory.vala b/src/core/uri-game-factory.vala
index b60b51c..e3f5896 100644
--- a/src/core/uri-game-factory.vala
+++ b/src/core/uri-game-factory.vala
@@ -1,5 +1,6 @@
public interface Games.UriGameFactory : Object {
public abstract bool is_uri_valid (string uri);
public abstract void add_uri (string uri);
+ public abstract Game game_for_uri (string uri) throws Error;
public abstract async void foreach_game (Games.GameCallback game_callback);
}
diff --git a/src/dummy/dummy-game-source.vala b/src/dummy/dummy-game-source.vala
index 6fc5573..e651e27 100644
--- a/src/dummy/dummy-game-source.vala
+++ b/src/dummy/dummy-game-source.vala
@@ -1,6 +1,10 @@
// This file is part of GNOME Games. License: GPL-3.0+.
private class Games.DummyGameSource : Object, GameSource {
+ public Game game_for_uri (string uri) throws Error {
+ return new DummyGame ("Dummy from URI");
+ }
+
public async void each_game (GameCallback callback) {
callback (new DummyGame ("Mines"));
callback (new DummyGame ("Sudoku"));
diff --git a/src/dummy/dummy-game.vala b/src/dummy/dummy-game.vala
index 69c3251..f4373a2 100644
--- a/src/dummy/dummy-game.vala
+++ b/src/dummy/dummy-game.vala
@@ -1,6 +1,6 @@
// This file is part of GNOME Games. License: GPL-3.0+.
-private class Games.DummyGame : Object, Game {
+public class Games.DummyGame : Object, Game {
private string _name;
public string name {
get { return _name; }
diff --git a/src/generic/generic-sync-game-uri-adapter.vala b/src/generic/generic-sync-game-uri-adapter.vala
index 5fcb585..186b038 100644
--- a/src/generic/generic-sync-game-uri-adapter.vala
+++ b/src/generic/generic-sync-game-uri-adapter.vala
@@ -9,7 +9,14 @@ public class Games.GenericSyncGameUriAdapter : GameUriAdapter, Object {
this.callback = (owned) callback;
}
- public async Game game_for_uri (string uri) throws Error {
+ public Game game_for_uri (string uri) throws Error {
return callback (uri);
}
+
+ public async Game game_for_uri_async (string uri) throws Error {
+ Idle.add (this.game_for_uri_async.callback);
+ yield;
+
+ return game_for_uri (uri);
+ }
}
diff --git a/src/generic/generic-uri-game-factory.vala b/src/generic/generic-uri-game-factory.vala
index b118248..28b47e2 100644
--- a/src/generic/generic-uri-game-factory.vala
+++ b/src/generic/generic-uri-game-factory.vala
@@ -4,19 +4,16 @@ public class Games.GenericUriGameFactory : Object, UriGameFactory {
private const uint HANDLED_URIS_PER_CYCLE = 5;
private GameUriAdapter game_uri_adapter;
- private UriTest? uri_validity_test;
+ private UriTest uri_validity_test;
private string[] uris;
- public GenericUriGameFactory (GameUriAdapter game_uri_adapter, UriTest? uri_validity_test = null) {
+ public GenericUriGameFactory (GameUriAdapter game_uri_adapter, UriTest uri_validity_test) {
this.game_uri_adapter = game_uri_adapter;
this.uri_validity_test = uri_validity_test;
this.uris = {};
}
public bool is_uri_valid (string uri) {
- if (uri_validity_test == null)
- return true;
-
return uri_validity_test.is_uri_valid (uri);
}
@@ -24,6 +21,13 @@ public class Games.GenericUriGameFactory : Object, UriGameFactory {
uris += uri;
}
+ public Game game_for_uri (string uri) throws Error {
+ if (!is_uri_valid (uri))
+ throw new GenericUriGameFactoryError.INVALID_URI ("Invalid URI: %s.", uri);
+
+ return game_uri_adapter.game_for_uri (uri);
+ }
+
public async void foreach_game (GameCallback game_callback) {
uint handled_uris = 0;
foreach (var uri in uris) {
@@ -32,7 +36,7 @@ public class Games.GenericUriGameFactory : Object, UriGameFactory {
continue;
try {
- Game game = yield game_uri_adapter.game_for_uri (uri);
+ Game game = yield game_uri_adapter.game_for_uri_async (uri);
game_callback (game);
}
catch (Error e) {
@@ -55,3 +59,7 @@ public class Games.GenericUriGameFactory : Object, UriGameFactory {
}
}
}
+
+public errordomain GenericUriGameFactoryError {
+ INVALID_URI,
+}
diff --git a/src/tracker/mime-type-tracker-query.vala b/src/tracker/mime-type-tracker-query.vala
index c68f282..429c088 100644
--- a/src/tracker/mime-type-tracker-query.vala
+++ b/src/tracker/mime-type-tracker-query.vala
@@ -24,6 +24,20 @@ public class Games.MimeTypeTrackerQuery : Object, TrackerQuery {
uri_game_factory.add_uri (uri);
}
+ public Game game_for_uri (string uri) throws Error {
+ // FIXME
+// if (!uri.has_prefix ("file:") || !uri.has_suffix (".libretro"))
+// throw new LibretroError.NOT_A_LIBRETRO_DESCRIPTOR ("This isn’t a Libretro core
descriptor: %s", uri);
+
+// var file = File.new_for_uri (uri);
+// if (!file.query_exists ())
+// throw new LibretroError.NOT_A_LIBRETRO_DESCRIPTOR ("This isn’t a Libretro core
descriptor: %s", uri);
+
+// var path = file.get_path ();
+
+ return uri_game_factory.game_for_uri (uri);
+ }
+
public async void foreach_game (GameCallback game_callback) {
yield uri_game_factory.foreach_game (game_callback);
}
diff --git a/src/tracker/tracker-game-source.vala b/src/tracker/tracker-game-source.vala
index 65681f0..e6ced9c 100644
--- a/src/tracker/tracker-game-source.vala
+++ b/src/tracker/tracker-game-source.vala
@@ -18,6 +18,17 @@ public class Games.TrackerGameSource : Object, GameSource {
queries += query;
}
+ public Game game_for_uri (string uri) throws Error {
+ foreach (var query in queries)
+ try {
+ return query.game_for_uri (uri);
+ }
+ catch (Error e) {
+ }
+
+ throw new TrackerError.NOT_A_GAME ("This isn’t a game: %s", uri);
+ }
+
public async void each_game (GameCallback game_callback) {
for (size_t i = 0 ; i < queries.length ; i++)
yield each_game_for_query (game_callback, queries[i]);
@@ -76,4 +87,5 @@ public class Games.TrackerGameSource : Object, GameSource {
public errordomain TrackerError {
FILE_NOT_FOUND,
+ NOT_A_GAME,
}
diff --git a/src/tracker/tracker-query.vala b/src/tracker/tracker-query.vala
index 69facd0..96ee38a 100644
--- a/src/tracker/tracker-query.vala
+++ b/src/tracker/tracker-query.vala
@@ -4,5 +4,6 @@ public interface Games.TrackerQuery : Object {
public abstract bool is_cursor_valid (Tracker.Sparql.Cursor cursor);
public abstract string get_query ();
public abstract void process_cursor (Tracker.Sparql.Cursor cursor);
+ public abstract Game game_for_uri (string uri) throws Error;
public abstract async void foreach_game (GameCallback game_callback);
}
diff --git a/src/ui/application.vala b/src/ui/application.vala
index ea4d6a6..a8556c2 100644
--- a/src/ui/application.vala
+++ b/src/ui/application.vala
@@ -9,7 +9,7 @@ public class Games.Application : Gtk.Application {
internal Application () {
Object (application_id: "org.gnome.Games",
- flags: ApplicationFlags.FLAGS_NONE);
+ flags: ApplicationFlags.HANDLES_OPEN);
}
construct {
@@ -106,6 +106,22 @@ public class Games.Application : Gtk.Application {
return @"$data_dir/medias";
}
+ protected override void open (File[] files, string hint) {
+ if (window == null)
+ activate ();
+
+ if (files.length == 0)
+ return;
+
+ var uri = files[0].get_uri ();
+ var game = game_for_uri (uri);
+
+ if (game != null)
+ window.run_game (game);
+ // else
+ // TODO Display an error
+ }
+
protected override void activate () {
Gtk.Settings.get_default ().gtk_application_prefer_dark_theme = true;
@@ -133,6 +149,29 @@ public class Games.Application : Gtk.Application {
return false;
}
+ private Game? game_for_uri (string uri) {
+ Game? game = null;
+
+ var register = PluginRegister.get_register ();
+ register.foreach_plugin_registrar ((plugin_registrar) => {
+ if (game != null)
+ return;
+
+ try {
+ var plugin = plugin_registrar.get_plugin ();
+ var source = plugin.get_game_source ();
+ if (source == null)
+ return;
+
+ game = source.game_for_uri (uri);
+ }
+ catch (Error e) {
+ }
+ });
+
+ return game;
+ }
+
internal async void load_game_list () {
GameSource[] sources = {};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]