Out of a mojito bar in South Beach with a lobotomised plastic picnic spoon and a crew of control freaks.
3.22 is here
GNOME Photos has again taken significant strides forward – just like we did six months ago in 3.20. One of the big things that we added this time was sharing. This nicely rounds out our existing online acccounts integration, and complements the work we did on editing six months ago.
Sharing is an important step towards a more tightly integrated online account experience in GNOME. We have been interested in a desktop-wide sharing service for some time. With Flatpak portals becoming a reality, I hope that the sharing feature in Photos can be spun off into a portal for GNOME.
Thanks to Umang Jain, our GSoC intern this summer for working on sharing.
We overhauled a lot of hairy architectural issues, which will let us have nicer overview grids in the near future. Alessandro created a Flatpak. This means that going forward, you can easily try out the nightly builds of Photos thanks to the Flatpak support in GNOME Software 3.22.
Thanks to Kalev Lember for the wonderful screenshot.
I think that we are reaching a point where we can recommend Photos to a wider group of users. With editing and sharing in place, we have filled some of the bigger gaps in the user experience that we want to offer. Yes, there are some missing features and rough edges that we are aware of, so we we are going to spend the next six months addressing the ones that are most important. You can look at our roadmap for the full picture, but I am going to highlight a few.
Better overview grids (GNOME #690623)
We have been using GtkIconView to display the grid of thumbnails that we call the overview. GtkIconView has been around for a long while, but it has some issues – both visual and performance. Therefore, we want to replace it with GtkFlowBox so (a) that the application remains responsive while we are populating the grid, and (b) we can have really pretty visuals.
Eventually, we want this:
Import from device (GNOME #751212)
This is one of the biggest missing features, in my opinion. We really need a way to import content from removable devices and cameras that doesn’t involve mucking around with files and directories.
Petr Stetka has already started working on this, but I am sure he will appreciate any help with this.
More sharing (GNOME #766031)
Last but not the least, I definitely like showing off on Facebook and so do you! So I want to add a Facebook share-point and possibly a few more.
Come, join us
If any of this interests you, then feel free to jump right in. We have a curated list of newcomer bugs and a guide for those who are relatively new. If you are an experienced campaigner, you can look at the roadmap for more significant tasks.
For any help, discussions or general chitchat, #photos on GIMPNet is the place to be.
I spent some time today documenting how to debug various problems with online account integration in GNOME. It is also linked from the main GNOME Online Accounts wiki page. So, you can find it via the usual click-stream and don’t need to rely on this blog.
It is still basic. I want to expand it further to cover how to debug specific integration points. For example, issues with mounting Google Drive in Nautilus, or some breakage involving Kerberos. Anyway, it’s a start and I am quite happy to have one less thing on my TODO list. Sometimes, things in GNOME seem like a maze of hidden D-Bus daemons, known only to the initiated. Hopefully, this will make it more approachable.
Oh, and don’t shy away from editing it. It’s a Wiki!
MALLOC_PERTURB_ is a useful thing. If you are developing on glibc-based systems, I encourage you to put this snippet in your ~/.bash_profile:
MALLOC_PERTURB_=$(($RANDOM % 255 + 1))
I have been using it for the last six years on all my computers (3 laptops running every Fedora x86_64 build released since then), and while things haven’t exploded, it has helped uncover the odd bug every once in a while. One such occasion presented itself this week.
I was busy following Ondrej’s hint, debugging why Eye of GNOME was taking so long to open a file from ownCloud. Imagine my shock when it would just crash after showing the window. The same optimization was working just fine on the gnome-3-18 branch, while master was crashing even without any changes. How could that happen? Obviously, while it was failing for me, it was working fine for all those who run unstable GNOME versions via jhbuild, gnome-continous, Fedora rawhide, etc.. Otherwise we would have been debugging this crash, and not a performance issue.
I guess, most of them didn’t have MALLOC_PERTURB_.
Here is another such story.
In case you were wondering, there is already an update on its way to Fedora 24 address the crash.
Now that we are in the middle of the various freezes in preparation for GNOME 3.20, and eventually Fedora 24, it is a good time to talk about some of the things that happened over the last six months. You might have noticed that a bunch of GNOME applications received significant improvements this cycle. If you haven’t, then go ahead and check out the new hotness in Documents, Maps (it is awesome), Nautilus (or Files), Calendar and News.
It wasn’t any different for Photos.
Non-destructive editing has landed this cycle. It was one of the high level plans that Allan had written about last summer. While Photos will never be a fully featured professional image editor like Darktable or GIMP, I believe this plugs an important gap for those looking for a simpler option.
Internally, it is based on GEGL (which explains the cryptic title of the teaser in November). For those who are not in the know, GEGL is a graph based image processing framework that is going to be new image processing core of GIMP. For us, it means that we benefit from the plethora of operations that are built into GEGL and the many more that are being ported over from GIMP; and we get things like non-destructive editing, higher bit-depths, handling larger than RAM images, multiple pixel formats and many more advanced features for free.
In the spirit of non-destructive editing, we never touch the original images. However, you can export the result of the edits out of the application through.
I expect the export functionality to evolve as we integrate sharing into Photos — uploading to online accounts, attaching to an email or sending to a USB stick. Exporting entire albums or a selection of multiple images is also something that we will be adding in the near future.
When New Heroes Emerge
At this point, I must mention the amazing work done by two new GNOME contributors — Rafael Fonseca and Umang Jain. It does feel good to be reviewing more patches, even if I don’t time to write that many myself.
Thanks to Rafael we now have the usual undo notification for editing. This is typical of GNOME 3 applications — instead of asking for confirmation, we try to make the actions as reversible as possible. He also worked on export and cleaned up our selection toolbar code.
Umang did a lot of work on the crop palette, metadata handling, improvements to undo and gave us this export notification.
Last, but not the least, along with many other GNOME applications we added a help overlay to show our keyboard shortcuts. You can either access it from the application menu, or press Ctrl+? or Ctrl+F1.
There is a lot to do. So come join us in #photos on the GIMPNet IRC network if you want to join the fun.
I spent most of the previous week attending the Content Apps Hackfest in Madrid. The agenda was to work on GNOME’s content applications: Documents, Files, Music, Photos and Videos; to identify missing features and sore points; and raise the standard of the overall content experience in GNOME. Of these, I focused mainly on Documents and Photos.
The first day was spent discussing high-level goals:
- Previews – should the content applications take over the role played traditionally by Evince and Eye of GNOME?
- Status and plans about sharing. We are still waiting for a platform-wide sharing framework, but since it is a crucial feature for some of the applications, it has become a case of perfection being the enemy of good.
- Porting away from GtkIconView to GtkFlowBox. GtkIconView has some very visible problems – it becomes terribly slow when the images are updated; the grid’s content doesn’t re-flow when the size of the widget changes leading to an awkward gutter appearing on the side; cannot pack any GTK+ widget into a GtkCellRenderer.
I set up a live Google Hangouts stream on my laptop to let those who couldn’t attend in person to join us remotely. With Andreas’ help, I fixed the HiDpi breakage in Photos’ cropping tool, Bastien fired some new LibreOffice builds, while the other Bastian revamped Documents’ wiki page.
The second day started with breakfast in Florian’s flat. It was less chatty with people quietly hacking away, presumably, to rest their tired throats. Bastien picked up Pranav’s patches to integrate LOKDocView widget in Documents. I worked a bit on polishing rough edges in Photos’ editing code, and tried to keep up with the endless stream of patches from Alessandro and Umang.
Discussions picked up a bit on the third and final day. Allan spent a lot of time talking to the developers of each application. UX reviews were done, new designs were made, and future plans were sketched out. I spent some time with him working on a roadmap for Photos. We are still cleaning up our rough notes and transferring them to the wiki, but I think it is good enough for others to take a look. Øyvind paid us a surprise visit, and we grabbed the opportunity for some impromptu chat.
TL;DR: If you are using any GFile API that can create a new file or directory, then please take care of “volatile” paths. Look at standard::is-volatile, g_file_output_stream_query_info and g_file_query_info. Read further if you don’t trust me, or if you develop file management software.
Like other cloud storages, Drive is database-based. Every file or folder is identified by an opaque, server generated, immutable, blob (say “0B9J_DkziBDRFTj1TRWLPam9kbnc”), and has a human-readable title that can be displayed in the user interface (say “Summer Vacation”). This is unlike POSIX filesystems where a file is identified by its path and, barring encoding issues, the basename of that path is its name. ie., the name of the file “/home/alice/Summer\ Vacation” is “Summer Vacation”. Sounds like an innocuous distinction at first, but this is at the heart of the issue.
Let’s look at a few operations to get a feel for this.
mv /home/alice/foo /home/alice/bar
We need the paths to carry out the operation and once successfully finished, the file’s path changes. Since files are identified by their paths, the operation would fail if there existed another file called “bar” in the same location.
set_title (id_of_foo, bar)
We only need the identifier (or ID) and the new title for the operation and once successfully finished, the title changes but the ID remains the same. Since IDs are unique and immutable, you can have two files with the same title in the same location. That’s a bit strange, you might think, but not so much.
Creating a New File
If you want a file named “foo” in a certain location, barring encoding issues, you ask for a path that has “foo” appended to the path of the location. It will work as long as there isn’t another “foo” in the same location.
create_file (id_of_parent_folder, foo) → id_of_new_file
Notice that we cannot specify the ID of the new file. We provide a title and the server generates the ID for it. Again, there is no restriction on having two files with the same title in the same location. This is where it starts getting weird.
GIO and GVfs
The file handling APIs in GIO are based on the POSIX model, with some room to accommodate minor diversions. They are ill-equipped to deal with a case like this.
As a quick aside, both MTP and PTP are somewhat similar in this regard. Both use IDs to refer to objects (think of them as files) stored on the phone or camera, and we have backends implementing them in GVfs. These backends construct POSIX-like paths using the human-readable titles of the files, and have an internal cache mapping IDs to paths and vice-versa. Easy enough, but there are two important differences:
- MTP allows no parallelism. You can only perform one operation at a time — a new one won’t start until the earlier has finished. So, the GVfs backend can assume complete control over the storage. Google Drive, on the other hand, is massively parallel. You might be modifying it via GVfs, via a web browser, from a different computer, or someone might be sharing something to you from yet another computer. It is better to rely on the server generated IDs to identify files as much as possible, and let the server worry about keeping the data consistent.
- MTP and PTP are usually backed by a traditional filesystem on the device. eg., FAT12, FAT16, FAT32, exFAT or ext3. Therefore the issue of duplicate titles doesn’t arise.
So, how do we deal with this?
Assuming that we are only doing read-only operations, the URIs used by GVfs’ Google Drive backend look like:
The backend has its own scheme, the account is mentioned, and the path is made up of identifiers. Quite easy. The server doesn’t care about having a POSIX-like path, but we create one to fit into GIO’s POSIX-like world view.
These IDs are decidedly ugly and unreadable, so we use the standard::display-name attribute to tag them with the titles. If you run g_file_query_info on one of these URIs, you will get the ID as the standard::name and the title as the standard::display-name. Thus, the user won’t encounter any ugliness unless she deliberately went looking for it.
It gets complicated when we go beyond read-only access.
Let’s look at creating new files again. Since the GIO and GVfs APIs are designed around the POSIX model, a GVfs backend receives the request as:
Even though the application thinks that it has created a new file named “some-title” inside “/id1/id2” that can be accessed by the path “/id1/id2/some-title”, the new file’s identifier is not “some-title”. It is whatever the server generated for us, say “id3”. If the application has to carry on the illusion of accessing the file as “/id1/id2/some-title”, then the backend has to map this “fake” path back to “/id1/id2/id3”; and this has to happen somewhat recursively because if we are copying a directory, then multiple elements in the file path can be “fake”. eg., “/id1/id2/title-of-subdir/title-of-file”, and so on.
We call these volatile paths. These are identified by the standard::is-volatile attribute and you can use standard::symlink-target to find the actual ID that it maps to. It is recommended that applications map volatile paths to the real IDs as soon as possible because the mapping can break if a parallel operation changes the title of the file.
In the specific case where you have created a new file and writing to it through a GFileOutputStream, then it is better to use g_file_output_stream_query_info instead of g_file_query_info. The output stream knows exactly which file it is writing to, and doesn’t have to do the mapping based on the volatile path, which could fail if the contents of the Drive changed out of band.