Sunday, June 23, 2013

Sound Recorder: Update Two

I spent the past week working mainly on backend code for the listview. I found that most of my effort this week went to figuring out how the necessary classes functioned.

To start with, last week I stole some code from GNOME Shell and tried to dissect it so I could see how it dealt with things like scope within closures, and callbacks. When I code in Java, I generally use an IDE. When I was first learning concepts (like loops, which were difficult to understand at first, and recursion) I generally put the code into the IDE, inserted a break point, and stepped through the code so I could see how the variables changed values. Replicating that process with the terminal, with GJS, has been interesting: I end up inserting logging into my code so I can easily match my debug output to my code, and then read them side by side to determine how execution is happening.This is not quite as user-friendly as an IDE GUI: a single run of the application with debug set to 6 yields ~33,000 lines of output. So, yeah. Usually I set debug to 3 :)

After reading some code over and over (mainly selections.js from Documents, but also random blog posts on the internet, Stack Overflow, and whatever else I could find), I could understand the Shell code enough to be able to re-write it. After that I moved on to writing the gstreamer code.

Last week Bastien pointed me to some Gst.Discoverer code in Totem. Again, what I accomplished was getting the basic structure set up and functioning so I can fill in details (such as which tags to discover) as I go along.

I also started to add a basic playback functionality and spent some time being driven insane by a bug. It turned out that I had a bug in the "Record" toggle button which was setting the pipeline state to paused when the button was inactive (that is, when I pressed "Stop"), so I never received eos messages on the Gst.Bus and consequently never set the pipeline state to null.

This coming week I am planning to work on an object that stores the uris and dates that I retrieve from the GFileEnumerator. Since I only want to load fifty files at a time into the listview, I also need to implement a sensible sorting algorithm to sort by most recent before I store the information (although I think GFileEnumerator does this already). I'm planning to read the code for Rhythmbox in tomorrow to see if it is helpful; so far most of the applications I've read through seem to use database queries for this, rather than implementing it by hand. Anyway, I think it will be an interesting problem, and hopefully I can write a decent solution :) After it is finished, I will add a "load file" object to play.js and a "load more" object to listview.js.

Saturday, June 15, 2013

Sound Recorder, Update One

When I wrote out my initial plan for the sound recorder, I decided to start with the backend. I haven't used GStreamer before. I generally prefer to put the steepest part of the learning curve first, since I find that the bast way to learn any coding skill is to spend some time drowning in deep water (well... or even shallow water. I'm pretty sure I could manage the drowning at first part no matter what coding skill I'm learning).

So I have indeed been coding the backend functions. I've been reading a lot of code, and monkey-copying a little too much. So far I have some code that I stole from:

Transmageddon - it has some handy methods for defining encoding container types, encoding audio profiles, and file extensions.

Sound Juicer - I spent some time the other day stealing error handling from Sound Juicer. It puts a bus on encodebin and listens for errors missing plugin errors emitted by the encodebin. Today my mentor told me that I'm supposed to be listening for errors on the pipeline's bus. You wouldn't think that would be difficult to understand, but I ended up getting confused. When I looked at documentation for adding a bus to a pipeline, there were two ways that buses were handled: either they were connected using add_watch() or by popping messages of the bus and handling them if they are the correct type. Sebastian told me to use add_watch, but I wasn't able to return any errors because I asked the bus to listen before I set the pipeline to Gst.State.PLAYING.

GNOME Shell - I stole an interesting while loop from GNOME Shell a few days ago and I've been trying to work out exactly how to handle callbacks in it. I'm using it to gather metadata about the files in the Recordings directory so I can populate a listview. I'm interested in having an asynchronous callback that passes the data to the code that populates the listview after it's returned data about 50 files, and then continues gathering data.

So in general I'm having a lot of fun trying to understand and learn from the code base. I never learn as quickly or as well as I would like, and I tend to destroy more code than I create, but there you have it: my weekly update :)

Wednesday, June 5, 2013

Google Summer of Code 2013

I'm going to be spending the summer writing a new sound recorder for GNOME. I finished up my graduate assistantship duties last Friday. The motherboard on my laptop died early last week (after blackscreening on and off while I was writing my C/C++ final, yay). I bought a new laptop on ebay so I could swap the hard drive into a similar machine, and when I tried to pull out the drive on the new laptop I discovered that it was hot glued in place. Anyway, hopefully the rest of the laptop is fine, since it's what I'm using now, but I'm kind of scared to open it up and look.

Reda Lazri has been working on some pretty cool mockups for the sound recorder, and I've been bikeshedding them :) We are keeping them in the gnome-sound-recorder mockups folder on github. I keep meaning to ask Allan, Jon, and Jakub for feedback but so far I haven't. Partly that is due to trepidation, and partly it's because I'm still figuring out what is and isn't possible in GStreamer.

I've been battling a little with GJS, mainly because there are a lot of functions in GNOME libraries that simply don't work in GJS, and there is no documentation. In the past I thought things were failing because I didn't understand what I was coding, but in fact it was often the case that I was trying to use functions which didn't have GObject bindings. Sometimes GJS will helpfully announce that something is "not a function", which is not exactly useful, since it's listed as a function in the documentation. This always lead me to believe that I was writing code with syntax errors. When I started working on the sound recorder, I asked Jasper St Pierre how to generate GJS docs with g-ir doc tool, and it's been really nice to be able to look up the syntax of functions when I get stuck.

While I'm fairly comfortable with GJS because of working on some stuff for Documents, I still don't know it nearly as well as Java. I did an independent study last semester so I could learn C (the instructor threw in C++ as well, which honestly was a lot like Java with .h files). So far it's been really useful. Some of the GNOME codebase is still a bit difficult for me to understand in places, but being able to steal code snippets and translate them into GJS makes coding with an unfamiliar API a lot more reasonable. GStreamer seems pretty user friendly but it's pretty huge and complex. I have already gotten a lot of help from my mentor, Sebastian Dröge. Indeed, I almost think I'll finish by the end of the summer, if I can sneak it past the Design Team :)