一、項目概述
Mplayer。它支援大量的多媒體檔案格式,像常見的音頻檔案如mp3/wav/mid,常見的視訊檔案如avi/vcd/dvd/rm等等,各種視訊編/解碼方式也是應有盡有。
我們項目的目标是在liunx下,用QT做一個MPlayer皮膚,能夠實作播放器的常見
功能,如:播放、停止、快進、快退、上/下一曲等。并把程式移植到ARM平台上。
二、功能體驗
本節主要目的是讓大家在學習具體實作過程前,先體驗下播放器的功能。
1、PC端功能體驗
将“項目代碼/工程代碼”目錄下的mplayer.tar.gz拷貝linux系統中(主機環境配置好以後,參照第四節的實作過程)。
#tar xvfz mplayer.tar.gz
#./mplayer
2、目标平台功能體驗
l 将“項目代碼/工程鏡像”檔案夾中的zImage、rootfs.cramfs燒寫到目标闆(或者采用nfs方式)。分區情況為:
Boot: 0 - 40000 size=0x40000
Kernel:40000 – 240000 size=0x200000
Rootfs: 240000 -3740000 size=0x3500000
啟動參數為:
setenv root=1f02 init=/linuxrc rootfstype=cramfs console=ttySAC0,115200 display=sam240
setenv bootcmd setenv bootcmd nand read 30008000 40000 200000 /; go 30008000
l 啟動系統後運作:
#. ./Qtopia.sh
#cd mymplayer
#./mymplayer -qws
三、實作原理
先來考慮考慮如何為mplayer編寫前端界面的問題。有兩種思路,一種是把mplayer解剖,直接修改他裡面的代碼,這樣我們做得界面就能夠和mplayer一體了(當然也能夠通過link mplayer用到的任何的庫和.o文檔,把他無縫的內建在程式裡面);第二種方法就是mplayer所謂的slave模式。
mplayer '/home/linux/1.mp3' -quiet -slave
現在來探讨一下slave模式:所謂的slave模式,就是mplayer在運作過程中能夠接收使用者的輸入指令行,具體支援哪些指令行,能夠通過mplayer -input cmdlist這條指令來得到,在Mplayer源碼的slave.txt中也有對這些指令有詳細的講解。Slave模式下工作的Mplayer可以和系統的标準輸入、輸出進行資訊互動。我們可以用linux C程式設計來完成對slave模式工作的Mplayer進行控制和資訊擷取。
如:
mkfifo(“/tmp/fifo”,0777);
可以使用popen()來打開Mplayer
FILE* mp;
mp=popen(“mplyer /home/linux/1.mp3 -quiet –slave –input file=/tmp/fifo,”r”);
可以通過管道/tmp/fifo給mplayer發送指令,通過mp擷取mplay的傳回資料
如:system(“echo /”mute 0/” > /tmp/fifo”);//寫指令
fgets(buf,1000,mp);//讀取mplay傳回資料
而Qt給我們提供了更友善的實作方法。
通過定義一個QProcess對象調用已編譯好的Mplayer。
QProcess *process = new QProcess();
process->setProcessChannelMode(QProcess::MergedChannels);
Process->start(“mplayer –ac mad xxxxx”);
在指令中添加 -slave 和 -quiet就可以通過指令設定Mplayer實作相應的功能。在mplayer源碼中的,slave.txt中對這些指令有詳細的講解。
Process->start(“mplayer –slave –quiet –ac mad xxxxx”);
1、暫停功能
通過如下代碼可以設定Mplayer暫停。
process->write(“pause/n”);
執行這段代碼的時候如果是播放狀态就會暫停,暫停狀态時就會繼續播放。
2、擷取播放檔案的總時間和目前播放進度
執行下面代碼時,Mplayer将時間在标準輸出顯示。
process->write("get_time_pos/n");
process->write("get_time_length/n");
通過如下代碼即可讀出我們需要的資訊:
connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(back_message_slots()));
process有可讀取的資訊時,發出信号,在槽函數back_message_slots()中讀取資訊。
void MPlayer::back_message_slots()
{
while(process->canReadLine())
QString message(process->readLine());
//message即為讀取的資訊我們可以根據需要取我們要的資訊如
//檔案總時間為:ANS_LENGTH=23.00
//目前時間為:ANS_TIME_POSITION=23.00
}
3、快進功能
seek <value> [type]
Seek to some place in the movie.
0 is a relative seek of +/- <value> seconds (default).
1 is a seek to <value> % in the movie.
2 is a seek to an absolute position of <value> seconds.
下面代碼即可實作快進功能:
process->write(“seek ** 1/n”);
4、音量調節
volume <value> [abs]
Increase/decrease volume or set it to <value> if [abs] is nonzero.
Process->write(“volume -1/n”); //音量減小
Process->write(“volume +1/n”); //音量增加
5、靜音功能
mute [value]
Toggle sound output muting or set it to [value] when [value] >= 0
(1 == on, 0 == off).
process->write("mute 0/n"); //開啟靜音
process->write("mute 1/n"); //關閉靜音
6、定位視訊視窗
通過上面的代碼基本功能實作了,可是播放視訊的時候發現又彈出一個視窗。并沒有出現在我們的視窗裡。
如下代碼即可時間視窗的定位。
QString common = "mplayer -slave -quiet -ac mad -zoom movie/" + file_name + " -wid " + QString::number(widget->winId());
process->start(common);
紅色部分實作視窗的定位。Widget是一個QWidget對象。通過winId可以獲得一個數字,-wid既将視訊輸出定位到widget窗體部件中。
注意:-wid參數隻在X11、directX和OpenGL中适用。
四、PC環境下的實作過程
1、PC環境搭建
主機環境:Red Hat Enterprise Linux 5.0
交叉編譯工具:gcc-3.4.5-glibc-2.3.6
主機編譯工具:gcc-4.1.2
(1)主機端安裝mplayer
l 将“項目代碼/mplay源碼”目錄下的MPlayer-1.0rc2.tar.bz2、libmad-0.15.1b.tar.gz(1個mp3解碼庫)拷貝到linux系統中,如:/home/linux/mplayer目錄下
l 安裝libmad-0.15.1b.tar.gz
#tar xvfz libmad-0.15.1b.tar.gz
#cd libmad-0.15.1b
#./configure
#make
#mkdir /lib/lib
#mkdir /lib/include
#cp mad.h /lib/include
#cp .libs/libmad.a /lib/lib
l 安裝mplayer
#tar xvfj MPlayer-1.0.rc2.tar.bz2
#cd MPlayer-1.0rc2
#./configure --with-extraincdir=/lib/include --with-extralibdir=/lib/lib
#make install
此時可以試着播放一下mp3、avi等檔案了
# mplayer -ac mad 1.mp3
# mplayer -ac mad 2.avi
(2)安裝、移植qtopia-4.2.0
注:需要先按照5.2節将tslib按照好
l 将“項目代碼/qtopia源碼”目錄下的qtopia-opensource-src-4.2.0.tar.gz拷貝到linux系統中,如:/home/linux/Qtopia目錄下
# tar zxvf qtopia-opensource-src-4.2.0.tar.gz
# mv qtopia-opensource-4.2.0 source
# mkdir target //建立在source同級目錄下建立目錄target
修改源碼包
# cd source
# cd src/libraries/qtopiabase/
# cp custom-linux-cassiopeia-g++.h custom-linux-arm-g++.h
# cp custom-linux-cassiopeia-g++.cpp custom-linux-arm-g++.cpp
修改時區資訊
# vi src/libraries/qtopia/qtimezone.cpp
将114行的 /usr/share/zoneinfo/ 改為/Qtipia/zoneinfo/ ,儲存退出。
# vi src/settings/systemtime/settime.cpp
将318行的 /usr/share/zoneinfo/ 改為/Qtipia/zoneinfo/ ,儲存退出。
l 裁減Qtopia core的庫(下列操作後在螢幕上會出現一個光标,否則沒有光标。根據需求配置)
# vi qtopiacore/qconfig-qpe.h
首先注釋掉關于滑鼠光标的宏定義,讓程式運作時,觸摸屏中央有光标出現:
// Qtopia Core
/*
#ifndef QT_NO_QWS_CURSOR
# define QT_NO_QWS_CURSOR
#endif
*/
#ifndef QT_NO_QWS_MOUSE
# define QT_NO_QWS_MOUSE
#ifndef QT_NO_QWS_MOUSE_AUTO
# define QT_NO_QWS_MOUSE_AUTO
其它宏定義根據需要進行注釋。
儲存後将qconfig-qpe.h拷貝到global目錄。
# cp qtopiacore/qconfig-qpe.h qtopiacore/qt/src/corelib/global/qconfig-qpe.h (必須進行的操作)
注釋掉其他檔案裡的QT_NO_QWS_CURSOR的定義
# vi qtopiacore/qt/src/corelib/global/qfeatures.h
注釋掉如下内容:
#if !defined(QT_NO_QWS_CURSOR) && (defined(QT_NO_CURSOR))
#define QT_NO_QWS_CURSOR
儲存退出。
# vi qtopiacore/qt/src/corelib/global/qglobal.h
注釋掉以下内容:
//# define QT_NO_QWS_CURSOR
#vim qtopiacore/qt/tools/qvfb/qvfbshmem.cpp
注釋掉asm/page.h
//#include <asm/page.h>
#vim qtopiacore/qt/tools/qvfb/qvfbmmap.cpp
并修改如下内容
unsigned char *data;
uint data_offset_value = sizeof(QVFbHeader);
if (data_offset_value % PAGE_SIZE)
data_offset_value += PAGE_SIZE - (data_offset_value % PAGE_SIZE);
為:
const int page_size = getpagesize();
if (data_offset_value % page_size)
data_offset_value += page_size - (data_offset_value % page_size);
# vim src/libraries/qtopiabase/qmemoryfile_unix.cpp +128
修改
f = :pen(tmpFile.toLatin1(), O_CREAT | O_WRONLY);
f = :pen(tmpFile.toLatin1(), O_CREAT | O_WRONLY ,0777);
l 修改交叉工具
#vim qtopiacore/qt/mkspecs/qws/linux-arm-g++/qmake.conf
将檔案中的arm-linux-***全部修改為arm-softfloat-linux-gnu-**
這樣做的前提是我的交叉工具鍊是arm-softfloat-linux-gnu,如果你的是arm-linux就不用改了。
l 生成Makefile
#cd ../target //為了不破壞源碼,選擇在此目錄下配置、編譯源碼
#../source/configure -release -image /Qtopia -prefix /Qtopia -xplatform linux-arm-g++ -arch arm -no-qvfb -displaysize 320x240 -no-modem -extra-qtopiacore-config "-release -xplatform qws/linux-arm-g++ -embedded arm -qconfig qpe -depths 4,8,16,32 -qt-sql-sqlite -no-mouse-linuxtp -qt-mouse-tslib -I/home/linux/tslib/include -L/home/linux/tslib/lib " 2>../configureERR.txt
注意:這裡/Qtopia是最後Qtopia的安裝路徑,安裝到主機的某個路徑下,最終這個路徑和目标闆上的路徑必須一緻。
主要配置選項說明如下:
-xplatform linux-arm-g++ -arch arm
目标平台為arm-linux,體系結構為arm。
-no-qvfb
目标平台已支援framebuffer,因而不使用虛拟幀緩沖。
-extra-qtopiacore-config
為Qtopia core 配置選項。
-xplatform qws/linux-arm-g++ -embedded arm
目标平台編譯配置檔案使用qtopiacore/qt/mkspecs/qws/linux-arm-g++目錄下的配置檔案,嵌入式平台為arm。
-qconfig qpe
使用配置檔案qconfig-qpe.h,若使用qconfig-large.h配置檔案,則使用-qconfig large選項。
-qt-sql-sqlite
資料庫支援Sqlite。
-qt-kbd-usb
鍵盤支援usb協定。
-no-mouse-linuxtp -qt-mouse-tslib
-I/home/linux/tslib/include -L/home/linux/tslib/lib
觸摸屏協定不支援linuxtp,支援tslib,并在後面添加上剛才編譯的tslib的頭檔案和庫。
2>../qtopiaconfigureERR.txt
最後将配置過程中的錯誤輸出到qtopiaconfigureERR.txt檔案中。
l 編譯
l 将安裝和的目錄考到nfsroot目錄下
#cp /Qtopia /rootfs -a
(3)熟悉主機開發環境
l 提供給PC端的開發工具
上面的qtopia編譯安裝完成後,會在咱們前面建立的target目錄下生成很多開發工具。
先看一下供主機端使用的工具
[root@localhost bin]# pwd
/home/linux/Qtopia/target/qtopiacore/host/bin
[root@localhost bin]# ls
assistant linguist lupdate qmake rcc uic
designer lrelease moc qvfb templates uic3
如果系統以前有其它qt開發工具,把環境變量修改一下,保證它們不要和我們這幾個工具沖突。下面可以試一下你的designer了。
#./designer
2、在PC端實作基于qt前端的mplayer播放器
建立工程目錄/home/linux/mplayer
(1)搭建ui界面
利用前面安裝的designer搭建ui界面,并将其儲存至/home/linux/mplayer/mplayer.ui
圓角矩形标注: 加了一個widget,留作mplayer的播放區
(2)編寫程式
在/home/linux/mymplayer/下建立mplayer.cpp、mplayer.h、main.cpp 、image.qrc
Main.cpp
/*****************************main.cpp*****************************/
#include <QApplication>
#include "mplayer.h"
int main(int argc, char **argv)
QApplication app(argc, argv);
MPlayer player; //執行個體最終的MPlayer類
player.show(); //顯示界面
return app.exec(); //運作程式
mplayer.h
#ifndef _MPLAYER_H
#define _MPLAYER_H
#include <QIcon>
#include <QProcess>
#include <QTimer>
#include <QStringList>
#include <QDir>
#include <QTime>
#include <QString>
#include "ui_mplayer.h"
class MPlayer:public QDialog,private Ui_Dialog
Q_OBJECT
public:
MPlayer(QWidget *parent = 0);
QTime int_to_time(int);
public slots:
void play_pause_slots(); //暫停
void stop_slots(); //停止
void previous_slots(); //上一曲
void next_slots(); //下一曲
void seek_slots(int);
void get_time_slots(); //得到播放時間
void set_volume_slots(int); //設定音量
void set_sound_slots(); //靜音
void playerReward_slots(); //快退
void playerForward_slots(); //快進
void back_message_slots(); //更新顯示資訊
private:
QProcess *process;
QStringList files;
QDir directory;
int file_count;
QString file_name;
bool isPlay;
bool isSound;
bool isStop;
QTimer *timer;
int file_length;
int curr_time;
};
mplayer.cpp
/*******************************mplayer.cpp **********************************/
#include <QDebug>
#include <unistd.h>
MPlayer::MPlayer(QWidget *parent)Dialog(parent)
setupUi(this); //初始化界面
isPlay = true;
isSound = true;
isStop = false;
/************************為按鍵添加圖示**************************/
//play
QIcon icon_play;
icon_play.addPixmap(QPixmap(QString::fromUtf8("images/pause_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_2->setIcon(icon_play);
//stop
QIcon icon_stop;
icon_stop.addPixmap(QPixmap(QString::fromUtf8("images/stop_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_3->setIcon(icon_stop);
//reward
QIcon icon_reward;
icon_reward.addPixmap(QPixmap(QString::fromUtf8("images/reward_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_4->setIcon(icon_reward);
//forward
QIcon icon_forward;
icon_forward.addPixmap(QPixmap(QString::fromUtf8("images/forward_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_5->setIcon(icon_forward);
//sound
QIcon icon_sound;
icon_sound.addPixmap(QPixmap(QString::fromUtf8("images/sound_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton->setIcon(icon_sound);
QIcon icon_previous;
icon_previous.addPixmap(QPixmap(QString::fromUtf8("images/previous_disabled.png")), QIcon::Normal, QIcon::Off);
pushButton_6->setIcon(icon_previous);
QIcon icon_next;
icon_next.addPixmap(QPixmap(QString::fromUtf8("images/next_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_7->setIcon(icon_next);
/************************設定按鈕無邊框**********************************/
pushButton->setFlat(true);
pushButton_2->setFlat(true);
pushButton_3->setFlat(true);
pushButton_4->setFlat(true);
pushButton_5->setFlat(true);
pushButton_6->setFlat(true);
pushButton_7->setFlat(true);
/*************************獲得播放清單***************************/
directory.setPath("./movie");
files = directory.entryList(QDir::AllEntries,QDir::Time);
file_name = files[2]; //檔案0和1為 ”.” ”..”,是以從檔案2開始播放
file_count = 2;
label_3->setText(files[2]);
/*************************初始化進度條及QProcess類**************/
horizontalSlider->setPageStep(1);
process = new QProcess(this);
/*************************初始化信号、槽*************************/
connect(pushButton_2,SIGNAL(clicked()),this,SLOT(play_pause_slots()));
connect(pushButton_3,SIGNAL(clicked()),this,SLOT(stop_slots()));
connect(pushButton_4,SIGNAL(clicked()),this,SLOT(playerReward_slots()));
connect(pushButton_5,SIGNAL(clicked()),this,SLOT(playerForward_slots()));
connect(pushButton_6,SIGNAL(clicked()),this,SLOT(previous_slots()));
connect(pushButton_7,SIGNAL(clicked()),this,SLOT(next_slots()));
//connect(horizontalSlider,SIGNAL(valueChanged(int)),this,SLOT(seek_slots(int)));
connect(spinBox,SIGNAL(valueChanged(int)),this,SLOT(set_volume_slots(int)));
connect(pushButton,SIGNAL(clicked()),this,SLOT(set_sound_slots()));
//當process可以讀到Mplayer的傳回資訊時,産生readyReadStandardOutput()信号
//process->start("mplayer -slave -quiet -ac mad 2.avi");
//add -wid QWidget->winId();
QString common = "mplayer -slave -quiet -ac mad -zoom movie/" + file_name + " -wid " + QString::number(widget->winId()); //這裡的widget是ui中MPlayer的顯示區
process->start(common); //開始運作程式
spinBox->setValue(40);
timer = new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(get_time_slots()));
//定時擷取MPlayer的時間資訊
timer->start(1000); //啟動定時器 1秒timeout 1次
void MPlayer::play_pause_slots()
if(!isPlay)
if(isStop)
file_name = files[file_count];
else
process->write("pause/n");
QIcon icon_pause;
icon_pause.addPixmap(QPixmap(QString::fromUtf8("images/play_enabled.png")), QIcon::Normal, QIcon::Off);
pushButton_2->setIcon(icon_pause);
isPlay = false;
void MPlayer::stop_slots()
if(!isStop)
process->write("quit/n");
icon_stop.addPixmap(QPixmap(QString::fromUtf8("images/stop_disabled.png")), QIcon::Normal, QIcon::Off);
isStop = true;
label->setText("00:00:00");
label_2->setText("00:00:00");
void MPlayer::previous_slots()
if(file_count > 2)
if(file_count == (files.size()-1))
file_count--;
if(file_count == 2)
label_3->setText(files[file_count]);
void MPlayer::next_slots()
if(file_count < (files.size()-1))
icon_previous.addPixmap(QPixmap(QString::fromUtf8("images/previous_enabled.png")), QIcon::Normal, QIcon::Off);
process->write("quit/n");
file_count++;
{
icon_next.addPixmap(QPixmap(QString::fromUtf8("images/next_disabled.png")), QIcon::Normal, QIcon::Off);
void MPlayer::seek_slots(int seek_num)
qDebug()<<seek_num;
if(process && process->state() == QProcess::Running )
process->write(QString("seek " + QString::number(qMin(seek_num,100)) + "1/n").toAscii());
void MPlayer::get_time_slots()
if(isPlay)
void MPlayer::set_volume_slots(int volume)
qDebug()<<volume;
process->write(QString("volume +" + QString::number(volume) + " /n").toAscii());
//process->write(QString("volume +1/n").toAscii());
void MPlayer::set_sound_slots()
if(isSound)
process->write("mute 1/n");
icon_sound.addPixmap(QPixmap(QString::fromUtf8("images/nosound_enabled.png")), QIcon::Normal, QIcon::Off);
isSound = false;
process->write("mute 0/n");
void MPlayer::playerReward_slots()
//bool ok;
//int m=moviePosition.toInt(&ok);
if (process && process->state()==QProcess::Running && !isPlay)
//QString cmd="seek "+QString::number(qMax(m-10,0))+" 1/n";
//process->write(cmd.toAscii());
qDebug()<<"Reward";
void MPlayer::playerForward_slots()
// groupBox->setVisible(false);
/* if (process && process->state()==QProcess::Running && !isPlay)
//QString cmd="seek "+QString::number(qMin(m+10,100))+" 1/n";
qDebug()<<"Forward";
}*/
QStringList message_list = message.split("=");
if(message_list[0] == "ANS_TIME_POSITION")
curr_time = message_list[1].toDouble();//toInt();
QTime time = int_to_time(curr_time);
label->setText(time.toString("hh:mm:ss"));
horizontalSlider->setValue(100 * curr_time / file_length);
else if(message_list[0] == "ANS_LENGTH")
file_length = message_list[1].toDouble();//toInt();
QTime time = int_to_time(file_length);
label_2->setText(time.toString("hh:mm:ss"));
QTime MPlayer::int_to_time(int second)
int sec = 0, min = 0, hour = 0;
QTime time;
if(second < 60)
sec = second;
min = 0;
hour = 0;
if(second >= 60 && second < 3600)
sec = second % 60;
min = second / 60;
if(second >= 3600)
min = (second / 60) % 60;
hour = second / 3600;
time.setHMS(hour,min,sec);
return time;
image.qrc
<RCC>
<qresource prefix="images" >
<file>images/player_play.png</file>
<file>images/player_stop.png</file>
<file>images/player_pause.png</file>
<file>images/play_enabled.png</file>
<file>images/pause_enabled.png</file>
<file>images/reward_enabled.png</file>
<file>images/forward_enabled.png</file>
<file>images/stop_enabled.png</file>
<file>images/sound_enabled.png</file>
<file>images/nosound_enabled.png</file>
<file>images/previous_enabled.png</file>
<file>images/previous_disabled.png</file>
<file>images/next_enabled.png</file>
<file>images/next_disabled.png</file>
</qresource>
</RCC>
(3)編譯工程
l 拷貝qmake到目前工程目錄下
#cp /home/linux/Qtopia/target/qtopiacore/host/bin/qmake ./
l 生成項目檔案、
#qmake –project
#qmake
成功後,可以生成mplayer可執行程式
l 建立movie和images
#mkdir movie
#mkdir images
[root@localhost mplayer]# ls movie/
1.mp3 2.avi 3.avi 4.avi 5.avi
[root@localhost mplayer]# ls images
forward_enabled.png nosound_enabled.png player_play.png reward_enabled.png
images pause_enabled.png player_stop.png sound_enabled.png
next_disabled.png play_enabled.png previous_disabled.png stop_disabled.png
next_enabled.png player_pause.png previous_enabled.png stop_enabled.png
l 運作程式
[root@localhost mplayer]#./mplayer
五、移植到ARM平台過程
1、核心要求
要求核心支援framebuffer驅動、OSS音頻驅動、支援input事件的觸摸屏驅動。
2、目标闆上部署qt環境
将前面交叉編譯好的/Qtopia目錄拷貝到nfsroot目錄下
#cp /Qtopia /rootfs –a
注:rootfs為目标平台的nfs根檔案系統位置
3、檔案系統中移植tslib
(下面的步驟是在ubantu-8.10環境下編譯的,其它的系統基本相同)
(1)拷貝“項目代碼/tslib源碼”目錄下的tslib-1.4.tar.gz到linux系統
(2)# tar -zxvf tslib-1.4.tar.gz
# cd tslib-1.4
# ./autogen.sh
這一步需要安裝一些工具,如:在ubantu系統下可以執行:sudo apt-get install automake
(3)執行autogen.sh腳本所生成的Makefile檔案
請打入以下指令:
echo "ac_cv_func_malloc_0_nonnull=yes" >$ARCH-linux.cache
./configure --host=arm-softfloat-linux-gnu --prefix=/home/linux/tslib --cache-file=$ARCH-linux.cache
--host是指你的交叉編譯器的前最;例如:你的交叉編譯器是arm-linux-gcc,則--host=arm-linux.如果是arm-softfloat-linux-gnu-gcc
則--host=arm-softfloat-linux-gnu
--prefix 是你執行make install 的時候編譯後生成的可執行檔案和庫檔案以及配置文所安裝的目錄;
configure檔案下還有好多選項,你可以執行./configure --help 來進行選擇其他項,不過在這裡這些選項就夠了。
(4)#make
(5)把指定安裝目錄下的mytslib的檔案都copy到你所挂載的根檔案下
#cp -rf /home/linux/tslib/* /rootfs/tslib
(6)修改/rootfs/tslib下的etc目錄中ts.cong檔案
#vi ts.conf 将第二行的#module_raw input修改成module_raw input 注意一定要頂格寫否則程式執行時會發生讀取ts.conf錯誤
(7)啟動你的開發闆
在終端上設定一下環境變量:
export TSLIB_ROOT=/mytslib
export TSLIB_TSDEVICE=/dev/event0
export LD_LIBRARY_PATH=/mytslib/libLD_LIBRARY_PATH
export QWS_SIZE=320x240
export TSLIB_FBDEVICE=/dev/fb0
export TSLIB_PLUGINDIR=/mytslib/lib/ts
export TSLIB_CONSOLEDEVICE=none
export TSLIB_CONFFILE=/mytslib/etc/ts.conf
export POINTERCAL_FILE=/etc/pointercal
export QWS_MOUSE_PROTO=Tslib:/dev/event0
export TSLIB_CALIBFILE=/etc/pointercal
export QWS_DISPLAY="LinuxFb:mmWidth100:mmHeight130:0"
export TSLIB_TSEVENTTYYPE=H3600
為了實作Tslib的正确運作,需要對如下的Tslib的環境變量進行配置:
TSLIB_TSDEVICE //觸摸屏裝置檔案名。
TSLIB_CALIBFILE //校準的資料檔案,由ts_calibrate校準程式生成。
SLIB_CONFFILE //配置檔案名。
TSLIB_PLUGINDIR //插件目錄
TSLIB_CONSOLEDEVICE //控制台裝置檔案名
TSLIB_FBDEVICE //裝置名
以上環境變量在實際開發中的實際配置可以根據實際情況決定。而這些指定的裝置節點一定要和你的開發闆上的/dev目錄下的裝置節點相對應。
為了不浪費時間我們把上面的這些設定寫入一個腳本裡面:參見5.6節
(8)就可以運作mytslib/bin下的測試檔案,如ts_calibrate校準程式。
4、檔案系統中移植mplayer播放器
需要在目标闆上也移植開源的mplayer播放器,步驟如下:
l 編譯libmad
重新配置前面針對主機編譯過的libmad
#./configure --enable-fpm=arm --host=arm-linux --disable-shared /
--disable-debugging --prefix=/usr/local/arm/3.4.1/lib /
CC=arm-linux-gcc
就可以編譯出libmad了。注意--prefix配置選項表示libmad庫和頭檔案在哪個目錄生成,比如本例中make install後在/usr/local/arm/3.4.1/lib目錄下就多了include和lib兩個目錄。這與mplayer的配置選項--with-extraincdir指定的目錄是相符的。如果沒找到編譯生成的lib庫和include頭檔案。則在目前編譯目錄下的mad.h以及.libs目錄下的libmad.a拷到你自己指定的目錄下
l 編譯mplayer
./configure --cc=arm-linux-gcc --host-cc=gcc --target=arm-linux --enable-static /
--prefix=/tmp/mplayer-rc2 --disable-win32dll --disable-dvdread /
--enable-fbdev --disable-mencoder --disable-live --disable-mp3lib /
--enable-mad --enable-libavcodec_a --language=zh_CN /
--disable-armv5te --disable-armv6 /
--with-extraincdir=/usr/local/arm/3.4.1/lib/include /
--with-extralibdir=/usr/local/arm/3.4.1/lib/lib
幾點注意:—host-cc參數指定X86的gcc,不指定的話,有些必須用gcc編譯的,make會交叉編譯,就會出錯
--cc指定交叉工具鍊名稱
--with-extraincdir與--with-extralibdir指定剛才交叉編譯libmad生成的mad.h與liblibmad.a存放路徑
編譯過程中會出現如下錯誤:
armv4l/dsputil_arm_s.S:79:error:selected processor does not support 'pld[r1]'
【解決辦法】
修改dsputil_arm_s.S,在前面添加上:
#ifndef HAVE_PLD
.macro pld reg
.endm
5、主機交叉編譯工程
(1)針對目标平台調整UI
由于目标平台的液晶是320*240分辨率的,是以需要調整下UI的大小。将UI的整個視窗大小調整為320*240。
(2)交叉編譯工程
l 拷貝針對目标平台的qmake工具到工程目錄下
#cp /home/linux/Qtopia/target/qtopiacore/target/bin/qmake ./
l 生成項目檔案
l 生成Makefile檔案
l 編譯生成目标檔案mymplayer
6、設定環境變量腳本檔案Qtopia.sh
#vim Qtopia.sh
!/bin/sh
export TSLIB_ROOT=/tslib
export LD_LIBRARY_PATH=/tslib/libLD_LIBRARY_PATH
export TSLIB_PLUGINDIR=/tslib/lib/ts
export TSLIB_CONFFILE=/tslib/etc/ts.conf
export TSLIB_TSEVENTTYYPE=H3600i
export LD_LIBRARY_PATH=/Qtopia/libLD_LIBRARY_PATH
export QWS_SW_CURSOR
export set HOME=/root
export set QPEDIR=/Qtopia
export set QWS_KEYBOARD="TTY:/dev/tty1"
export QWS_DISPLAY="LinuxFb:mmWidth60:mmHeight65:0"
7、通過nfs方式測試程式
(1)設定uboot參數
setenv bootcmd tftp 30008000 zImage /; go zImage
setenv bootargs root=nfs nfsroot=192.168.1.112:/rootfs ip=192.168.1.202 init=/linuxrc console=ttySAC0,115200 devfs=mount display=sam240
(2)啟動目标系統
l 将“項目代碼/工程鏡像”目錄下的zImage拷貝到tftp服務目錄/tftpboot下
l 開啟nfs、tftp服務,服務目錄分别為/rootfs /tftpboot
l 啟動系統
l 運作測試程式
#. ./Qtopia.sh //設定環境變量
#./mymplayer –qws //運作程式
8、QT程式國際化
利用/home/linux/Qtopia/target/qtopiacore/host/bin下面的幾個工具給程式做漢化工作
(1)修改pro檔案
在.pro檔案添加如下内容:
TRANSLATIONS = zh_CN.ts
(2)生成ts檔案
#lupdate mymplayer.pro
生成zh_CN.ts檔案
(3)生成qm翻譯檔案
#linguist zh_CN.ts
(4)拷貝字型檔案到目标系統
l 從C:/WINDOWS/Fonts選擇一個字型,如simsun.ttc
cp simsun.ttc /rootfs/Qtopia/lib/fonts //simsun.ttc 是宋體字庫
l 修改fonts中檔案fontdir,添加如下内容
simsun simsun.ttc TTC n 50 120 u
(5)修改源碼
修改main.cpp為如下形式
#include <QtCore/QTextCodec>
#include <QTranslator>
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")) ;//設定編碼為UTF8
app.setFont(QFont("simsun", 10)); //設定顯示字型為漢字
QTranslator *translator = new QTranslator( 0 ); //導入中文化qm檔案
translator->load( "zh_CN.qm", "." );
app.installTranslator( translator );
MPlayer player;
player.show();
return app.exec();
9、目标機獨立測試
(1)裁剪系統
(2)制作cramfs鏡像