OSD700 0.5
Today mark’s the release of 0.5 for OSD700 and compared to the last release, this one didn’t feel quite as awesome. For my 0.4 I was able to get 3 separate tickets up for review/feedback and it felt great. This release was quite different. I had to take my half finished work from 0.4, put the polish on it, and actually get it landed, which sadly didn’t go as planned.
Bug 702161, which was the first bug I began working on last release, is still sitting on it’s second stage of review. Justin Dolske had a few minor comment’s that I cleaned up quickly and I have been waiting on another review for over a week now, which sort of sucks. I’m assuming Justin is really busy with his work and will get to it soon, but it sucks not getting a ticket landed this release that I thought would definitely land.
Bug 680321 was a bit different than 702161. Chris Pearce had a bunch of feedback on how my current implementation was wrong and how I could fix it ( outlined in my last post ). I managed to bring it up to par with what Chris described for the most part, but continued to run into a failing case when my fix was implemented. I spent the better part of this week trying to fix the problem and continued to hit dead ends. I spoke with Chris on IRC a bunch and last night he say’s he figured out the problem and pointed me in the direction of where it was occurring. He said if I couldn’t figure it out he would give me the solution, but I don’t want this bug to end that way. Seeing as I’ve been scowering over the code for the last 2 weeks, simply having Chris hand me the answer would be a pretty anti-climatic end to an interesting ticket. The area of the code that Chris pointed me at was AbortExistingLoads, Load, and IsCancelled in nsHTMLMediaElement.cpp. My guess is that there is something going wrong when we load our new source ( which calls Load() ). Load calls AbortExistingLoads, which resets the state of a bunch of flags pertaining to the media element so that when we load a new resource, it act’s as tho it was from first load. Some of the things I noticed in AbortCurrentLoad was that we never reset the preload state back to undefined, and it kept it’s previous state from the last time it was set. I thought I had figured it out, I mean it all made sense in my head that this was the problem. After waiting on a build it ended up fixing this bug, but now failed test 13 again ( not allowing less aggressive buffering to occur then what is currently happening ). I know I’m getting closer to figuring this out and once I do I will be pretty close to finishing this ticket, seeing as I already have test’s written for it.
Last week I also picked up bug 722788, which was adding an optimization to the number parsing code for JSON. The code I was working on was inside Firefox’s JavaScript engine, SpiderMonkey. I briefly outlined what was supposed to happen for this ticket in my last post, but I think I severely underestimated how hard it was going to be. There was a lot of math, terms, and other thing’s that I didn’t understand and although I began researching what I needed to do, it was too little too late. I tried to not understand the math as much as I could, but in doing I felt myself lost at time’s and didn’t know what the next step was. I tried copying Chrome’s implementation ( which the ticket was based off of ), using the suggested places to look that were mentioned in the ticket, and asking for help on IRC, but that still left me dumbfounded and most of the time with 5 other questions I had to ask. Last night the nail was pretty much driven into the coffin for me regarding this bug when someone else posted a fix for this. The fix he posted was crazy. If what was posted is correct, I was way, way, WAY off on what I needed to do. I’m not gonna lie, I was pretty disappointed that I didn’t figure this out as I was really excited to work on the JS engine, but at the same time it was an awesome learning experience. I may have put about a week’s worth of work into getting no where, but I learned a lot about what I am capable of currently. It made me realize that I am really going to need to revamp my math skill’s if I ever want to work on a ticket like this again and that I am not even close to being done learning. All in all the experience was humbling and gave me a new perspective on how to approach problem’s. So for now I am going to stay out of SpiderMonkey, but I don’t plan on making that permenant.
This release ended up being a lot of work for little to no results. This is probably one of the most frustrating part’s of being a programmer, in that we put so much time and effort into trying to solve a problem, when so much of the time it ends up being a dead end or code we just throw away. With that being said tho, programming can also be one of the most satisfying thing’s to do as well. With all that time and effort put towards figuring something out, when you finally do figure it out, there is no other feeling quite like it.
Firefox bug 680321
Over the past 2 weeks I have been working primarily on bug 680321, which pertains to issue’s with the way Firefox handles the changing of the preload attribute. I explain in a prior post the details surrounding the bug and some of my thinking towards getting my patch up for review. Since then I have put another patch up for review, gotten some great feedback, and am working towards getting another working version up and running.
My first patch failed mainly because it was just wrong. I created the desired functionality but in doing so I broke features that I shouldn’t have ( this happened due to the fact that I didn’t write any tests before I asked for feedback ). What I broke was a case where the user changes the preload state, but does not change the media’s source. If this happens firefox simply ignores the changed preload state as we are requesting to change the buffering algorithm on a video that is already buffering. My first fix was to simply allow this to happen, which fulfilled my use case but obviously broke what I just outlined. I quickly got some feedback saying that my approach was wrong and I got a few pointers in the right direction from Chris Pearce.
Chris gave me the following advice:
Can you look a the testcase attached here in the bug and add a similar test to content/media/test/test_preload_actions.html?
::: content/html/content/src/nsHTMLMediaElement.cpp
@@ -889,5 @@
> nextAction = static_cast(preloadDefault);
> }
> }
>
> – if ((mBegun || mIsRunningSelectResource) && nextAction < mPreloadAction) {So mBegun is true after we’ve chosen a resource and started to download and decode it. We don’t want to support reductions in the amount of buffering after decoding has begun at the current time; that should be the subject of another bug.
So instead of doing what you’re doing now, create a new boolean flag mHaveQueuedSelectResource, and use that in QueueSelectResourceTask instead of using mIsRunningSelectResource. This will prevent multiple calls to SelectResource being queued concurrently. Then call UpdatePreloadAction() in SelectResource, but set mIsRunningSelectResource to true in SelectResource() *after* calling UpdatePreloadAction().
Then the preload action will be updated before we start trying to load the resource, so if it’s changed after load() is called on the media element, but before the load’s synchronous section is run, the new load will reflect the changed preload state.
If that doesn’t make sense (or work!), let me know.
![]()
Seeing as Chris basically outlined a solution for me I would be dumb not to roll with it so that’s what I did. After about two nights of writing tests and bring the code up to par I submitted it again for review. The main problems that I got nailed for in review were not adding comments, which I guess I should of known would have been said considering how well commented the Firefox source code is. I was also asked to write another test in order to prove the results of my fix. The last thing I got nailed on was changing the use of mIsRunningSelectResource to mHaveQueuedResource. One of the problems I encountered while writing the fix Chris suggested was that the fix broke the same previous case as my first fix did. This was due to the fact that although we were loading a new resource and setting the preload state again, we were still running into the same issue as before because the resource selection algorithm still thought we were loading the original source. We ( currently ) had no way of explicitly stating that the source had changed so that it was ok to allow the preload state to change. I managed to find a hacky workaround to this by leveraging the new variable that we created and I found a unique case where the boolean state of the flag accurately reflected that we were loading a new source.
Although I had a fix that satisfied both cases it was still not optimal, which is probably why I got another R-. Currently I am waiting for Chris to come back to irc in order to have a conversation with him about the problem ( I think he is travelling at the moment ). In the meantime I am going to be focusing my attention on a new bug I picked up which is working on Firefox’s JavaScript engine, SpiderMonkey.
Bug 722788 is a starter bug which explains there is a simple( for them ) optimization to be made when parsing JSON numbers from a string. Instead of using double’s to do the parsing we can simply use unsigned integers to accomplish what we need. This code is the most intense looking C code that I have seen to date, so I’m not gonna lie, I’m a bit intimidated. I think I have what seems like a fix but I’m getting some odd results when I try and run the tests. The next step here is to go into the #jsapi channel and ask how I am supposed to be running the tests and if there is any known fails I can expect to see.
I know this bug is a starter bug, but it has been the hardest bug so far for me to wrap my head around, probably because it is on a lower level than I am used to. One of the thing’s I have been trying to do this semester is to get a working patch up as fast as I can, regardless of how hacky it is. I’ve been doing this for 2 reasons: 1. It allows me to attempt a lot of bugs and I don’t get hung up on any 1 issue, giving me a chance to think about problems I’m encountering. 2. I get feedback on what I am doing wrong earlier rather than later, allowing me to reduce the possibility of building on an early mistake. It seems to be working out well so far and the only thing I am concerned with is that I may be putting patches up for review too early, in which case I might be annoying some of the reviewers with an insignificant patch.
I hope to have a patch up for the new bug I have taken on up for review by tonight as wel as hopefully hear from Chris at some point this week. Until then I am going to keep doing what I’m doing and hope for the best.
OSD700 – First release!
For the last two weeks I have been working on various Firefox bugs for my first release in OSD700. My bugs have been centered around various parts of the media implementation, ranging from issues with the controls to problems with how preload states are handled. As it stands, I’ve managed to get a patch up for 3 of my tickets which is pretty cool if I do say so myself. The tickets that I’ve worked on so far are 702161, 708814, and 680321. I’m going to touch briefly on each ticket and the changes that I made.
The first ticket I started on for the course was 702161 and was focused around removing anonymous functions that were set up for event listeners but were never removed because we had no reference to them. Fixing these was a matter of storing a reference to each of these functions and removing them at the proper time. You can read up on my earlier work for this ticket in my other blog posts. My first patch for this ticket was rejected because I attached each function to the video object instead of attaching an object to the video and attaching the event listeners to it. I forget my reasoning for not doing this in the first place, but thats beside point. I learned a lot about Firefox’s review process with this bug and how it differs from the review process in other open source projects I work on ( Popcorn.js and Popcorn Maker ). In Popcorn projects we typically wait until both a fix and tests have been written before review is requested. The review process in Firefox is a bit different. It seems to the norm to submit patches more frequently in order to get early feedback on what you’ve been working on. I like this because it allows you to find any glaring mistakes you are making early and ensures that you are on the right track for later patches. It also allows reviewers to handle your code in smaller doses. I remember one ticket that I submitted in Popcorn that touched ever file of every plugin ( ~100 files ). I remember dumping that ticket on Chris De Cairos for review and seeing the look on his face. I can just imagine how much more manageable my patch would have been if we did something similar to Firefox. All in all this ticket taught me a lot about Firefox’s review process, how patches should look, and was a good way to get my foot in the door of Firefox development.
My second ticket was 708814 and had to do with fixing an issue where mousing over a full-screened video would not hide the controls. It was cool that this ticket was centered around code that I just finished working with in 7021661, so I felt pretty confident about getting started. The first thing I did was to make sure that I could reproduce the bug. Chris Pearce posted a test case and some guidelines about how to reproduce the bug. I fired up the test and followed his instructions and what do you know there was the bug. The problem was that when using a hotkey to trigger a video to go full-screen that the controls would not disappear. This was because prior to my patch, a timeOut for removing the controls was initially fired on mouse move when the video was fullscreen. My fix consisted of checking to see if the mouse was over the video element when it was fullscreen. If it was, we would start the timeOut then. The interesting part about this ticket was that my fix spawned another ticket for me to work on. The bug that I found ( that already existed in bugzilla )was 708553.
Bug 708553 is about the video element not properly handling hover states when in full-screen mode. This relates to 708814 because my fix essentially says that if the video is full-screen and if the mouse is hovered over the video, then start the timeOut. I picked up this bug because from what I can tell, it is blocking my fix for 708814, so I figured why not speed up the process and fix it myself.
My final bug for this release is 680321. This bug is centered around the preload attribute on video elements and how it handles being changed in the resource selection algorithm. The initial issue with this ticket was that the resource selection algorithm would ignore preload states that buffered less agressively if changed programatically. This means that if we start video A with preload auto and set a timeOut for one second later to switch preload to auto and change the videos source, that the new preload state is now ignored. This means that video B will begin loading assuming preload auto when it should use preload none. This ticket was interesting because it was my first ticket involving C++. Now I’m not gonna lie my C++ skills are pretty lacking, and I had to do a bit of refreshing to ever begin to understand what was going on in this code. The file that I was working in, nsHTMLMediaElement.cpp, was also pretty huge ( ~4k lines ). I spent pretty much the entirety of a whole night just reading this file and trying to understand how all of the pieces fit together. After finding an area of the code that I thought the bug was in, I began hacking. After a few incremental builds and I found that I was pretty lost without a debugger. I remember Chris and Jon talking about a good C++ debugger for the command line so I went to irc to ask for some help. I was given a quick rundown about GDB and how to use it, tho I found a way to screw it up so I opted out and chose to wait until David Humphrey explained it in class. I was going to have to go with the ole trial and error approach if I wanted to make progress before Thursdays class. The odd thing that I noticed was the no matter how many changes I made to the file I was not seeing and changes actually happen to the browser ( I even commented out huge blocks of seemingly important code, and nothing happened ) so I figured my build process was screwed up somewhere. My guess was that I was attempting to build too far into the tree and my changes were not actually being seen further up the tree where they needed to. I said screw it and waited the few minutes and did a fresh new build and I finally saw my changes! I was lucky in the fact that I was pretty close to a solution on my first try. It took a few more small tweaks to make the change elegant and following the rest of the codes style and I was ready to submit for some feedback. The fix involved removing a chunk of code that prevented the functionality that we now wanted and added in another conditional check for our preload state.
My experience so far hacking on Firefox has been awesome. I’ve had a chance to talk with some cool dev’s on irc, make changes to Firefox that will help Popcorn.js, and learn a ton along the way. As it stands two of my tickets still need tests to be written for them before they get officially reviewed, but I’m optimistic about finishing them and can hopefully get that done by mid next week. I managed to get 3 tickets somewhat finished so far and hope that I can continue this pace until the end of the semester. I know the tickets are only going to get harder the deeper I go into Firefox but that also means the satisfaction I get out of finishing them will be even greater. I have no idea what other crazy bugs I will get to work on this semester but I can’t wait.
Firefox bug 702161 – part II
In my last post I described the work I have been doing on Firefox bug 702161. I got ( what I think ) is a fix and I was ready to write some tests. Personally I hate writing tests, as I’m sure everyone does, but they are essential ( especially in an open source project where many people are touching the code ). The unit tests that I had to write this time weren’t so much annoying as most that I write are, but more just hard to figure out a good way to write tests for. I have had a few ideas over the past 2 days how to test what I wrote and nothing seems to be easy or viable.
My initial idea was to get a reference to each element of the controls that I needed to test and get a list of all of the listeners attached to it. Initially my problem was trying to get a list of those listeners, as currently there is no way to do so from the native javascript code. After talking to Jon and Dave in irc a bit Jon linked me to a file that he thought I might find helpful. The file showed how to include and use an interface that was setup to do what I needed to do. There was a code that I had never seen before and had little to no idea what it actually did internally, but I used it non the less. Including the interface gave me access to its methods, in particular getListenerInfoFor(). getListenerInfoFor would return me a list of all the listeners on a given element, which is exactly what I needed. At this point all I needed to do was get a reference to each part of the controls and I was but a hop, skip, and a jump away from finishing my tests. Sadly, this wasn’t the case. After digging through various files and looking for a way to access the controls directly from JavaScript ( some how I ended up looking through XPCOM code? ). After 5 hours of searching on Tuesday night I went to bed still wondering what I needed to do. Earlier today I spoke with jaws in the #introduction channel on irc and asked him how I could get a reference to the controls. I was then told it was not possible, and that the controls were designed so I couldn’t get a reference to them. Sadly I accepted this and went back to the drawing board.
Another idea that I had, tho not as good as the above one, was to use some of the EventUtils tests that Firefox has to offer. The one in particular that caught my eye was synthesizeMouseExpectEvent. From what I understood about this test method was that I could go to a x,y location, synthesize a click, and check to see if any events resulted from that click ( or mouse movement ). It would be perfect if I could do this because I can check to see if there is an event thrown initially, then somehow call the terminate method ( still haven’t figured that out either ), and check to make sure that no event is thrown the second time. The problem I ran into here was that I couldn’t get the test method to work properly with the video controls, which leads me to believe that what I want to do isn’t possible with this either. I set up a dummy test case with a button and on click listener and the test method worked fine. As soon as I tried a similar approach on the controls it didn’t work. What I’m guessing is the issue here is that the event that is being fired is being stopped from bubbling up to a point where I can catch it. I am going to have to do a bit of searching tomorrow on this theory and see if my assumption is correct.
Other than this I am pretty much at a standstill with this bug. I have thrown what I have done up for an initial look over and hope to get some good feedback. In the meantime I am going to take a break from this bug and start on one of my others in the meantime. I’ve got a few other cool ones, so I don’t feel bad about taking a break from this for a day or so
Firefox bug 702161
Mid way through last week David Humphrey sent out an email explaining that he spoke with Chris Pearce about some possible bugs for us to work. The list consisted of various bugs, varying in difficulty. Dave encouraged us to pick up any bugs that interested us so thats exactly what I did. I picked up the following bugs:
- 702161 - videocontrols.xml has anonymous function event listeners that are added but never removed
- 708814 - Should fade out videocontrols even if there’s no mouse movement
- 680321 - Media preload state should reset in resource selection algorithm
These are all in addition to the bug that I was assigned last week ( 688370 ). I chose these bugs for a variety of reasons. 702161 seemed like a good bug to get my foot wet with and get the feel for submitting a patch and going through the review process. The other two interested me on different levels. 708814 looked like a cool media bug to fix and I can identify with it on a personal level. I don’t know how many times I’ve been watching videos online and have my mouse over the video just to notice that the controls don’t disappear. Not annoying the first time it happens but after a while it irks you. 680321 seemed to touch some of the preload code which interests me because in the past we have had issues with preload ( especially in Chrome ). I figured this would be a good way to take a look at whats going on and if any bugs in the future come up around the code I would already have some exposure to it.
Last night I built Firefox from source for the first time in about a year. I feared that it would not be an easy process as my experience with this kind of stuff typically always takes a turn for the worse. I was surprised that this wasn’t the case, in fact, the whole process was quite stress free. I began by following a guide I found online by simply Googling “Building FireFox from source”. After installing various dependencies I was set to begin the build. Something to note is that I was doing this build from a git repo of Mozilla-Central that is updated daily ( I believe ). From what I gather installing is about the same as it would be with mercurial just managing the repo would be a bit different. Something to note is that there is a flag in your .mozconfig file that you can set to specify the number of cores you will use for the build ( for those of you with numerous cores ). The build took about 20 minutes in total and then I was ready to open up my nightly build of FireFox, and it was a success!
The next step was to start on a bug. The logical choice as I mentioned earlier was bug 702161. The problem that was outlined in the bug was that various anonymous functions were created but were never destroyed when the terminate function was called. This is bad because each time terminate was called it would mean various listeners were never removed properly. So what I needed to do was pretty straight forward. I needed to store a reference somewhere to each of these anonymous functions so that upon removal later we could access that reference in order to remove the listener. I was even fortunate enough that within the bug itself Jared told me exactly where to find the file. Perfect. I then went to take a look at the file, which was quite a bit bigger than I thought it was going to be ( ~2000 lines ). After reading over the file a bit and taking a hint from the filename, it was obvious that this file was responsible for all of the code surrounding the video controls. The first thing I wanted to do was simple, make a change that I could see. All I did for this was add in a console.log. I then created a test html file that I could test off of. I added the console.log to the mouseover of the volume button, so it would be pretty obvious when it was working and when it wasn’t. After I made my change I had to rebuild FireFox in order to see my fancy new changes. I found a small article online that outlined how I could only rebuild the portions that I touched, which would in turn drastically reduce the amount of time it was taking to build, in fact it took it down to about 30 seconds. Behold my changes:
I then proceeded to actually do what the bug set out to do, cache the function and remove it on terminate. I’ve done this before in JavaScript a few time’s so it wasn’t too bad to get working. I initially just created a variable and stored the function in it that I could later reference. Far from elegant but it worked! Tonight I am going to be focusing on a nice elegant fix and hopefully ( fingers crossed ) get a patch submitted before I head to bed.
I’m itching to get this bug done so I can go and start on the controls not disappearing one, I’m pretty stoked to get going on it. So stay tuned, there are plenty of blog post’s to come
OSD700 and Firefox Hacking
This morning I attended my first class of the year which was David Humphrey’s OSD700. The class is about expanding on what we learned in OSD600 ( Intro to open source development ) and taking it to a whole new level. In OSD600 we were encouraged to try as much as we could and whether we succedded or failed didn’t matter, it was that we were getting an initial feel for how open source development worked. This time around the stakes are much higher, failure is not an option. We have all been exposed in one facet or another to open source development and know what to expect. This is my only class this semester and I’m excited that I can devote all of my time outside of work to working on what I enjoy and what interests me.
In a nutshell, I am going to be working on various portions of Firefox’s media implementation. I have been warned that the good is going to be hard, its going to make me angry, and its going to require a lot of time and effort. To be honest, I didn’t really expect anything else. After watching the amount of hours and hard work that were put in by everyone who worked on the MouseLock implementation last semester, I knew I was going to be in for some serious coding. The good thing is that I am not alone here. Pretty much the whole Popcorn.js team at CDOT is taking the course with me and is also going to be working on various media bugs and features. The others in the class will be working on Firefox as well ( with the exception of Mo who is working on Popcorn Maker stuff ) which is pretty cool and exciting.
During todays class we also all got assigned our bugs. I was fortunate enough to get a bug that I was interested in which is awesome. The bug is 686370 and is about implementing playback statistics for Firefox’s video element. This problem interests me because a while back Dave, Jon, Rick and I were attempting to figure out an issue surrounding a Pirate Bay video that a Popcorn demo had been built around. The issue was the the video would seize playbak about 1/3 of the way through playing in Firefox but would continue to play for about 10 seconds longer in Chrome. Dave explained that Firefox and Chrome take very different approaches to how they load there videos. Chrome takes a much more aggressive approach ( which is why it buffered further ) but apparently adheres much less to the spec than Firefox does. This still didn’t explain why we were seeing the issue we were. After Dave got a debug build of Firefox running he was able to get some info on what exactly was going on. It turns out that the video was encoded in such high quality that it required something like 1.5mbps of data buffered to be able to run smoothly the whole way through ( which is pretty crazy for us Canadians ). It took us probably an hour to figure out what was going on which is crazy. Seeing how it took us so long to figure out what was going there was obviously a problem that needed solving. Wouldn’t it be nice it we were able to get info back about the video’s playback via JavaScript? It would have made debugging this a 100x simpler and not required an hours worth of digging. I can only imagine what other uses something like this might create.
My plan for the next few days and over the weekend is to find a good place to look in the media code and see if I can dig up something that might help me. It sounds like it should be pretty trivial but I know I’m in for hours of searching and trial and error testing to find out where the code I need lives. On top of that I am going to familiarize myself with the spec and make sure I understand the problem. On top of that I am going to have to brush up on my C skills. I havn’t written a line of C code in about a year now and I’m sure its quite rusty compared to others in my class. Ive been writing JavaScript for the last 8 months so I know its going to being weird going from one to the other.
All in all I am nothing but excited for this course. I fluffed on my last Firefox bug and I don’t want to do that again ( I SWEAR I’LL FINISH IT SOMEDAY ). I want to see firsthand just how crazy the Firefox code is and get in way above my head. I’ve got a great class that I can rely on should I have questions or require any help, so I’m super excited to get working this semester. I know as a class we are going to create some crazy code this semester and I can’t wait to see what we accomplish!
Setting up Test Swarm
Near the end of 2011 ( before I disappeared for 2 weeks ), the Popcorn.js team and I went out for an end of year dinner. Throughout dinner a discussion came up about how our testing infrastructure could be improved and some of the things that would be nice to have. Something that stuck with me that David Humphrey mentioned was how we could benefit from continuous integration within our tests. Continuous integration is essentially creating a way to test our code as we are developing it. This means running manual tests less frequently, being able to identify bugs sooner, and prevent regressions from occurring. After coming off my 2 – 3 months working primarily on improving Popcorn’s documentation, I figured I could use a serious change of pace. So at the beginning of 2012 I told myself that this is what I wanted to do.
One of the difficult issues that arose right out of the gate was which CI ( continuous integration ) framework did I want to use, and more importantly, which one was right for us. After doing a bunch of googling a came up with numerous different options, but none of them seemed right for what we wanted. Most of the one’s that came close failed in one major aspect, that they didn’t test on actual browsers. What I mean by this is a lot of the options that came close offered there ghetto webkit rendition that the tests would run on. The problem lies in the fact that some tests pass on lets say Firefox, but fail on Safari. We can’t rely on a single point of testing and needed a way to continue to test on all of the modern browsers. After a bit more searching I came across an option that seemed to fit our needs and was even written by John Resig ( previous Mozilla employee and creator of JQuery ), so I had high hopes.
The project was called Test Swarm and described as the following:
The primary goal of TestSwarm is to take the complicated, and time-consuming, process of running JavaScript test suites in multiple browsers and to grossly simplify it. It achieves this goal by providing all the tools necessary for creating a continuous integration workflow for your JavaScript project.
After talking it over with a Jon Buckley and Rick Waldron a bit ( fellow Popcorn.js devs ) we decided to give it a shot. Rick was awesome enough to get us a few minutes to talk with Corey Frang ( member of the JQuery Core and UI teams ) to lend us a bit of his expertise in the area of setting up Test Swarm. Corey and Rick both cautioned that setting it up was not a simple task and they ended up being right as it took me about a week of work to get to where I am now. Initially I searched for other’s who had set up test swarm and the problems that they encountered because I figured if they hit these issues I was sure too. I was surprised that there really wasn’t a detailed guide to setting up Test Swarm and to learn that it isn’t that widely used. So I started working with what I had, which was the README from the Test Swarm repo and a small set of instructions on the wiki page.
Setting up the server, for the most part, wasn’t that bad. I ran into a few problems trying to set up the server on my localhost and ended up throwing it up on a web server for simplicities sake ( I’d recommend doing so for any else who is trying this as well ). The main problem that I ran into in this part of the installation was configuring apache correctly. Up to this point in my exposure to actual programming ( what I refer to as about the last year of my life ) I have just ignored setting up apache for myself and most of the time got help from others when I needed something. When I started working on this project it turned out that I no longer had to luxury of remaining ignorant. I ran into a slew of problems with permissions, how .htaccess files worked, and how to enable a rewrite module. If anyone is wondering, all of this work was done on Ubuntu.
The first thing problem I listed was setting up permissions properly with apache ( and Ubuntu for that matter ). This was a problem because I needed certain scripts to be able to call other scripts, perform git actions, write to a databases, and so on. This involved A LOT of googling in order to figure out just how all of this is done. For the most part, the searching was pretty straightforward in the fact that I could essentially google what I was thinking and get helpful results. The next issue I ran into was working with the .htaccess files. From what I learned, a .htaccess file is essentially a configuration file on a per directory basis. This means I can create a file to specify options that are only applied in the context of that directory. By default, .htaccess files are not used and have to be turned on in apache settings ( from my reading online, it seems .htaccess files are frowned upon for some reason ). According to the README, all I needed to do was change the AllowOverride attribute from None to All. Alright great, but HOW do I do that and where exactly should I look? I started of by searching for “AllowOverride” in the main apache config file and found a few instances of it kicking around and figured I would just set all of those to All instead of None and see what happened. I was hoping to figure out which one I needed to actually be set to All by process of elimination, but as it turns out, none of them were the right one to set to All. Well, as of this point, I had never touched another apache config file so it was back to Google for me. After about a day of searching I finally found out what I needed to do via a helpful blog post I found. The post outlined exactly what I needed to do and after actually doing it I had a fair bit better understanding of what I needed to do. At this point I had our Test Swarm server up and running. The next step was to set up a git post commit hook and create jobs based on each commit.
The way we envisioned this all working was that when a commit is pushed to our develop branch that it would automatically checkout that commit and run all of our tests. After the tests have finished we would get a report of some sort back with the results of the tests that were run. You can imagine how this is benefitial to any project, especially the bigger they get. Popcorn.js currently has ~1500 tests in total, so running those tests can become quite time consuming ( especially when you factor in a complete and minified version ). The next step that I needed to take was to create a git hook the would send our server information each time a commit was made to our develop branch. I did this by doing the following:
- Set up the post-commit hook on github to send a POST message to our server when something was committed
- Create a php file that would receive the POST message. All this file did essentially was check to see if the branch that the commit came from was our develop branch ( only want to run tests based of develop ( for now at least ) ). Once we verify that the commit came from develop, I call a bash script that I created passing along the URL to the git repo and the commit id as arguments.
- The bash file essentially created a git repo ( with the passed in URL ) with a directory named after the commit. Naming the directory after a commit is essential here because if numerous commits come in, we need to separate them and not have them overwrite one another. I then checkout the commit and call a perl script.
- Inside our Popcorn test suite I had to add an injection script in order to report passes/fails back to the swarm when I test was done. This was added inside our project repo and not on the server. The script itself is pretty small ( ~150 lines ) and is included in the Test Swarm repo in the js/ directory.
- The perl script does most of the heavy lifting for us. The Test Swarm repo actually has a few sample scripts setup ( they fortunately already had one setup for QUnit! ) so I used it as a starting point. For the most part it was as simple as replacing there directory paths and options with what we needed. I had to modify a bit of stuff as it just didn’t work otherwise ( for some reason there was code in there to shorten the commit id, which didn’t work when trying to locate our repo ).
- That was essentially it in a nutshell. There was a ton of debugging that went along with the process but I actually didn’t have to write much code at all.
As of right now I am able to commit to my Popcorn repo, have that commit automatically pulled in, a job created based off that commit, and that job be pushed out to all of the connected clients. The tests are then run and the results are reported. The next things I need to get done are:
- removing a git repo when that commit’s tests have finished. There is no need to keep old repos around, it is only taking up disk space.
- set up a few dedicated boxes here at work each running VM’s for all of the browsers that we tests off of. The reason for this is that we have many tests that will fail if the browser is not in focus ( which is why we need to run a VM for each browser on each OS ).
- The tests are running, and I am getting results back, but in our report chart, even if a test fully passes the square still shows up as black ( should be green ). I image this is probably a problem with the injection script and how we are reporting the amount of passes/fails back.
- It would be nice to not have to run all of the plugin tests if a commit only pertains to core tests and vice versa. This would mean that we would get results back faster and new commits could be tested sooner.
- Im sure there are a ton of things that I am missing
All in all this has been a great experience and an awesome change of pace from writing documentation. Once this is fully up and running I think everyone will benefit from it, I mean lets be honest, no one likes sitting there manually running tests! Having a system such as this should make releases let strenuous and ( hopefully ) we shouldn’t be presented with any surprise bugs come release day.
Jekyll, YAML Front Matter, and the Liquid templating system
During the sprint to get Popcorn.js 1.0 out the door I was tasked with getting our documentation up to date with the current API and making sure everything was in a working state. It involved some wordpress nonsense, lots of time contemplating my wording ( which is also a work in progress ), and countless days creating small demos showcasing each part of the API. In the end we had a functional set of docs that everyone could use. They weren’t that pretty, didn’t have a table of contents, and were a pain to navigate through, but they did what they set out to do. We wanted to make the docs even better then our first stab at them, and thought it would be awesome if we could have them on github. Having the docs on github would mean making future alterations simple, meaning anyone with git could send in a pull request in order to make changes. This also meant that we could leverage the power of various templating libraries and order to make our docs really shine. This is what I have set as my goal for 1.1 of Popcorn.js, make the docs awesome.
To begin I talked a bit with Jon Buckley about what he had recently done with the Processing.js website and documentation. They recently migrated there website over to github pages and Jon explained that it was actually quite a pain free process. He showed me what he created and it looked pretty stellar. The best part about this was how easy it would be to make future changes. I think one of the main reasons that people hate documenting stuff has to do with the tedious nature in doing so. You have to get access to the web-server, which usually involves getting permission from someone, and then you can begin writing the docs. Using git instead someone could add a completely new function to the current API, write unit tests for it, and document it all in one pull request. Jon also showed me some of the templating stuff that he was utilizing, namely Jekyll, YAML Front Matter, and the liquid templting system. You can do some pretty amazing things with the 3 of these. Jekyll is described as the following:
Jekyll is a simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub.
YAML Front Matter allows you to specify some predefined variables in your page, as well as access various pages across your site ( if you set up your directory structure correctly ). Jekyll interprets files with YAML data in them as special files and all data gets processed as the page is read. Using YAML with the liquid templating allows you to create some pretty amazing things, such as essentially define your table of contents based on your directory structure, create default templates to be used site wide, and use unique Liquid tags and filters to define which content goes where on your page. So what does all of this mean? Well it means that having our docs live in git, and using a libraries like we are, we are able to allow users to push there doc changes to git, have them be read in by our templating library at compile time, and then generate the content on the pages accordingly. This means once we have the pages set up, its simply a matter of updating our git repo to have our doc changes appear.
So 2 days ago I finally began the overhaul of the docs. I began by creating my directory structure according to how I wanted the docs to be laid out. I created a folder for each major part of our API, Static methods, instance methods, instance properties, media methods, plugins, players, parsers, effects, and modules. Each of these had there own folder which each had a sub-directory called _posts. Jekyll walks your directory tree and looks for folders called _posts and knows that this is where various posts will leave within the site. What this means in the context of our docs is that each “post” will be a doc for different part of the API. The next thing I needed to do was change the naming structure for each of our markdown files. Jekyll expects the files to be named in the following fashion: YYYY-MM-DD-fileName. I took this as an excuse to write a bash script ( as I don’t get to write enough of them ) that would do what I needed. After this I created an index.html page that had some YAML Front Matter defined at the top ( to let Jekyll know that this is a special file that needs to be processed ) as well as some liquid code to read in various categories ( defined by our directory structure ). This is when my day long battle with liquid and YAML came in. Im not gonna lie, I went down a bit of a rabbbit hole here, but refused to except what I was told by the internet, that I couldn’t do what I wanted to.
So what did I want to do that was supposedly not possible? What was this psycho idea that I had that YAML and liquid just could not handle? Sort. An. Array. Yes, you heard me, I wanted to sort an array and this took me the better part of a day to get working. So to begin, to access the categories of your site YAML provides you with a global liquid variable called site. On this variable we can access the array ( or what I thought was an array ) of categories. Sounds typical, so I attempt to loop over those categories and print them out. Well you see, if you wanna do that, you also get all of the categories posts as well ( makes complete sense right? ). Hmmm, well, I can work with that, I’ll just take the first word that they give me, as it was the name of the category, and print that out. Awesome, that worked. So it seems that the output isn’t sorted, well I’ll just call the sort filter on the array. Oh crap, I just took the first word off of that array of categories, so that means all those words that I just stored using a capture, are not longer an array, but just one big string seperated by spaces. So turns out I can’t use the sort filter. This is when the googling began. All searches came up with “you can’t do this”. Take a look at this stackoverflow question, where the person who posted wanted the same thing as I did, and the accepted answer was that it is not possible. I refused to accept reality. This must be possible. How can I not sort my categories? I spent the following hours hacking with liquid, battling it every step of the way, but in the end, I made liquid, YAML, and Jekyll my B***h. It did what I wanted, whether it liked it or not. My final code looked like the following ( tho to get there I hacked with probably 50 or so lines of code to make sure everything was working ):
<ul>
{% capture get_items %}
{% for cat in site.categories %}
{{ cat | first }}
{% endfor %}
{% endcapture %}
{% capture num_words %}
{{ get_items | split:' ' | sort | join:' ' | number_of_words }}
{% endcapture %}
{% for item in (1..num_words) %}
{% capture this_word %}
{{ get_items | split:' ' | sort | join:' ' | truncatewords:item | remove:'...' | split:' ' | last }}
{% endcapture %}
<li><a class="caps" href={{ this_word }}>{{ this_word }}<a></li>
{% endfor %}
</ul>
And main page of the docs looks like the following:
In the end I probably spent more time then I should have on such a small issue, but I proved that it was possible. The next steps for the docs from this point are creating some small YAML files in each of the categories folders describing what each one is about. Then i will create an index.html file in each of those directories that will a table of contents for each category, linking to each item. Im also planning on creating a template that that each file will use, so I only have to define the YAML and liquid filters for each file. Reinforcing my earlier point, and part of the reason I was so adiment on getting the sorting working, was that if this is set up properly everything will just fall into place. When someone updates the docs, everything will just work. You add a new category? Just works. Add methods to the API? Still works. Deer driving a car? Nope. Chuck Testa. But thats a whole other blog on its own. Still quite a bit of work to do in the coming weeks, but it is going to be awesome when it is done, so expect an updated blog post on my progress in the coming weeks before Popcorn.js 1.1!
Mozilla Drumbeat Festival and Popcorn.js 1.0
First and foremost, just over a week ago the Popcorn.js team and I released our 1.0 milestone, so congratulations to everyone who was a part of it. It was an amazing feeling for me in particular ( and I’m sure everyone else as well ) as this was my first 1.0 release. It signified ( to me at least ) that we did something right, that what we were building meant something to someone other than the immediate Popcorn team. In the pasts months I found it awesome when just one person would come on IRC asking questions about Popcorn and now after 1.0 and the attention we got at the Mozilla Festival there seem to be a ton of people on both the mailing list and IRC, its awesome.
The last few weeks have been crazy as ever; I spoke at FSOSS on Popcorn.js and Popcorn-Maker ( which deserves a blog post on its own ), we had 4 articles written by wired magazine, we travelled to London, England to attend the Mozilla Drumbeat Festival, which I even had the honor to speak at. I don’t think I have had time to really take in what we have done and just how awesome it really is. When I began on the project back in February as a student in David Humphrey’s Open Source Development class, I had no idea I would ever be working on the project, let alone seeing it to 1.0. Yet here we are, 10 months later and we did it. We released the 1.0 version of Popcorn.js and the alpha version of Popcorn-Maker. Its crazy what can happen in a year.
So more on the Festival! Last week on November 2nd Jon Buckley, Christopher DeCairos, Scott Downe, David Humphrey and myself flew out to the Mozilla Drumbeat Festival in London, England. The funny thing about all of this is that Chris and I only found out we were going about a month ago. It was originally only supposed to be Jon, Scott and Dave going, but some additional funding came up and Chris and I were invited along. I remember getting the news and feeling like a child on Christmas eve, I had a perminant smirk on my face for the next 48 hours or so. But back to the festival. When we arrived we still had some work to do on the release so we got to it. Jon and I tackled some issues with WordPress and the documentation while Chris finished off the amazing build tool that he created. After about 4 hours of hacking we had officially finished everything that needed to be in 1.0, we had released. A few hours later we attended what was called a science fair.
The science fair is essentially a ton of booths for all of the amazing projects that are apart of the festival. Its very laid back and everyone is encouraged to go walk around and see what everyone has to offer ( not to mention pick up a ton of cool swag
). Im not the most social guy, so I mostly ended up walking around listening to people explain there projects. I remember standing at the Twillio booth when the guy asked if I was a technical person before he gave a demo, I said yes and he asked what project I was apart of. I said I worked on Popcorn.js and the next thing I know I get a “WHAT I LOVE POPCORN!, YOU GUYS ARE AWESOME” followed up by a high five. It was small things like this that reassured me that we built something amazing. I had a similar experience when I went to the RAMP booth, where they were giving me a brief intro to what RAMP did when Jon and I mentioned we worked on Popcorn. The conversation went from explaining what they did, to thanking us on building something awesome and how much of a pleasure it was to use the software. I can’t thank the RAMP guys enough for everything they did. They took our software really to the next level for a major commercial application, creating new plugins and giving us feedback on what type of things would be nice to have and such. They also took the Popcorn team out for an amazing dinner, so thanks again for that! The rest of the science fair was filled with wine and talking with a ton of crazy smart people, followed by an unexpected hike across london with Jon, Bobby Richter and Alan Kligman. I don’t regret following Jon on his crazy way back to the hotel for a second, I mean how often is it that you get to walk through a construction site in London, England!
The next two days were filled with hacking on various things and helping people create their own Popcorn experiences. One of the major things that stuck with me was what Jon and I created. Simon Klose, the director of the upcoming Pirate Bay documentary had an idea of creating a dual screen Popcorn experience, where the video would be played full screen on lets say your computer, and all of the popcorn events would come to a mobile device. At the time we had nothing like this, and we sort of put the idea aside. This idea intrigued the hell out of me ( and obviously Jon as well ) because after our brainstorming session with Simon, Jon and I started talking and said something to the extent of “we can do that, lets make it later tonight”. For those of you who have never worked with Jon before, he is one of the smartest people that I’ve had the pleasure of working with, he somehow has an answer for everything. Working with Jon is always an amazing experience and I learn a ton from that man each time I work with him, so props to Jon for being awesome. Later that night over some beers Jon and I hacked together the first version of Popcorn remote using Peerbind. The problem with this initial demo was that both devices had to connect to the exact same page, which sort of defeated the purpose ( at least in my eyes ) of what we were trying to create. It was an awesome first demo, but we could take it further. Over the next 24 hours or so Jon and I hacked our hearts out in order to get two pages speaking with each, having the video on one screen, and a play/pause button on another. After 6 hours or so working as fast as we could, Jon finally figured out where we went wrong and we had it working. Later that night Brett Gaylor, the project lead for Popcorn, presented it infront of the Mozfest crowd and asked us to stand up as well. We had a video of Atul fullscreen on a projector and the play/pause button on Jons phone. We asked someone in the audience to press the button and voila, it worked. It was an awesome feeling getting this to work, and really shows how awesome Popcorn is and what kind of crazy stuff can come out of a small idea. Once we got back to Canada Jon and I actually took this a step further and built the demo that Simon originally wanted, which was pretty awesome.
Following are links to videos of the first and second demo Jon and I created, as well as a picture of Jon and I at the festival hacking away.
http://yfrog.com/5onzwz

There is so much more to mention about the festival, but I have already ranted for a 1000+ words, so I’m going to wrap it up. All in all it was the most amazing trip I have ever been on and I can’t thank David Humphrey, Brett Gaylor, Mozilla, and Seneca’s Centre for Development of Open Technology enough, I never would have had this amazing opportunity without you, so thank you x10000. I met so many amazing people ( Jonathon McIntosh, Simon Klose, Henrik Moltke, all of the guys from RAMP, Cole Gillespie, Alan Kligman ) and so many more as well as hacking with the rest of the amazing Popcorn.js team, Bobby Richter, Brian Chirls, Ben Moskowitz, Jon, Scott, Chris, Dave, and Brett. It will be a trip I wont soon forget!
Working with the CBC – An HTML5 audio experiment
For the last 2 days a small team and myself have been working on an HTML5 audio puzzle for a tribute to Marshall Mcluhan. The team consisted of Chris DeCairos, Scott Downe and myself from CDOT, Bobby Richter, Mark Surman and Allen Gunn from Mozilla, and Lilly, Sean and Angela from the CBC. We had a brief introduction on Monday morning and then went straight into brainstorming. The group from the CBC explained to us there vision and what it is they were looking for in terms of a demo. What they wanted was essentially an HTML5 audio puzzle. The puzzle would consist of various short clips that were from a much larger clip. They would be split into various sections and jumbled in a word box. The user would then have to organize the quote of Marshall Mcluhan in what they think is the correct order and then click play. Even if the order the user entered was wrong, it would still play the audio, just out of order and sounding weird. THe user would then rearrange the pieces and try it out again until the demo produced a seamlessly playing clip. At this point the user can attempt to submit there selection if they think they have it correct. When the user clicks submit all of the correct entries will stay locked in place, highlighted green, and all of the incorrect ones will be thrown back into the word box. This outlined the basic functionality of the game. The CBC crew also wanted a simple way to create these short audio clips from a larger one. So we needed to devise a plan to do so.
The CDOT team, Bobby and I quickly began throwing around ideas on what we could use to build this and what would be necessary. We contemplated on using Popcorn.js, but in the end decided it was a bit overkill for what we were going to be doing. We decided to write our own mini-timeupdate portion of Popcorn.js to use and went from there. We split into two small coding groups, Scott and I were working on the user facing side of things, so we essentially handled the adding of audio clips, what clicking on a clip would do, implementing drag and drop, and adding in the logic for the puzzle. This included locking pieces in that were in a correct spot, playing the clips regardless of what order they were in, and determining if the user has won or not. Chris and Bobby were responsible for creating an editor in which the user could highlight a portion of an audio clip, and in doing so it would save that clips data in JSON. The user could then select it again to enter the text that will correspond with this clip ( likely the words that are said in the clip ). They could then click a button after they have created several clips and it would output a big JSON blurb in which they can easily plugin to what Scott and I wrote. The goal for Monday was to on both ends, get a basic demo up and running with all of the essential features included.
In order to be accurate with clips, Scott and I decided to use request animation frame ( getting 30 frames per second i believe ). This would allow for Chris and Bobby to create extremely accurate sound clips for us to use. We got a small blurb of code from Paul Irish’s blog ( as apparently its now the standard for request animation frame ) and rolled with that as a starting point. We then implemented a addEvent function to our small core that we created. Within the hour we had our event registration system up and running, which was very similar to the structure of Popcorn.js. We provided a start, end and text attribute for the user to fill in, and then stored these events in our core for later access. We then added onClick functionality to each of the bin items so that the corresponding event would be fired when they were clicked, sort of like a small preview. This was simple enough to get going and basically just required us to create a function that would be run when request animation frame was fired. The next task was a bit more difficult.
Since the CBC was excited to use HTML5 tools and functionality, we decided to go with the HTML5 drag and drop over the jQuery one as we figured it was probably overkill again to go with jQuery. The sad part about this is, is that the HTML5 drag and drop is pretty messy and wasn’t something that I could just common sense together ( as I found out the hard way ). Tho it is all done through listeners, it heavily relies on some weird event functions that I’ve never used before, such as preventDefaults and stopPropogation to name a few. Scott and I scowered over the documentation for the better part of the morning to get this working in a very basic sense. Shortly after lunch we got it working and were ready to start implementing the actual puzzle part of the demo.
Our next step was to on a button click, attempt to play all of the clips that the user had assembled in our, for lack of a better term, timeline box. It would go through each of the events, play it until its end time, and then go onto the next event if there was one. This was one of the cooler pieces of code that I’ve had the opportunity to write in the last little while as it was asynchronous and involved a good bit of recursion. The code itself wasn’t the pretty thing I’ve ever written ( as im sure Bobby can vouch for haha ), but it was fun to write and made me really sit down and think about how to solve the problem. The code block for this was as follows:
<pre>var ridinSpinnas = function( options, cb ) {
if ( audioElement.currentTime >= options.end || audioElement.currentTime === audioElement.duration ) {
cb && cb();
} else if ( !stopSpinnin ) {
requestAnimFrame( function(){
ridinSpinnas( options, cb );
});
}
};
var getNextChild = function( children ) {
var increment = function() {
playingIndex++;
if ( playingIndex >= itemsLength ) {
audioElement.pause();
playingIndex = 0;
} else {
getNextChild( children );
}
},
itemsLength = children.length,
childsChildren = children[ playingIndex ].children,
currentNode = children[ playingIndex ],
options;
if ( childsChildren.length > 0 ) {
options = playingEvents[ childsChildren.item( 0 ).id ];
if ( options.start !== lastEnd ) {
audioElement.currentTime = options.start;
}
lastEnd = options.end;
audioElement.play();
addClass( currentNode, "cbc-puzzle-playing" );
}
if ( options ) {
requestAnimFrame( function() {
ridinSpinnas( options, function() {
removeClass( currentNode, "cbc-puzzle-playing" );
increment();
});
});
} else {
increment();
}
};</pre>
Excuse the variable names, but other than that its a cool piece of code. Essentially we call our getNextChild function, which then gets the first audio clip that we are going to play. We pass it into our request animation frame function and let it spin ( we ridin spinnas yo ). We also pass in a callback because of its asynchronous nature, we tell it to fire the callback once its done. Inside our callback we then either finish or call ourself again ( getNextChild ) and continue from there. I think its pretty neat.
It is reasons like this that I love programming so much and really reinforces why I love doing this so much. Even tho im sure its been done 100000x before, it is cool to sit down and do it by myself and to see the outcome first hand. I love that each and every week im being tested with new problems and have to think up new solutions to solve them. There is never a shortage of unique and challeneging problems and I love it!
The second day Scott wasn’t around due to school commitments, so I was flying solo here. Essentially what needed to be finished was some end game logic and some logic to lock a piece in place if it is found to be in the right place when the submit button is clicked. This took me a while to get up and running and still has a few bugs with it in some fringe cases, but for the most part is finished. If I had one more day I think I would have it perfect, but I guess that can be said for a lot of things
. Chris and I also threw togethor a randomizer function to randomize the data being entered ( scramble the words in the word bin ) and a readInJSON function for, well, reading in JSON events. After this we headed over to the CBC office downtown toronto and worked with Sean and another designer there on getting there design incorporated with our code. There were a few issues with CSS collisions and such, but for the most part it all started to come togethor. We saw our crappy looking demo looking all nice and shiny now, which is always a good feeling. We were also able to identify a few bugs here as well, which although sort of sucks, is nice that we had the opportunity to sit down with the designers and go over everything. All in all, it was an amazing two days and I can’t wait for when this goes live on CBC‘s website
Im sure you all want to see what we have done over the last two days, so here are two small demos showcasing what we have done, enjoy!
http://scotland.proximity.on.ca/dseif/cbc-puzzle/puzzleCSS/
The above is pretty self explanatory, drag onto timeline, click play to hear, submit to validate. Fun ensues.
http://scotland.proximity.on.ca/dseif/cbc-puzzle/editor.html
Above made by Bobby and Chris, hold down the z key to capture audio fragments and let go to stop the capture. Click on it to play the capture and hit enter when focused on it to enter text for it.
ALso, here are a few pics of the Toronto Mozilla office and one of the CBC.





