В процессе изучения YouTube API возникла идея написать YouTube плеер для Nokia N9. При выборе средства реализации выбор пал на набирающий обороты QML. Т.к. QML очень легко интегрируется с JavaScript, то получать фиды YouTube было решено именно в JSON (JavaScript Object Notation) формате. При создании пользовательского интерфейса на QML за основу был взят пример Flickr Mobile из QtSDK. Загруженный из фида список предоставляется пользователю в виде ListView или GridView и при щелке пользователя на выбранном видео оно открывается в установленном по умолчанию видео-плеере.
Далее в статье будет более подробно показано, как это все выглядит и как реализуется.
Выглядит это все примерно так:
Итак, для начала создадим функцию loadYouTube() на JavaScript, которая будет загружать JSON-объект с YouTube посредством HTTP запроса и парсить его. По умолчанию тег для поиска видео rssModel.tags выставим в Nokia N9 и количество отображаемого контента в 32. Далее — код этой функции:
Все загруженные и распарсенные данные с YouTube добавляем в QML ListModel:
Для отображения данных в том виде, в каком показано выше на скриншотах, мы добавляем созданную модель в model property для элементов Grid View и List View:
Когда пользователь щелкнет на выбранном элементе, мы вызываем метод Qt.openUrlExternally(), который откроет потоковое видео в дефолтном плеере:
Добавляем в приложение меню для выбора тэга и количества отображаемых элементов, кнопки для обновления контента и смены способа отображения результатов поиска и всё — плеер готов.
Далее в статье будет более подробно показано, как это все выглядит и как реализуется.
Выглядит это все примерно так:
Итак, для начала создадим функцию loadYouTube() на JavaScript, которая будет загружать JSON-объект с YouTube посредством HTTP запроса и парсить его. По умолчанию тег для поиска видео rssModel.tags выставим в Nokia N9 и количество отображаемого контента в 32. Далее — код этой функции:
- function loadYouTube(){
- var doc = new XMLHttpRequest();
- doc.onreadystatechange = function() {
- if (doc.readyState == XMLHttpRequest.DONE) {
- var jsresp = JSON.parse(doc.responseText);
- var entries = jsresp.feed.entry;
- var len = entries.length
- rssModel.clear();
- var vi=1;
- for (var i = 0; i < len; i++) {
- var obj = entries[i];
- rssModel.append( {
- number:
- i + 1,
- url:
- (function() {
- try {return(obj.id.$t.replace("http://gdata.youtube.com/feeds/api/videos/", ""));}
- catch(e) { return("(no title)"); }
- } )(),
- videoRTSP:
- (function() {
- try {
- return(obj.media$group.media$content[1].url);
- }
- catch(e) { return("(no title)"); }})(),
- videoHTTP:
- (function() {
- try {
- return(obj.media$group.media$content[0].url);
- }
- catch(e) { return("(no title)"); }})(),
- tags:
- (function() {
- try {
- return(obj.yt$statistics.viewCount);
- }
- catch(e) { return("(no title)"); }})(),
- photoType:
- (function() {
- try {
- return(obj.category[0].term);
- }
- catch(e) { return("(no title)"); }})(),
- description:
- (function() {
- try {
- return(obj.content.$t);
- }
- catch(e) { return("(no title)"); }})(),
- photoAuthor:
- (function() {
- try {
- return(trimString(obj.author[0].name.$t,35));
- }
- catch(e) { return("(no title)"); }})(),
- photoHeight:
- (function() {
- try {
- return(obj.media$group.media$thumbnail[0].height);
- }
- catch(e) { return("(no title)"); }})(),
- photoWidth:
- (function() {
- try {
- return(obj.media$group.media$thumbnail[0].width);
- }
- catch(e) { return("(no title)"); }})(),
- photoDate:
- (function() {
- try {
- return(obj.published.$t);
- }
- catch(e) { return("(no title)"); }})(),
- imagePath:
- (function() {
- try {
- return(obj.media$group.media$thumbnail[0].url);
- }
- catch(e) { return("(no title)"); }})(),
- title:
- (function() {
- try {
- return(trimString(obj.title.$t,35));
- }
- catch(e) { return("(no title)"); }})()
- });
- }
- console.log("Successfully")
- }
- }
- doc.open("GET", "http://gdata.youtube.com/feeds/api/videos?q="+rssModel.tags+"&orderby=viewCount&alt=json&max-results=32");
- doc.send();
- }
Все загруженные и распарсенные данные с YouTube добавляем в QML ListModel:
- ListModel{id:rssModel; property string tags :"Nokia N9";}
Для отображения данных в том виде, в каком показано выше на скриншотах, мы добавляем созданную модель в model property для элементов Grid View и List View:
- Mobile.GridDelegate { id: gridDelegate }
- GridView {
- id: photoGridView; model: rssModel; delegate: gridDelegate; cacheBuffer: 100
- cellWidth: (parent.width-2)/4; cellHeight: cellWidth; width: parent.width; height: parent.height - 1;
- }
-
- Mobile.ListDelegate { id: listDelegate }
- ListView {
- id: photoListView; model: rssModel; delegate: listDelegate;
- width: parent.width; height: parent.height; x: -(parent.width * 1.5); cacheBuffer: 100;
- }
Когда пользователь щелкнет на выбранном элементе, мы вызываем метод Qt.openUrlExternally(), который откроет потоковое видео в дефолтном плеере:
- MouseArea{
- id:listMouseArea
- anchors.fill: parent
- onClicked: Qt.openUrlExternally(videoRTSP);
- }
Добавляем в приложение меню для выбора тэга и количества отображаемых элементов, кнопки для обновления контента и смены способа отображения результатов поиска и всё — плеер готов.