android 電視盒下XBMC源碼功能的簡單分析


XBMC  是一個優秀的自由和開源的(GPL)媒體中心軟件。XBMC最初為Xbox而開發,現在可以運行在Linux、OSX、Windows系統。 2003年,一些興趣相投的程序員 創建了這個項目。XBMC是一個非盈利的項目,由遍布世界各地的自願者開發維護。超過50名軟件開發人員為XBMC作出貢獻,還有超過100名翻譯人員努力擴大它的應用范圍,使它支持超過30種語言。

 

     由於XBMC一開始設計就是傾向於遙控輸入,自身的框架極其強大,容易擴展,用在電視盒上面剛好可以補充小公司在內容不足時的替代品。值得慶幸的是,XBMC的android 源碼也開源了,android 電視盒的開發者可以學習或者拿過來改造了。前一篇寫xbmc默認中文顯示的文章:點擊打開 。

    XBMC官方網站:點擊打開 。 

 也可直接下載:

  $ git clone git://github.com/xbmc/xbmc.git

 XBMC的WIKI: 點擊打開 。 


 

  最近一直在負責xbmc 的擴展,大致對xbmc的結構比較清晰,今天不講結構目錄,網上大把。主講一些控件的使用的數據填充等。 大致會講到從一個界面的形成到界面上的元素的交互這方面,基本可以滿足一般開發者對現有XBMC簡單的界面擴展需要。

 先上一張效果圖

 

1):界面的繼承

   XBMC使用的是C++編寫的界面,所有眼睛能看到的界面都是繼承於CGUIWindow(Dialog 繼承於CGUIDialog),XBMC又分為不同的類別,比如音樂、視頻、圖片、天氣等,每個類別分別有一個Base界面繼承自CGUIWindow用來作為該類別的基類,比如視頻的基類為:CGUIWindowVideoBase,假如你要為視頻新增一個界面,那么可以繼承CGUIWindowVideoBase,實現這個類的一些虛承數即可,非常方便。

  以我為視頻增加一個縮略圖展示界面的頁面為例,代碼為:

CGUIWindowVideoThumbList::CGUIWindowVideoThumbList( void)

        :CGUIWindowVideoBase(WINDOW_VIDEO_THUMBLIST,"MyVideoThumb.xml"

  A. WINDOW_VIDEO_THUMBLIST定義在源碼里的:xbmc/guilib/Key.h ,代碼為:

#define WINDOW_VIDEO_THUMBLIST              10026

  這個常量用來代表這個界面,要使用這個界面可以直接使用,比如打開或者顯示該界面可以:

 g_windowManager.ActivateWindow(WINDOW_VIDEO_THUMBLIST);

 另外,想要讓XBMC認出這個界面還需要在xbmc/Application.cpp 初始化時添加進來,代碼塊位於:

bool CApplication::Initialize(){
   ……
g_windowManager.Add( new CGUIWindowVideoThumbList);
……
}

 

 

 B.MyVideoThumb.xml這個文件代表界面元素,可以理解成android 的xml界面,但編寫方式和控件的排列方面都不相同,關於界面控件的排布齋在第2點詳細說明。到此為止,一個新的界面就算是完成了,下面說說如何在xml上畫界面。

 注意:需要在Makefile文件將你新增的文件寫進去,以便編譯時能夠順利編進去。

2):界面元素

XBMC所支持的控件列表:點擊打開 。 

 默認界面存放於android/addons/skin.confluence/720p目錄,這里面包含了所有界面的XML,對應的素材包括:聲音、字體、語言文字、圖片、顏色等也一並在android/addons/skin.confluence此目錄,最后生成build.bat文件。

注意:一些經常用的或者通用的布局,可以寫在Includes.xml文件里面,以后有需要用到的可以直接寫在你需要的xml上,比如:

<include>CommonBackground</include>

