After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 787489 - Add g_osx_app_info_get_for_id()
Add g_osx_app_info_get_for_id()
Status: RESOLVED OBSOLETE
Product: glib
Classification: Platform
Component: gio
2.53.x
Other Mac OS
: Normal normal
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2017-09-10 00:11 UTC by Jehan
Modified: 2018-05-24 19:47 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
gio: add function g_osx_app_info_get_for_id(). (2.46 KB, patch)
2017-09-10 00:11 UTC, Jehan
needs-work Details | Review

Description Jehan 2017-09-10 00:11:44 UTC
Created attachment 359451 [details] [review]
gio: add function g_osx_app_info_get_for_id().

Getting a MacOS Bundle from its known id is useful and use different code depending on the version of MacOS available. We do this in GIMP as well because GIMP needs to research the presence of third-party software (i.e. Darktable and Rawtherapee right now) to run them.

GLib already implemented the code logics with MacOS API and different code paths depending on MacOS version: get_bundle_for_id() in gio/gosxappinfo.c.
Unfortunately there is no public API so we can't use this from GIMP.

Therefore I propose:

> GOsxAppInfo * g_osx_app_info_get_for_id (const gchar *mac_bundle_id);

Cf. attached patch.
Comment 1 Philip Withnall 2017-09-11 09:15:57 UTC
Review of attachment 359451 [details] [review]:

I’m not sure how this can work, given that gosxappinfo.h is not installed as a public header. However, the code looks good to me, modulo the minor issues below.

::: gio/gosxappinfo.c
@@ +603,3 @@
+ * @mac_bundle_id: the CFBundleIdentifier from Info.plist.
+ *
+ * Searchs and returns the information of the application identified by

s/Searchs/Searches/

@@ +606,3 @@
+ * @mac_bundle_id. This string should be in reverse DNS format using
+ * only the Roman alphabet in upper and lower case, the dot and the
+ * hyphen, as specified by MacOS documentation. It identifies an

Could add a link to the relevant MacOS documentation here.

@@ +609,3 @@
+ * application uniquely in the system and is set in the file Info.plist.
+ *
+ * Returns: the #GOsxAppInfo or %NULL if no application was found with

Needs (nullable) and (transfer full) annotations.

@@ +613,3 @@
+ *
+ * Since: 2.54
+ **/

Use `*/` rather than `**/` (the latter is old-style gtk-doc format).
Comment 2 Philip Withnall 2017-09-11 09:16:39 UTC
Patrick, does this fit in with what you had in mind for the GOsxAppInfo API?
Comment 3 Jehan 2017-09-11 11:20:52 UTC
> I’m not sure how this can work, given that gosxappinfo.h is not installed as a public header.

Oh ok. Well could it be installed as a public header? Isn't the class GOsxAppInfo public itself? What about the interface GAppInfo, since we will probably just need a method from the interface?

For full disclosure, I have not tested the code. I don't have a MacOS machine so I can't. I know this simple code in my patch is meant to work because I basically copied it from our own code (and a MacOS bug reporter confirmed it worked in bug 787326, comment 4), but if that's not a public header, that's obviously not usable by GIMP.

It also means I may have overlooked other issues. Feel free to make the relevant changes to my patch. :-)

> Could add a link to the relevant MacOS documentation here.

The link is a bit long, but if you want to add it, here it is:
https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-102070

> s/Searchs/Searches/
> […]
> Needs (nullable) and (transfer full) annotations.
> […]
> Use `*/` rather than `**/` (the latter is old-style gtk-doc format).

Ok.

> Patrick, does this fit in with what you had in mind for the GOsxAppInfo API?

