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功能源码方面欢迎讨论。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值