以一個panel的控件的XML為例,代碼如下:

 <control type="group">

         < include >VisibleFadeEffect </ include >
             < control  type ="panel"  id ="8000" >類型panel,id為8000
                 < posx >180 </ posx > 位於界面x 軸為180
                 < posy >20 </ posy >  位於界面y軸為20
                 < width >1160 </ width > panel 的寬度的1160
                 < height >590 </ height > panel 的高度為590
                 < onleft >9000 </ onleft > 遙控按向左鍵時如果焦點還在panel里面,並且己經是最左邊一個元素時,將焦點切換到ID為9000的控件上
                 < onright >60 </ onright > 遙控按向右鍵時如果焦點還在panel里面,並且己經是最右邊一個元素時,將焦點切換到ID為60的控件上
                  < onup >1000 </ onup > 遙控按向上鍵時如果焦點還在panel里面,並且己經是最頂一個元素時,將焦點切換到ID為1000的控件上
                  < ondown >1000 </ ondown > 遙控按向下鍵時如果焦點還在panel里面,並且己經是最底一個元素時,將焦點切換到ID為1000的控件上
                  < viewtype  label ="21371" >list </ viewtype > 顯示類型為列表
                 < pagecontrol >60 </ pagecontrol > 與下面 scrollbar綁定,作為該panel的滾動控件 
                  < scrolltime  tween ="sine"  easing ="out" >200 </ scrolltime >拖動延時
                 < preloaditems >2 </ preloaditems >預加載項目2
                 元素默認時的控件高度200寬度220,該薦包括一個默認無獲得焦點的image(圖片)和未獲得含焦點的label(文字)

        <itemlayout height="200" width="220"> 
                    <control type="image"> 類型image
                        <posx>1</posx> 位於panel里面的位置是x 軸1
                        <posy>0</posy>位於panel 里面的位置 是y軸0
                        <width>180</width>image寬度180
                        <height>160</height> image高度160
                        <aspectratio>scale</aspectratio>不論圖片大小填充整個圖片的寬高.keep 為保持圖片的大小不拉伸。更多請 點擊 。
                        <bordertexture border="5">folder-nofocus.png</bordertexture>image邊框紋理圖片
                        <bordersize>5</bordersize>邊框大小
                        <texture background="true">$INFO[Listitem.Icon]</texture>image圖片,ListItem.Icon為獲取CFileItemPtr里面的數據,后文會介紹
                    </control>
                    <control type="label">類型label
                        <posx>88</posx>位於panel里面的位置是x 軸88
                         <posy>160</posy>位於panel 里面的位置 是y軸160
                         <width>180</width>label寬度為180
                        <height>25</height>label高度為25
                        <font>font50caps_title</font> 文體類型,該字體定義於:xml同級目錄的Font.xml里面,也可以自行設置filename與size
                        <textcolor>white</textcolor>文體顏色
                        <selectedcolor>selected</selectedcolor>選中時顏色 
                        <align>center</align>位於itemLayout的中間x方向
                        <aligny>center</aligny>位於itemLayout的中間y方向
                        <info>ListItem.Label</info>顯示信息同樣獲取自CFileitemPtr,也可自行指定
                    </control>
                    
                </itemlayout>
                元素獲得焦點時的控件高度200寬度250,該薦包括一個默認無獲得焦點的image(圖片)和未獲得含焦點的label(文字)

        <focusedlayout  height="200" width="250">
                    
                    <control type="image">
                        <posx>1</posx>
                        <posy>0</posy>
                        <width>180</width>
                        <height>160</height>
                        <aspectratio>scale</aspectratio>
                        <bordertexture border="5">folder-focus.png</bordertexture> 獲取焦點時的圖片
                        <bordersize>5</bordersize>
                        <texture background="true">$INFO[Listitem.Icon]</texture>
                    </control>
                    <control type="label">
                        <posx>88</posx>
                        <posy>160</posy>
                        <width>180</width>
                        <height>25</height>
                        <font>font50caps_title</font>
                        <textcolor>white</textcolor>
                        <selectedcolor>selected</selectedcolor>
                        <align>center</align>
                        <aligny>center</aligny>
                        <info>ListItem.Label</info>
                    </control>
                </focusedlayout>
            </control>
            <control type="scrollbar" id="60">滾動條
                <posx>1250</posx>
                <posy>20</posy>
                <width>25</width>
                <height>590</height>
                <onleft>8000</onleft>
                <onright>9000</onright>
                <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
                <texturesliderbar border="2,16,2,16">ScrollBarV_bar.png</texturesliderbar>
                <texturesliderbarfocus border="2,16,2,16">ScrollBarV_bar_focus.png</texturesliderbarfocus>
                <textureslidernib>ScrollBarNib.png</textureslidernib>
                <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
                <onleft>500</onleft>    
                <onright>2</onright>
                <showonepage>false</showonepage>
                <orientation>vertical</orientation>方向
            </control>
        </control>

 

3):界面需要實現的幾個虛函數

頭文件代碼為:

#include  " GUIWindowVideoBase.h "
#include  " ThumbLoader.h "
#include  " GUIWindowVideoNav.h "
class CGUIWindowVideoThumbList :  public CGUIWindowVideoBase
{
   public:
     
    CGUIWindowVideoThumbList( void);
     virtual ~CGUIWindowVideoThumbList( void);

     virtual  bool OnAction( const CAction &action);動作回調函數,不怎么用到
     virtual  bool OnMessage(CGUIMessage& message);消息回調函數,處理界面元素的點擊消息,有點像android 的handler消息機制 

     virtual  bool Update( const CStdString &strDirectory);當界面完成一個更新或者顯示一開始顯示時調用

      void LoadItemByDirectory( const CStdString &strDirectory);

      void LoadItemByDirectory( const CFileItemList &items);


  protected:
    virtual  void OnInitWindow();初始化
    virtual  void OnWindowLoaded();加載完畢后
   
    int GetWindowSeletectedItem( int iControl);
   
   CFileItemList* m_vecItems;
   CFileItemList* itemList;
    bool load_done;

  
   CFileItemList* page_index_list;

   CStdString previous_path;
   
   CStdString next_path;