Another question for Patrick. ;-)
In the end, we need to get the executable path of the bundle, which will allow us to build our own command line (GIMP calls darktable/RawTherapee, where photographers can do their magic and the third party returns a file to GIMP on closure, hence it's just launching the app).

At first glance, I assumed once I have a GAppInfo, I could use g_app_info_get_executable(), but looking closer now, it looks like it would return only the file name, not the full path, am I right?
I guess the right one would be g_app_info_get_commandline() but it's not implemented for GOsxAppInfo.

This is how we get the executable path currently in GIMP:
https://git.gnome.org/browse/gimp/tree/plug-ins/file-raw/file-raw-utils.c#n79

From a NSBundle, from what I gathered on the web, it could even be just a oneliner:

> NSString *path = [bundle executablePath];

(but once again, untested. MacOS code is a little like flying blind here)

Basically we just want a GLib API to get the executable path of an installed application for us to create our own command lines. I see most of the code is already inside glib, simply not public. So if we could avoid code duplication, we'd be happy. :-)
Comment 4 Jehan 2017-09-11 11:23:38 UTC
s/hence it's just launching the app/hence it's *not* just launching the app/
Comment 5 Patrick Griffis (tingping) 2017-09-12 19:49:38 UTC
(In reply to Philip Withnall from comment #2)
> Patrick, does this fit in with what you had in mind for the GOsxAppInfo API?

This seems like a reasonable addition.

(In reply to Jehan from comment #3)
> > I’m not sure how this can work, given that gosxappinfo.h is not installed as a public header.
> 
> Oh ok. Well could it be installed as a public header?

The only problem is applications have to manually check for OSX specific headers since we don't offer something like G_OS_UNIX for OSX atm.

Other than that it is should be acceptable as public API.

> Another question for Patrick. ;-)
> In the end, we need to get the executable path of the bundle, which will
> allow us to build our own command line (GIMP calls darktable/RawTherapee,
> where photographers can do their magic and the third party returns a file to
> GIMP on closure, hence it's just launching the app).
> 
> At first glance, I assumed once I have a GAppInfo, I could use
> g_app_info_get_executable(), but looking closer now, it looks like it would
> return only the file name, not the full path, am I right?
> I guess the right one would be g_app_info_get_commandline() but it's not
> implemented for GOsxAppInfo.
> 
> This is how we get the executable path currently in GIMP:
> https://git.gnome.org/browse/gimp/tree/plug-ins/file-raw/file-raw-utils.c#n79
> 
> From a NSBundle, from what I gathered on the web, it could even be just a
> oneliner:
> 
> > NSString *path = [bundle executablePath];
> 
> (but once again, untested. MacOS code is a little like flying blind here)
> 
> Basically we just want a GLib API to get the executable path of an installed
> application for us to create our own command lines. I see most of the code
> is already inside glib, simply not public. So if we could avoid code
> duplication, we'd be happy. :-)

Well `g_osx_app_info_get_filename()` returns the path to the bundle. You normally don't need the executable name and you just launch by bundle I believe.
Comment 6 Patrick Griffis (tingping) 2017-09-12 20:03:27 UTC
Also before we make this header public maybe `g_osx_app_info_get_filename()` should stop just prepending `file://` at the front and it should instead be converted to a uri where it is used internally.
Comment 7 Philip Withnall 2017-09-15 10:32:56 UTC
(In reply to Patrick Griffis (tingping) from comment #5)
> (In reply to Jehan from comment #3)
> > > I’m not sure how this can work, given that gosxappinfo.h is not installed as a public header.
> > 
> > Oh ok. Well could it be installed as a public header?
> 
> The only problem is applications have to manually check for OSX specific
> headers since we don't offer something like G_OS_UNIX for OSX atm.
> 
> Other than that it is should be acceptable as public API.

We’d need a gio-macos-2.0.pc library, just like we have gio-unix-2.0.pc and gio-windows-2.0.pc.

We might want to switch to a `g_macos_*` prefix rather than `g_osx_`, since Apple seem to be rebranding in that direction (see https://en.wikipedia.org/wiki/MacOS). That would mean renaming GOsxAppInfo to GMacosAppInfo, which is a tiny API break since it was exposed in the type system (but not in any public headers). I’d like feedback from MacOS people about whether that would break things for them before we do that. If it would break things, we should stick with `g_osx_` as a prefix.

Matthias/Emmanuele, what do you think about that (new library and prefix change)?
Comment 8 Emmanuele Bassi (:ebassi) 2017-09-15 10:48:27 UTC
(In reply to Philip Withnall from comment #7)
> (In reply to Patrick Griffis (tingping) from comment #5)
> > (In reply to Jehan from comment #3)
> > > > I’m not sure how this can work, given that gosxappinfo.h is not installed as a public header.
> > > 
> > > Oh ok. Well could it be installed as a public header?
> > 
> > The only problem is applications have to manually check for OSX specific
> > headers since we don't offer something like G_OS_UNIX for OSX atm.
> > 
> > Other than that it is should be acceptable as public API.
> 
> We’d need a gio-macos-2.0.pc library, just like we have gio-unix-2.0.pc and
> gio-windows-2.0.pc.
> 
> We might want to switch to a `g_macos_*` prefix rather than `g_osx_`, since
> Apple seem to be rebranding in that direction (see
> https://en.wikipedia.org/wiki/MacOS). That would mean renaming GOsxAppInfo
> to GMacosAppInfo, which is a tiny API break since it was exposed in the type
> system (but not in any public headers). I’d like feedback from MacOS people
> about whether that would break things for them before we do that. If it
> would break things, we should stick with `g_osx_` as a prefix.
> 
> Matthias/Emmanuele, what do you think about that (new library and prefix
> change)?

I don't have any issues with a new library, after all we already have sub-libraries for Windows and *nix-like systems, like you said.

I also don't have any problem with a rename of internal types to a different name. Personally, I like the `g_macos_` namespace, but we have a bunch of ancillary code that uses `*_osx_*` here and there — like: https://git.gnome.org//browse/gtk-osx. The bundler for GTK+ apps uses `gtk-mac-` as a prefix, though.
Comment 9 Philip Withnall 2017-09-15 11:15:22 UTC
(In reply to Emmanuele Bassi (:ebassi) from comment #8)
> I also don't have any problem with a rename of internal types to a different
> name. Personally, I like the `g_macos_` namespace, but we have a bunch of
> ancillary code that uses `*_osx_*` here and there — like:
> https://git.gnome.org//browse/gtk-osx. The bundler for GTK+ apps uses
> `gtk-mac-` as a prefix, though.

Those look like build scripts rather than C API. Do we have any other C APIs (not in GLib/GIO) which use `*_osx_*` naming? That would put a bit of a damper on things. I’m happy for GLib’s API naming to not be consistent with build scripts in gtk-osx or the GTK+ Mac bundler.
Comment 10 John Ralls 2017-09-15 14:44:40 UTC
(In reply to Emmanuele Bassi (:ebassi) from comment #8)
 
> I also don't have any problem with a rename of internal types to a different
> name. Personally, I like the `g_macos_` namespace, but we have a bunch of
> ancillary code that uses `*_osx_*` here and there — like:
> https://git.gnome.org//browse/gtk-osx. The bundler for GTK+ apps uses
> `gtk-mac-` as a prefix, though.


Heh. It's gtk-osx because back when Imendio wrote it "macos" could mean the entirely different System 9. It's just a wrapper around jhbuild and some modulesets. 

The project that integrates GtkMenus into the Mac menu bar is gtk-mac-integration (which also offers bundle-finding code, BTW) but it uses gtkosx_application for its namespace. (gtkosx instead of gtk_osx because gobject-introspection complained that the gtk namespace was already taken). I'm not at all opposed to changing it to gtkmac_application (or gtkcocoa_application) if we decide to change to a consistent set of namespaces across Gnome.

Besides gosxappinfo and gosxcontenttype Gio also has gcocoanotification and gnextstepsettingsbackend.
Comment 11 John Ralls 2017-09-15 14:59:35 UTC
(In reply to Patrick Griffis (tingping) from comment #5)

> Well `g_osx_app_info_get_filename()` returns the path to the bundle. You
> normally don't need the executable name and you just launch by bundle I
> believe.

That depends on how you launch it. If you want to fork & exec then you need the actual binary, but that will bypass Info.plist and, if the bundle uses a launcher script to set up the environment, shell-script processing. LaunchServices provides LSOpenFSRef() to open application bundles but that doesn't get you a child process.
Comment 12 Jehan 2018-02-02 14:24:19 UTC
(In reply to Patrick Griffis (tingping) from comment #5)
> > Basically we just want a GLib API to get the executable path of an installed
> > application for us to create our own command lines. I see most of the code
> > is already inside glib, simply not public. So if we could avoid code
> > duplication, we'd be happy. :-)
> 
> Well `g_osx_app_info_get_filename()` returns the path to the bundle. You
> normally don't need the executable name and you just launch by bundle I
> believe.

As I said, we are running it from GIMP for specific actions. We don't just "run and forget". We run with specific CLI options, and we wait for the result to resume our processing in GIMP. This is some workflow we have worked on with darktable and RawTherapee developers: people open their RAW image in GIMP, which opens their favorite raw developer (either darktable or RawTherapee), where they make the initial raw processing, and when done, it is automatically sent back into GIMP for further processing.

So: can we add options when we launch by bundle? If yes, it's ok. If not, then we need the executable path.
For instance, we need to run something like:

> darktable --width XX --height YY --luacmd 'some lua command'

Therefore we have 2 needs: (1) discover whether the app is present (2) if present, we want to run it by adding specific CLI options.
Comment 13 John Ralls 2018-02-02 16:42:18 UTC
The current guidance for opening applications is https://developer.apple.com/documentation/coreservices/1441986-lsopenfromurlspec?language=objc

It can take launch parameters, but it appears that the receiving app needs to know how to unpack them rather than that they're passed in as unix-style command-line options.
Comment 14 John Ralls 2018-02-04 20:21:02 UTC
I see two issues here: First, how many other GIO-based applications would use MacOS-specific functions and depend on other bundled applications in such a way that they need to get their executable paths?

Second, does it really make sense for GIO to expose platform-specific API? The whole point of GIO is to abstract a platform-independent API. Shouldn't the proposal be to implement g_app_info_get_for_id() and g_app_info_get_executable_path() for all platforms?
Comment 15 Jehan 2018-02-04 21:08:12 UTC
(In reply to John Ralls from comment #13)
> The current guidance for opening applications is
> https://developer.apple.com/documentation/coreservices/1441986-
> lsopenfromurlspec?language=objc
> 
> It can take launch parameters, but it appears that the receiving app needs
> to know how to unpack them rather than that they're passed in as unix-style
> command-line options.

Well… having *also* a function for doing things the macOS way would be good too, but it is better to have first a generic "running a command line with options" method. The generic CLI call may not be the "recommanded Apple way" but it has the interesting of working everywhere, even on macOS; and it allows developers to not have to do too much specific per-platform coding. In our specific example, if we only had the bundle method, I'm not sure if darktable and RawTherapee developers will be in a hurry to develop macOS specific code (or even if they will be interested, or *when* they would do it according to priorities) since we have a generic code which works.

I mean: we have working code and that's how it works right now.

(In reply to John Ralls from comment #14)
> I see two issues here: First, how many other GIO-based applications would
> use MacOS-specific functions and depend on other bundled applications in
> such a way that they need to get their executable paths?

Any GIO application which has a macOS port and wants to communicate with other applications. That's a specific use case and not all software out there, for sure. That's ours at GIMP, darktable and rawtherapee (and actually a few other RAW software already made their GIMP-RAW plug-in to communicate with GIMP, I heard).

> Second, does it really make sense for GIO to expose platform-specific API?
> The whole point of GIO is to abstract a platform-independent API. Shouldn't
> the proposal be to implement g_app_info_get_for_id() and
> g_app_info_get_executable_path() for all platforms?

Of course, you are entirely right: ideally we want the most generic functions as possible. Playing with #ifdef is not funny.

Nevertheless the specific use case here was only that Linux, macOS and Win32 used different logics. Linux researches the other applications through the $PATH. On macOS, I guess $PATH would be possible too, but they mostly have this bundle id stuff. On Win32, I guess you can also do some $path search as well, though you can also look up the registry for software which adds key there (it seems darktable does so, not RawTherapee for instance).

Basically it's a bit of a mess. And so what would `g_app_info_get_for_id()` mean for Win32, Linux and BSD? They don't have the concept of "ID" of an application. So in the end, that's a function which would work only for macOS, hence the `g_osx_app_*()` naming. You can name it generically if you want, it doesn't make the concept of application ID generic.

`g_app_info_get_executable_path()` on the other hand, why not, using various parameters. Here is how we do this in GIMP for instance:

> char *
> file_raw_get_executable_path (const gchar *main_executable,
>                               const gchar *suffix,
>                               const gchar *env_variable,
>                               const gchar *mac_bundle_id,
>                               const gchar *win32_registry_key_base,
>                               gboolean    *search_path)

https://git.gnome.org/browse/gimp/tree/plug-ins/file-raw/file-raw-utils.c#n36

Then it's a single call, which contains all the specificities of each OS as parameters (but at least the calling code is generic and would not need #ifdef).
Comment 16 John Ralls 2018-02-04 23:27:38 UTC
(In reply to Jehan from comment #15)
> The generic CLI call may not be the "recommanded Apple way"

Not so much the "recommended Apple way" as the way that Apple's LaunchServices API works. That was to answer "can we add options when we launch by bundle"? from your comment 12. Executive summary: Yes, but only with a bit of work both on your part and on the part of the darktable and RawTherapee development teams to implement the LaunchServices way of passing options.

> > I see two issues here: First, how many other GIO-based applications would
> > use MacOS-specific functions and depend on other bundled applications in
> > such a way that they need to get their executable paths?
> 
> Any GIO application which has a macOS port and wants to communicate with
> other applications. That's a specific use case and not all software out
> there, for sure. That's ours at GIMP, darktable and rawtherapee (and
> actually a few other RAW software already made their GIMP-RAW plug-in to
> communicate with GIMP, I heard).

No, the code you're proposing for specifically addresses bundled applications with an CFBundleIdentifier in its Info.plist. Otherwise get_bundle_for_id returns NULL. An application running from the command line won't have a bundle id.

> 
> > Second, does it really make sense for GIO to expose platform-specific API?
> > The whole point of GIO is to abstract a platform-independent API. Shouldn't
> > the proposal be to implement g_app_info_get_for_id() and
> > g_app_info_get_executable_path() for all platforms?
> 
> Of course, you are entirely right: ideally we want the most generic
> functions as possible. Playing with #ifdef is not funny.
> 
> Nevertheless the specific use case here was only that Linux, macOS and Win32
> used different logics. Linux researches the other applications through the
> $PATH. On macOS, I guess $PATH would be possible too, but they mostly have
> this bundle id stuff. On Win32, I guess you can also do some $path search as
> well, though you can also look up the registry for software which adds key
> there (it seems darktable does so, not RawTherapee for instance).
> 
> Basically it's a bit of a mess. And so what would `g_app_info_get_for_id()`
> mean for Win32, Linux and BSD? They don't have the concept of "ID" of an
> application. So in the end, that's a function which would work only for
> macOS, hence the `g_osx_app_*()` naming. You can name it generically if you
> want, it doesn't make the concept of application ID generic.
> 
> `g_app_info_get_executable_path()` on the other hand, why not, using various
> parameters. Here is how we do this in GIMP for instance:
> 
> > char *
> > file_raw_get_executable_path (const gchar *main_executable,
> >                               const gchar *suffix,
> >                               const gchar *env_variable,
> >                               const gchar *mac_bundle_id,
> >                               const gchar *win32_registry_key_base,
> >                               gboolean    *search_path)
> 
> https://git.gnome.org/browse/gimp/tree/plug-ins/file-raw/file-raw-utils.c#n36
> 
> Then it's a single call, which contains all the specificities of each OS as
> parameters (but at least the calling code is generic and would not need
> #ifdef).

That's more or less what I was thinking of, yes. Maybe even another level of abstraction: g_app_info_launch_app_with_arguments(char* app_id,  gstringv* args). That doesn't avoid #ifdefs because you have to provide a registry key for MSWin, a CFBundleIdentifier for MacOS, and I suppose a path for X11/Wayland.
Comment 17 Jehan 2018-02-05 01:17:11 UTC
(In reply to John Ralls from comment #16)
> (In reply to Jehan from comment #15)
> > > char *
> > > file_raw_get_executable_path (const gchar *main_executable,
> > >                               const gchar *suffix,
> > >                               const gchar *env_variable,
> > >                               const gchar *mac_bundle_id,
> > >                               const gchar *win32_registry_key_base,
> > >                               gboolean    *search_path)
> > 
> > https://git.gnome.org/browse/gimp/tree/plug-ins/file-raw/file-raw-utils.c#n36
> > 
> > Then it's a single call, which contains all the specificities of each OS as
> > parameters (but at least the calling code is generic and would not need
> > #ifdef).
> 
> That's more or less what I was thinking of, yes. Maybe even another level of
> abstraction: g_app_info_launch_app_with_arguments(char* app_id,  gstringv*
> args). That doesn't avoid #ifdefs because you have to provide a registry key
> for MSWin, a CFBundleIdentifier for MacOS, and I suppose a path for
> X11/Wayland.

Well… it doesn't avoid #ifdef in implementation in glib/GIO code of course, but on the application code, we could just have a single common call with all the various identifiers for all platforms and no #ifdef. :-)

Be careful about removing a step with your level of abstraction, if you get a slightly different use case, this is the best way to make your function useless and having to reimplement it yourself. Not everyone wants to run an application the same way. You may want to run and forget, run and wait for the output while freezing the app, run and not freeze the app yet set a callback for when it's done, run and control communication pipes, etc.
So it is much much better to just have a g_app_info_get() (or call it whatever you want), then additional functions to run the GAppInfo in the various ways.
Comment 18 GNOME Infrastructure Team 2018-05-24 19:47:44 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glib/issues/1287.