Instilling agile values at the Seattle Scrum Gathering

Making a layered brightcove player using the player api and beml



My goal was to build a Brightcove player that the layers the videoplayer and playlist in the same space with a way of toggling from the one to the other. I wanted to create minimal code external to the player and I didn’t want to do any custom Flash development.

Brightcove Experience Markup Language (BEML)

Brightcove offers their customers the ability to customize players via an XML extension called BEML which has a complete, if terse, DTDDoc.

I started with the BEML for a standard player template Video with Dropdown.

It contains the video player and the playlist layout I want to use. I basically want to stack the one on top of the other.

I duplicated it, renamed it and then edited the BEML.

BEML layout is pretty straightforward. It reminded me of java AWT. Components are laid out in canvasses with either vertical (VBox) or horizontal (HBox) arrangements.

<Runtime>
<Theme name=”Deluxe” style=”Light”/>
<Layout id=”application” boxType=”vbox”>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</Layout>
</Runtime>

And there is an element called ViewStack which takes any child components and layers them one on top of the other.

So, the first change was to place the UI within a ViewStack and then make sure the children of that ViewStack are the layers I want (if I didn’t wrap the components correctly the playlist combobox would be one layer and the playlist another).

<Runtime>
<Theme name=”Deluxe” style=”Light”/>
<Layout id=”application” boxType=”vbox”>
<ViewStack id=”viewStack” selectedIndex=”0″>
<VBox>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
</VBox>
<VBox>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</VBox>
</ViewStack>
</Layout>
</Runtime>

Next, I need a component that lets me toggle back and forth from the player to the playlist and back. I chose to use a simple link. I placed it directly below the ViewStack.

<VBox width=”100%” hAlign=”right” height=”24″>
<Spacer height=”3″/>
<Link id=”moreOrLessLink” text=”Show more video…”/>
</VBox>

Next, I added some text below the videoplayer for the title and short description of the video currently loaded into the player.