    int pageIndex;


        }; 

 以上幾個有添加注釋為必須實現函數,XBMC界面控制也基本在這幾個回調函數里面進行。

 

4): 數據的加載或者填充

普通的控件如Button、Label之類的加載文字,可以直接使用預定義好的全局方法SET_CONTROL_LABEL(controlID,label)來做。

 而列表加載需要做一個類型List的數據給CGUIMessage,代碼為:

 

bool CGUIWindowVideoThumbList::Update(const CStdString &strDirectory)
{     
   
   // if(!load_done){

      CFileItemList list; 
    GetDirectory( " plugin://plugin.video.XuZhiTV ",list);通過獲取目錄得到python插件的數據目錄

    itemList->Clear();
     for( int i= 0;i<list.Size();i++){循環填充進itemList
          
      CFileItemPtr pItem = list.Get(i); 
        
       if(strcmp(pItem->GetLabel().c_str(), " .. ")== 0)
         continue;
        CFileItemPtr cateItem( new CFileItem(pItem->GetLabel()));
        cateItem->SetPath(pItem->GetPath());
        itemList->Add(cateItem);
      }

   通過消息將列表廣播出去,加載列表 

      CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LOAD_CATEGORY_LIST_ID, 00, itemList);
      g_windowManager.SendMessage(msg);

//--------------------end------------------------

//-------------item list---------------------------
     CFileItemList firstList;
     GetDirectory(itemList->Get(0)->GetPath(),firstList);得到插件目錄的子目錄
//-------------------end-----------------------


    /*  load_done=true;
  
*/

    LoadItemByDirectory(firstList); 加載子項

  //}
  return true;
}

 

LoadItemByDirectory方法代碼:

void CGUIWindowVideoThumbList::LoadItemByDirectory( const CFileItemList &items){
    m_vecItems->Clear();
    page_index_list->Clear();
      for ( int i= 0;i<items.Size(); ++i)
      {
          CFileItemPtr pItem = items.Get(i); 
         if(strcmp(pItem->GetLabel().c_str(), " .. ")== 0)
             continue;
        CFileItemPtr item( new CFileItem(pItem->GetLabel()));
        item->SetThumbnailImage(pItem->GetThumbnailImage());獲取網絡上的圖片給上面panel 的image
         item->SetPath(pItem->GetPath());
        
         if(pItem->GetLabel().Find( " | ")> 0){
            item->SetIntParam(- 1);
            CFileItemPtr ptr( new CFileItem(pItem->GetLabel())); 獲取label給上面panel 的label
            ptr->SetPath(pItem->GetPath());
            page_index_list->Add(ptr);
             continue;
        } else{
            item->SetIntParam( 0);
        }
        item->SetIconImage( " DefaultVideoCover.png ");
        
        item->SetLabelPreformated( true);
        
        m_vecItems->Add(item);
      }廣播消息加載內容
     CGUIMessage refresh(GUI_MSG_LABEL_BIND, GetID(), CONTROL_LOAD_ITEM_LIST_ID,  00, m_vecItems);
      bool isRefresh= g_windowManager.SendMessage(refresh);
      if(isRefresh){
         
          int m_size=page_index_list[ 0].Size();
        CFileItemPtr ptr=page_index_list[ 0].Get( 0);
         if(m_size== 0){
            SET_CONTROL_HIDDEN(CONTROL_NEXT_ID);
            SET_CONTROL_HIDDEN(CONTROL_PREVIOUSE_ID);
            SET_CONTROL_LABEL(CONTROL_PAGE_COUNT_ID, "");
        } else{
            SET_CONTROL_LABEL(CONTROL_PAGE_COUNT_ID,ptr->GetLabel().Right( 6));
            SET_CONTROL_VISIBLE(CONTROL_NEXT_ID);
            SET_CONTROL_VISIBLE(CONTROL_PREVIOUSE_ID);
        }
        
         switch(m_size){
             case  0:
                previous_path= "";
                next_path= "";
                 break;
             case  1:{
                    CStdString control_text=ptr->GetLabel().Left(ptr->GetLabel().Find( " | "));
                     if(strcmp(control_text, " down ")== 0){
                        next_path=ptr->GetPath();
                    } else{
                        previous_path=ptr->GetPath();
                    }
                }
                 break;
             case  2:
                previous_path=ptr->GetPath();
                next_path=page_index_list[ 0].Get( 1)->GetPath();
                 break;
        }
     }

 

 5):點擊事件的處理

 

 點擊事件可以重寫onclick,也可以由OnMessage函數處理,都可以。處理非常簡單代碼為:

bool CGUIWindowVideoThumbList::OnMessage(CGUIMessage& message)
{
     if (message.GetMessage() == GUI_MSG_CLICKED)消息類型為點擊時,message不止可以處理點擊,還有很多事件可以處理。
    {
     int iControl = message.GetSenderId();獲得點擊控件的ID
     if(iControl == 2000){ID等於2000時
       //處理點擊時響 應的代碼
    }
  }
     return CGUIWindowVideoBase::OnMessage(message);

 更多關於XBMC功能源碼方面歡迎討論。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM