Monday, April 18, 2011

Communicating with data services of third party , YouTube sample - I

Hummingbird allow you communicate with external data services. you can do so, using the http services objects provided by HB. On this post i will show you how to communicate with the data services offered by Youtube, but you could adapt the sample to communicate with others services like the one offered for flickr, panoramio, facebook, etc.
following are two images showing the HB page at design time, with the elements needed to do the sample:




The elements found on the page are:

1. commonWidgets: this widget will allow us create the elements 3,5 and 9. id: database5_3
2. search videos: is a text component, when the user click on it, access the youtube data services, and get a video list corresponding to the words in the element 3 (textInput). id: database5_1
3. textInput: here you enter the words corresponding to the videos you want to get from youtube.
4. text: it show you the title and description of the video you are watching currently. id: database5_2
5. video player: it is the chromeless video player provided by youtube. it allow us play streamed videos directly from the YouTube's servers.
6. play button: play the video. id: database5_5
7. stop button: stop the video you are watching. id: database5_6
8. rewind button: rewind the video. id: database5_8
9. video list: this is an vBox component generated using the cwidgets, it shows you the video list corresponding to the videos that match your search criteria. it show you the videos in a paged way, and you can use the buttons below it to move between pages. When you click on a video on this list the video begins to play.
10. back video list: allow you get the previous video list page. id: database5_9
11. forward video list: allow you get the next video list page. id: database5_10
12. text: shows you the start and end videos showed on the video list, and the total of videos. id: database5_12
13. comments list: this is an vBox component generated using the cwidgets, it shows you the comments list corresponding to the video that is being played. it show you the comments in a paged way, and you can use the buttons below it to move between pages.
14. back comments list: allow you get the previous comments list page. id: database5_17
15. forward comments list: allow you get the next comments list page. id: database5_18
16. text: shows you the start and end comments showed on the comments list, and the total of comments. id: database5_19

The next pictures show you the HB page in action (on visit mode):



One of the things you must know when you try to use data services of third party is the way you will communicate with the data services and the format of the returned data. On this case we will get data from Youtube, so you will have to understand how works the YouTube API, so you must read this:

YouTube API protocol
YouTube API player

The above links will provide you with useful info in order to understand what we will do next.

A first question you could be asking yourself is ¿ why use the YouTube's video player instead the HB video player ? Youtube don't allow you access flv videos directly, instead they provides two video players which allow us play the videos. Maybe by googling sometime you could find some hacks to access flv videos directly from YouTube, but there is not guarantee it keep working , because YouTube is constantly closing that hacks.

Following you can see the scripts of the page in the scripts editor:


and next is the code of every event script:

imports event:

import mx.controls.Alert;
import mx.collections.ArrayCollection;


// create our webService object
global.serv=page.newHttpService();
global.serv.service.url="http://gdata.youtube.com/feeds/api/videos";
global.serv.service.resultFormat="e4x";
global.serv.service.method = "GET";

// the next webservice will be used to retrieve the comments for the played video
global.servComments=page.newHttpService();
global.servComments.service.resultFormat="e4x";
global.servComments.service.method = "GET";

/*
every time a search is made we will save
the results videos in the next variable
*/
global.videos=null;
// the next variable will be our video list component container
global.vb=null;
// the next variable will show us the last canvas of the video list that was higlighted
global.lastCanvas=null;
// the next 3 variables will be used to control the movement of the video list pages
global.startIndex=1;
global.maxResults=10;
global.totalResults=0; // when searching this will be filled with the total numbers of videos



// the next 3 variables will be used to control the movement of the comments list pages
global.startIndexComments=1;
global.maxResultsComments=30;
global.totalResultsComments=0; // when searching this will be filled with the total numbers of comments for the selected video
// the next variable will save the comments for a video
global.comments=null;
// the next variable will be our comments list container
global.vbComments=null;
// the next variable will show us the last canvas of the comments list that was higlighted
global.lastCanvasComments=null;
// the next variable will save the url of the comments for the video being played
global.urlComments=null;

// needed to use the chromeless player of youtube
page.allowDomain("www.youtube.com"); // this allows HB access the chromeless YouTube video player