<HBox>
<Spacer width=”6″/>
<VBox>
<TitleLabel id=”maintitle” height=”18″ text=”{videoPlayer.video.displayName}” truncate=”true”/>
<Label multiline=”true” height=”54″ text=”{videoPlayer.video.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”6″/>
</HBox>

Finally, some inline CSS as allowed within the BEML dtd in order to have the text fit in the TitleLabel I just added and here’s the complete BEML for the revised player:

<Runtime>
<Theme name=”Flat” style=”Light”/>
</Style>
<Style id=”maintitle”><![CDATA[ .titleText
{
font-size:16;
font-weight:bold;
}
]]></Style>
<Layout id=”application” boxType=”vbox”>
<ViewStack id=”viewStack” selectedIndex=”0″>
<VBox>
<VideoPlayer id=”videoPlayer” height=”275″ video=”{videoList.selectedItem}”/>
<Spacer height=”3″/>
<HBox>
<Spacer width=”6″/>
<VBox>
<TitleLabel id=”maintitle” height=”18″ text=”{videoPlayer.video.displayName}” truncate=”true”/>
<Label multiline=”true” height=”54″ text=”{videoPlayer.video.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”6″/>
</HBox>
</VBox>
<VBox>
<ComboBox id=”playlistCombo” height=”25″/>
<List id=”videoList” rowHeight=”75″ automaticAdvance=”true” data=”{playlistCombo.selectedItem.videoDTOs}” itemLeading=”2″ selectOnClick=”true”>
<ListItem boxType=”hbox”>
<Spacer width=”8″/>
<VBox width=”80″ height=”74″ vAlign=”middle”>
<ThumbnailButton height=”60″ data=”{currentItem}” source=”{currentItem.thumbnailURL}”/>
</VBox>
<Spacer width=”7″/>
<VBox>
<Spacer height=”3″/>
<TitleLabel height=”18″ text=”{currentItem.displayName}” truncate=”true”/>
<Label height=”52″ multiline=”true” text=”{currentItem.shortDescription}” truncate=”true”/>
</VBox>
<Spacer width=”3″/>
</ListItem>
</List>
</VBox>
</ViewStack>
<VBox width=”100%” hAlign=”right” height=”24″>
<Spacer height=”3″/>
<Link id=”moreOrLessLink” text=”Show more video…”/>
</VBox>
</Layout>
</Runtime>

I did the rest of the color customizations in the publishing tools in Brightcove Studio.

This only addresses the UI of the player. I now need to wire up events.

Brightcove Player API for Javascript

Now I need to enable toggling between the player and playlist when someone clicks on the link. Brightcove doesn’t enable this within BEML itself. You need to interact with the player externally using the Player API.

The first step is to make sure your player is enabled for the Javascript/Actionscript API. This is a checkbox on the Global Tab of the player settings. It is by default unchecked.

Now, you need to load the Brightcove Javascript library. I loaded the combined js file as described in the Brightcove help page.

Brightcove supplies an API document.

When a Brightcove player loads in a page, it calls an onTemplateLoaded method that you can place in the page to gain access to Brightcove’s objects and interact with the player. There are examples of this on a dozen sites.

function onTemplateLoaded(experienceID) { /*insert code here*/ }

For encapsulation, I’ll create my own Javascript object. Construct it in this method passing the experienceID.

function onTemplateLoaded(experienceID) { new SnsCompactListVideoPlayer(experienceID); }

In the constructor, I obtain a reference to the Brightcove module object, lookup the link element by its ID then add an event listener for click events.

function SnsCompactListVideoPlayer(experienceID)
{
var playerExperience = brightcove.getExperience(experienceID);
var experienceModule = playerExperience.getModule(APIModules.EXPERIENCE);

this.moreOrLessLink = experienceModule.getElementByID(“moreOrLessLink”); //the link that toggles between the videoplayer and the playlist
this.viewStack = experienceModule.getElementByID(“viewStack”);//the ui element that contains the videoplayer in one stack and the playlist in another
this.videoPlayer = experienceModule.getElementByID(“videoPlayer”);//the video player ui element
this.videoList = experienceModule.getElementByID(“videoList”);
if (this.moreOrLessLink != null && this.viewStack != null && this.videoPlayer != null)
{
//toggle between videoplayer and playlist based on clicks
this.moreOrLessLink.addEventListener(“elementClick”, bindMethodToObject(this.togglePlayer,this));
//when a video plays make sure the videoplayer element is visible
this.videoPlayer.addEventListener(BCMediaEvent.PLAY, bindMethodToObject(this.togglePlayerToPlay, this));
}
}

I had to bind the click event to the instance of the video player — otherwise when the event fires, the this keyword references the calling page not the player instance. I did this using the apply method.

function bindMethodToObject(method, object)
{
return function() { return method.apply(object, arguments); }
}

In the event handler, I check which layer of the ViewStack is topmost (selectedIndex) and switch to the other one making sure to pause the video if it is currently playing whenever someone clicks to view the playlist.

SnsCompactListVideoPlayer.prototype.togglePlayer = function(e)
{
if (this.viewStack.getSelectedIndex() == 0)
{
this.viewStack.setSelectedIndex(1);
this.moreOrLessLink.setText(“Return to player…”);
if (this.videoPlayer.isPlaying())
{
this.videoPlayer.pause();
}
}
else
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}

I also wired an event to the video player to make sure that whenever the player plays, it becomes the selectedIndex in the ViewStack. This handles whens someone clicks on a video in the playlist.

/*
* Simon & Schuster Compact List Video Player
* Script by Ken Judy
* May 1, 2011
*/

function SnsCompactListVideoPlayer(experienceID)
{
var playerExperience = brightcove.getExperience(experienceID);
var experienceModule = playerExperience.getModule(APIModules.EXPERIENCE);

this.moreOrLessLink = experienceModule.getElementByID(“moreOrLessLink”); //the link that toggles between the videoplayer and the playlist
this.viewStack = experienceModule.getElementByID(“viewStack”);//the ui element that contains the videoplayer in one stack and the playlist in another
this.videoPlayer = experienceModule.getElementByID(“videoPlayer”);//the video player ui element
this.videoList = experienceModule.getElementByID(“videoList”);
if (this.moreOrLessLink != null && this.viewStack != null && this.videoPlayer != null)
{
//toggle between videoplayer and playlist based on clicks
this.moreOrLessLink.addEventListener(“elementClick”, bindMethodToObject(this.togglePlayer,this));
//when a video plays make sure the videoplayer element is visible
this.videoPlayer.addEventListener(BCMediaEvent.PLAY, bindMethodToObject(this.togglePlayerToPlay, this));
}
}

function bindMethodToObject(method, object)
{
return function() { return method.apply(object, arguments); }
}

SnsCompactListVideoPlayer.prototype.togglePlayer = function(e)
{
if (this.viewStack.getSelectedIndex() == 0)
{
this.viewStack.setSelectedIndex(1);
this.moreOrLessLink.setText(“Return to player…”);
if (this.videoPlayer.isPlaying())
{
this.videoPlayer.pause();
}
}
else
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}
SnsCompactListVideoPlayer.prototype.togglePlayerToPlay = function(e)
{
if (this.viewStack.getSelectedIndex() == 1)
{
this.viewStack.setSelectedIndex(0);
this.moreOrLessLink.setText(“Show more video…”);
}
}

Microsoft error reporting irony

Speaking in Seattle [Scrum Gathering]

I’m expanding my talk from last October’s Agile NYC for the spring Seattle Scrum Gathering.

Instilling Agile Values – A Manager’s Perspective Tuesday, May 17th, 3:30pm

The scale and speed of an agile adoption are external measures that don’t speak to the founding values of the practice. Collective ownership, continuous improvement and trust are hard won but lead to craftsmanship and joy. They are enabling conditions for innovation and beneficial change.

I will retrospect on my contributions both positive and negative towards cultivating these values in two organizations. The first was a practice that matured over four years, led to a new mission for the team and direct collaboration with the founder and CEO. The second is a team establishing its own agile practice after winding down an engagement with a much larger agile offshore team.

What will I do more off? What will I do less of? What impediments got in the way?

The existential joys of agile practice: angel on your shoulder

At Agile NYC I presented a pecha kucha. 20 slides. 20 seconds per slide. This is the fourth and final part.

Angel on your shoulder

play at your own riskAgile values call for honesty and trust. A shared ambition to do better and be better while causing each other less unnecessary pain.

I try to remember this in one on ones, retrospectives, coaching and in reflecting on my own decisions and actions.

The great thing about these values is that even as you strive towards them your co-workers will give you permission to demand more of them.

Just as they will demand more of you.

AngelThis demand gives you an angel on your shoulder. Watching you as you work. It inspires even as it shames you into substantial actions that go against your nature. And you do this because your team needs you to.

You invest in the hard daily work of adjusting your own bad habits one behavior at a time in the interests of the people you work with and the work you do together.

This isn’t easy. It’s mortifying. It’s scary.

TeamBut the reward is that you get to be the same person with your boss that you are with your peers that you are with your staff.

The reward is that you get to work at your best with other people working at their best.

And you carry that potential with you as you move on to other projects and other teams.

Building blocksUltimately, I want more than success on a project or in a particular job. I want a career.

I want to be proud of my accomplishments and I want to be proud of who I was as I attained them.

I want to spend my life loving what I do.

And I want to build things that are useful and delightful to people.

My pecha kucha topic was inspired by Samuel Florman’s book, The Existential Pleasures of Engineering

The main goal has always been to understand the stuff of the universe, to consider problems based on human solution, and to follow through to a finished product.

Existential delight has been the reward every step of the way…

— Samuel C. Florman