global.vidPlayer=null; // this will be the chromeless videoPlayer Object

functions event:


function clearCommentsList()
{
if (global.vbComments!=null)
global.vbComments.removeAllChildren();


}



function buildCommentsList()
{
/*
this function take the data of the comments and build a nice
comments list
*/

clearCommentsList();

// get a reference to the cWidget
var cw=page.findObject2("/database5_3");

// get a reference to the vertical box created
var vb=global.vbComments;
if (vb==null)
{
Alert.show("vbox for comments list not created");
return;
}


// loop over our comments list
for (var i = 0 ; i < global.comments.length ; i++)
{
// this is the i-esimal comment of the list


/* the data fields for a comment are:
comment.title
comment.published
comment.updated
comment.content
comment.authorName
*/



// create a text object to show some text of the video
var text=cw.content.application.new_text();
text.y=6;text.x=4;
text.width=vb.width-24;
//text.height=100; // component will be autosized according content
text.autoResize=true;
text.htmlText="TITLE: "+global.comments[i].title+"\nAUTHOR: "+global.comments[i].authorName+"\n"+global.comments[i].content;
text.setStyle("color", 0x000000);
text.id="text"+i;
//text.truncateToFit=true; // dont need truncateToFit
//text.addEvents("click");
text.toolTip=global.comments[i].content;
text.mouseChildren=false;



// create a canvas an locate every above object inside it
var can=cw.content.application.new_canvas();
can.setStyle("backgroundColor", 0xffffff);
can.setStyle("borderStyle", "solid");
can.setStyle("borderColor", 0x000000);
can.setStyle("borderThickness", 1);
can.autoLayout=true;
can.addChild(text);

//can.height=text.y+text.height+4; // canvas will be autoLayout
//can.width=text.x+text.width+4; // canvas will be autoLayout
can.id="canvCommentsList_"+i;
/*
next line: the events of the canvas (rollover,rollOut, etc.) will begin with commentsList prefix
*/
can.addEvents("rollOver|rollOut|click|mouseWheel",'|','commentsList');
can.hScrollPolicy("off");
can.vScrollPolicy("off");
can.buttonMode=true;

// add the canvas with its childrens to the container vBox
vb.addChild(can);

}

} // end of function buildCommentsList




function showOneOfComments()
{
// set the a message like this: 1-10 of 123
var c=page.findObject2("/database5_19");
if (c!=null)
{
c.text=global.startIndexComments+"-"+(global.startIndexComments+global.maxResultsComments-1)+" of "+global.totalResultsComments;
}
}


function searchComments()
{
// this function search for the comments of a video
if (global.urlComments==null)
return;

var startIndex=global.startIndexComments;
var maxResults=global.maxResultsComments;

global.servComments.service.url=global.urlComments;
var params=new Object();
params["max-results"]=maxResults;
params["start-index"]=startIndex;

global.servComments.call(params,"serverResponseComments","serverErrorComments");

}

function create_vBoxComments()
{
var cw=page.findObject2("/database5_3");

// creates a vBox which will be the container for the comments list
var vb=cw.content.application.new_vBox();
// set styles for vBox
vb.setStyle("borderStyle", "solid");
vb.setStyle("borderColor", 0x000000);
vb.setStyle("borderThickness", 1);
vb.setStyle("verticalGap", 0); // vertical space between childrens

vb.height=473;
vb.width=397;
vb.x=34;vb.y=544;
vb.setStyle("backgroundColor", 0xffffff);
page.content.addChild(vb);
global.vbComments=vb;

} // end of function vBoxComments



function setButtonMode()
{
// set buttonMode for search videos button
var pb=page.findObject2("/database5_1");
pb.buttonMode=true;
pb.mouseChildren=false; // this is a text so we need this too

// set buttonMode for the player buttons (play,stop,rewind)
var pb=page.findObject2("/database5_5");
pb.buttonMode=true;
var pb=page.findObject2("/database5_6");
pb.buttonMode=true;
var pb=page.findObject2("/database5_8");
pb.buttonMode=true;

// set button mode for videolist buttons (back video list,forward video list)
var pb=page.findObject2("/database5_9");
pb.buttonMode=true;
var pb=page.findObject2("/database5_10");
pb.buttonMode=true;

// set button mode for commentslist buttons (back comments list,forward comments list)
var pb=page.findObject2("/database5_17");
pb.buttonMode=true;
var pb=page.findObject2("/database5_18");
pb.buttonMode=true;

}

function showOneOf()
{
// set the a message like this: 1-10 of 32456
var c=page.findObject2("/database5_12");
if (c!=null)
{
c.text=global.startIndex+"-"+(global.startIndex+global.maxResults-1)+" of "+global.totalResults;
}
}


function searchVideos()
{
/*
here we send the search request to youtube
*/

//Alert.show(global.serv);

var searchString=global.t.text;
var startIndex=global.startIndex;
var maxResults=global.maxResults;

//global.serv.service.url=global.serv.service.url + "?vq=" + searchString + "&max-results=10";
//global.serv.call(null,"serverResponse","serverError");

var params=new Object();
params["vq"]=searchString;
params["max-results"]=maxResults;
params["format"]=5; // check this video format
params["start-index"]=startIndex;
global.serv.call(params,"serverResponse","serverError");

} // end of search videos function


function create_vBox()
{
var cw=page.findObject2("/database5_3");

// creates a vBox which will be the container for the video list
var vb=cw.content.application.new_vBox();
// set styles for vBox
vb.setStyle("borderStyle", "solid");
vb.setStyle("borderColor", 0x000000);
vb.setStyle("borderThickness", 1);
vb.setStyle("verticalGap", 1); // vertical space between childrens

vb.height=919;
vb.width=430;
vb.x=463;vb.y=97;
vb.setStyle("backgroundColor", 0xffffff);
page.content.addChild(vb);
global.vb=vb;


} // end of function create_vBox


function clearVideoList()
{
if (global.vb!=null)
global.vb.removeAllChildren();


}


function buildVideoList()
{
/*
this function take the data of the videos and build a nice
video list
*/

clearVideoList();

// get a reference to the cWidget
var cw=page.findObject2("/database5_3");

// get a reference to the vertical box created
var vb=global.vb;
if (vb==null)
{
Alert.show("vbox for video list not created");
return;
}

// loop over our video list
for (var i=0; i < global.videos.length ; i++)
{
// this is the i-esimal video of the list

// creates an image object to show a thumbnail for the video
var im=cw.content.application.new_image();
im.source=global.videos[i].thumbnail;
im.id="im"+i;
//im.addEvents("click");
im.y=6;im.x=4;
im.height=150;im.width=150;

// create a text object to show some text of the video
var text=cw.content.application.new_text();
text.htmlText=""+global.videos[i].title+""+"\n"+global.videos[i].description;
text.y=im.y;text.x=im.x+im.width+2;
text.height=100;
text.width=250;
text.setStyle("color", 0x000000);
text.id="text"+i;
text.truncateToFit=true;
//text.addEvents("click");
text.toolTip=global.videos[i].title+"\n"+global.videos[i].description;
text.mouseChildren=false;

/*
// create a play button
var but=cw.content.application.new_button();
but.label="play";
but.height=15;
but.x=90;but.y=140;
but.id="button"+i;
but.visible=false;
but.addEvents("click");
but.data=i;
*/

// create a canvas an locate every above object inside it
var can=cw.content.application.new_canvas();
can.setStyle("backgroundColor", 0xffffff);
can.setStyle("borderStyle", "none");
can.setStyle("borderColor", 0x000000);
can.setStyle("borderThickness", 1);
can.addChild(im);
//can.addChild(but); // si el boton es agregado despues del text inhibe el funcionamiento de los hyperlinks.
can.addChild(text);

can.height=im.y+im.height-30;
can.width=text.x+text.width+4;
can.id="canvVideoList_"+i;
// next line: the events of the canvas (rollover,rollOut, etc.) will begin with videoList prefix
can.addEvents("rollOver|rollOut|click|mouseWheel",'|','videoList');
can.hScrollPolicy("off");
can.vScrollPolicy("off");
can.buttonMode=true;

// add the canvas with its childrens to the container vBox
vb.addChild(can);
}


} // end of function buildVideoList


No comments:

Post a Comment