Wednesday, June 20, 2007

string和int间的类型转换 ZZ

*int 转换 string*
string int2str( int num)
{
if (num == 0 )
return " 0 " ;

string str = "" ;
int num_ = num > 0 ? num : - 1 * num;

while (num_)
{
str = ( char )(num_ % 10 + 48 ) + str;
num_ /= 10 ;
}

if (num < 0 )
str = " - " + str;

return str;
}
*string 转换 int
*
int str2int( string str)
{
int i,len = str.size(),num = 0 ;

i = 0 ;
if (str[ 0 ] == ' - ' )
i = 1 ;

while (i < len)
{
num = num * 10 + ( int )(str[i] - ' 0 ' );
i ++ ;
}

if (str[ 0 ] == ' - ' )
num *= - 1 ;

return num;
}

string和int间是可以自己写函数实现类型转换的,但是string和double就不太方
便了,stirng转换double可以自定义函数实现,但是,double转换string就需要使
用库函数了,如sprintf

Tuesday, June 19, 2007

STL vector容器介绍(转载)

在CSDN上看到一篇关于介绍vector的文章,觉得还不错,里面对于vector的成员函
数和简单用法介绍的还蛮清楚的,于是转过来作为备用,方便以后查找vector的一
些方法。(一下内容转自CSDN中masterlee的专栏)
  
  介绍std::vector,并且讨论它在STL中的算法和条件函数remove_if()。
  
  介绍
  这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等
操作。本文中还讨论了条件函数和函数指针在迭代算法中使用,如在 remove_if()
和for_each()中的使用。通过阅读这篇文章读者应该能够有效地使用vector容器,
而且应该不会再去使用C类型的动态数组了。
  
  Vector总览
  vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数
据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够
像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动
态数组,能够增加和压缩数据。
  为了可以使用vector,必须在你的头文件中包含下面的代码:#include
  vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:
   using std::vector;
   vector vInts;
  或者连在一起,使用全名:std::vector vInts;
  建议使用全局的命名域方式:using namespace std;
  在后面的操作中全局的命名域方式会造成一些问题。vector容器提供了很多接
口,在下面的表中列出vector的成员函数和操作。
  
  Vector成员函数
  函数 表述
  c.assign(beg,end):将[beg; end)区间中的数据赋值给c。
  c.assign(n,elem):将n个elem的拷贝赋值给c。
  c.at(idx):传回索引idx所指的数据,如果idx越界,抛出out_of_range。
  c.back():传回最后一个数据,不检查这个数据是否存在。
  c.begin():传回迭代器重的可一个数据。
  c.capacity():返回容器中数据个数。
  c.clear():移除容器中所有数据。
  c.empty():判断容器是否为空。
  c.end():指向迭代器中的最后一个数据地址。
  c.erase(pos):删除pos位置的数据,传回下一个数据的位置。
  c.erase(beg,end):删除[beg,end)区间的数据,传回下一个数据的位置。
  c.front():传回地一个数据。
  get_allocator:使用构造函数返回一个拷贝。
  c.insert(pos,elem):在pos位置插入一个elem拷贝,传回新数据位置。
  c.insert(pos,n,elem):在pos位置插入n个elem数据。无返回值。
  c.insert(pos,beg,end):在pos位置插入在[beg,end)区间的数据。无返回值。
  c.max_size():返回容器中最大数据的数量。
  c.pop_back():删除最后一个数据。
  c.push_back(elem):在尾部加入一个数据。
  c.rbegin():传回一个逆向队列的第一个数据。
  c.rend():传回一个逆向队列的最后一个数据的下一个位置。
  c.resize(num):重新指定队列的长度。
  c.reserve():保留适当的容量。
  c.size():返回容器中实际数据的个数。
  c1.swap(c2):将c1和c2元素互换。
  swap(c1,c2):同上操作。
  vector c:创建一个空的vector。
  vector c1(c2):复制一个vector。
  vector c(n):创建一个vector,含有n个数据,数据均已缺省构造产生。
  vector c(n, elem):创建一个含有n个elem拷贝的vector。
  vector c(beg,end):创建一个以[beg;end)区间的vector。
  c.~ vector ():销毁所有数据,释放内存。
  
  Vector操作
  函数 描述
  operator[]:返回容器中指定位置的一个引用。
  
  创建一个vector
  vector容器提供了多种创建方法,下面介绍几种常用的。创建一个Widget类型
的空的vector对象:
  vector vWidgets;
  
  创建一个包含500个Widget类型数据的vector:
  vector vWidgets(500);
  
  创建一个包含500个Widget类型数据的vector,并且都初始化为0:
  vector vWidgets(500, Widget(0));
  
  创建一个Widget的拷贝:
  vector vWidgetsFromAnother(vWidgets);
  
  向vector添加一个数据
  vector添加数据的缺省方法是push_back()。push_back()函数表示将数据添加
到vector的尾部,并按需要来分配内存。例如:向vector中添加10个数据,需要如
下编写代码:
  for(int i= 0;i<10; i++)
   vWidgets.push_back(Widget(i));
  
  获取vector中制定位置的数据
  很多时候我们不必要知道vector里面有多少数据,vector里面的数据是动态分
配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。如果你
想知道vector存放了多少数据,你可以使用empty()。获取vector的大小,可以使
用size()。例如,如果你想获取一个vector v的大小,但不知道它是否为空,或者
已经包含了数据,如果为空想设置为-1,你可以使用下面的代码实现:
  int nSize = v.empty() ? -1 : static_cast(v.size());
  
  访问vector中的数据
  使用两种方法来访问vector。
  1、 vector::at()
  2、 vector::operator[]
  operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。但at
()是我们的首选,因为at()进行了边界检查,如果访问超过了 vector的范围,将
抛出一个例外。由于operator[]容易造成一些错误,所有我们很少用它,下面进行
验证一下:
  
  分析下面的代码:
  vector v;
  v.reserve(10);
  for(int i=0; i<7; i++)
   v.push_back(i);
  try
  {
   int iVal1 = v[7]; // not bounds checked - will not throw
   int iVal2 = v.at(7); // bounds checked - will throw if out of range
  }
  catch(const exception& e)
  {
   cout << e.what();
  }
  我们使用reserve()分配了10个int型的空间,但并不没有初始化。也就是说
vector容器中前7个元素已经被初始化,分别是0、1、2、 3、4、5、6;但其后三
个元素只是分配了int型空间,但是并没有被初始化。
  你可以在这个代码中尝试不同条件,观察它的结果,但是无论何时使用at(),
都是正确的。
  
  删除vector中的数据
  vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了
erase(),pop_back(),clear()来删除数据,当你删除数据的时候,你应该知道要
删除尾部的数据,或者是删除所有数据,还是个别的数据。在考虑删除等操作之前
让我们静下来考虑一下在STL中的一些应用。
  
  Remove_if()算法
  现在我们考虑操作里面的数据。如果要使用remove_if(),我们需要在头文件
中包含如下代码::
  #include
  Remove_if()有三个参数:
  1、 iterator _First:指向第一个数据的迭代指针。
  2、 iterator _Last:指向最后一个数据的迭代指针。
  3、 predicate _Pred:一个可以对迭代操作的条件函数。
  
  条件函数
  条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指
针,或者是一个函数对象。这个函数对象需要支持所有的函数调用操作,重载
operator()()操作。remove_if()是通过unary_function继承下来的,允许传递数
据作为条件。
  例如,假如你想从一个vector中删除匹配的数据,如果字串中包含了一个值,
从这个值开始,从这个值结束。首先你应该建立一个数据结构来包含这些数据,类
似代码如下:
  #include
  enum findmodes
  {
   FM_INVALID = 0,
   FM_IS,
   FM_STARTSWITH,
   FM_ENDSWITH,
   FM_CONTAINS
  };
  typedef struct tagFindStr
  {
   UINT iMode;
   CString szMatchStr;
  }FindStr;
  typedef FindStr* LPFINDSTR;
  
  然后处理条件判断:
  class FindMatchingString : public std::unary_function
  {
  public:
  
   FindMatchingString(const LPFINDSTR lpFS) : m_lpFS(lpFS) {}
   bool operator()(CString& szStringToCompare) const
   {
   bool retVal = false;
   switch(m_lpFS->iMode)
   {
   case FM_IS:
   {
   retVal = (szStringToCompare == m_lpFDD->szMatchStr);
   break;
   }
   case FM_STARTSWITH:
   {
   retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
   == m_lpFDD->szWindowTitle);
   break;
   }
   case FM_ENDSWITH:
   {
   retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
  
   == m_lpFDD->szMatchStr);
   break;
   }
   case FM_CONTAINS:
   {
   retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
   break;
   }
   }
   return retVal;
   }
  private:
   LPFINDSTR m_lpFS;
  };
  通过这个操作你可以从vector中有效地删除数据:
  // remove all strings containing the value of
  // szRemove from vector vs.
  FindStr fs;
  fs.iMode = FM_CONTAINS;
  fs.szMatchStr = szRemove;
  vs.erase(std::remove_if(vs.begin(), vs.end(),
FindMatchingString(&fs)), vs.end());
  
  Remove_if()能做什么?
  你可能会疑惑,对于上面那个例子在调用remove_if()的时候还要使用erase()
呢?这是因为大家并不熟悉STL中的算法。Remove (),remove_if()等所有的移出操
作都是建立在一个迭代范围上的,那么不能操作容器中的数据。所以在使用
remove_if(),实际上操作的时容器里数据的上面的。思考上面的例子:
  1、 szRemove = "o".
  2、 vs的结果,说明remove_if()实际上是根据条件对迭代地址进行了修改,
在数据的后面存在一些残余的数据,那些需要删除的数据。剩下的数据的位置可能
不是原来的数据,但他们是不知道的。
  调用erase()来删除那些残余的数据。注意上面例子中通过erase()删除
remove_if()的结果和vs.enc()范围的数据。
  
  压缩一个臃肿的vector
  很多时候大量的删除数据,或者通过使用reserve(),结果vector的空间远远
大于实际需要的。所有需要压缩vector到它实际的大小。 resize()能够增加
vector的大小。Clear()仅仅能够改变缓存的大小,所有的这些对于vector释放内
存等九非常重要了。如何来解决这些问题呢,让我们来操作一下。
  我们可以通过一个vector创建另一个vector。让我们看看这将发生什么。假定
我们已经有一个vector v,它的内存大小为1000,当我们调用size()的时候,它的
大小仅为7。我们浪费了大量的内存。让我们在它的基础上创建一个vector。
  std::vector vNew(v);
  cout << vNew.capacity();
  vNew.capacity()返回的是7。这说明新创建的只是根据实际大小来分配的空
间。现在我们不想释放v,因为我们要在其它地方用到它,我们可以使用swap()将v
和vNew互相交换一下?
   vNew.swap(v);
   cout << vNew.capacity();
   cout << v.capacity();
  有趣的是:vNew.capacity()是1000,而v.capacity()是7。
  现在是达到我的目的了,但是并不是很好的解决方法,我们可以像下面这么写:
   std::vector(v).swap(v);
  你可以看到我们做了什么?我们创建了一个临时变量代替那个命名的,然后使
用swap(),这样我们就去掉了不必要的空间,得到实际大小的v。
  
  结论
  我希望这个文档可以给那些使用STL vector容器的开发者很有价值的参考。我
也希望通过阅读这篇文章你可以放心地使用vector来代替C语言中的数据了。
  
  参考
  Plauger, P.J. Standard C++ Library Reference. February, 2003. MSDN.
  Schildt, Herbert. C++ from the Ground Up, Second Edition. Berkeley:
1998.
  Sutter, Herb. More Exceptional C++. Indianapolis: 2002.

Another reject

from UNC(The University of North Carolina at Chapel Hill), received
several days ago, although I have withdrawn the application several
months ago :-) . The following is the details:

Dear Xin,

Your application for admission to graduate study at The University of
North Carolina at Chapel Hill has now been reviewed by The Graduate
School and the Department of Mathematics. We regret being unable to
offer you admission. Although your qualifications appear to be above our
usual minimum standards for admission, the number of highly qualified
applicants in your area of interest exceeds our facilities to train them
adequately. Consequently, we must limit new admissions rather severely.

We appreciate your interest in The University of North Carolina at
Chapel Hill and the opportunity you have given us to consider your
application. We are sorry we could not select you for admission and wish
you success in finding a suitable situation in which to continue your
education.

Sincerely yours,

Linda Dykstra
Dean of the Graduate School

Monday, June 18, 2007

C++文件操作 ZZ

在C++中,有一个stream这个类,所有的I/O都以这个"流"类为基础的,包括我
们要认识的文件I/O,stream这个类有两个重要的运算符:

1、插入器(<<)
  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是
指的显示器,所以,cout<<"Write Stdout"<<'\n';就表示把字符串"Write
Stdout"和换行字符('\n')输出到标准输出流。

2、析取器(>>)
  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就
是指的键盘,所以,cin>>x;就表示从标准输入流中读取一个指定类型(即变量x的
类型)的数据。

  在C++中,对文件的操作是通过stream的子类fstream(file stream)来实现
的,所以,要用这种方式操作文件,就必须加入头文件fstream.h。下面就把此类
的文件操作过程一一道来。

一、打开文件
  在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是:

void yWXz(const char* filename,int mode,int access);

参数:

filename:  要打开的文件名
mode:    要打开文件的方式
access:   打开文件的属性
打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:

ios::app:   以追加的方式打开文件
ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性
ios::binary:  以二进制方式打开文件,缺省的方式是文本方式。两种方式的区
别见前文
ios::in:    文件以输入方式打开
ios::out:   文件以输出方式打开
ios::nocreate: 不建立文件,所以文件不存在时打开失败 
ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
ios::trunc:  如果文件存在,把文件长度设为0
  可以用"或"把以上属性连接起来,如ios::out|ios::binary

  打开文件的属性取值是:

0:普通文件,打开访问
1:只读文件
2:隐含文件
4:系统文件
  可以用"或"或者"+"把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打
开文件。

  例如:以二进制输入方式打开文件c:\config.sys

  fstream file1;
  file1.open("c:\\config.sys",ios::binary|ios::in,0);

  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:

  file1.open("c:\\config.sys");<=>file1.open("c:\\config.sys",
ios::in|ios::out,0);

  另外,fstream还有和open()一样的构造函数,对于上例,在定义的时侯就可
以打开文件了:

  fstream file1("c:\\config.sys");

  特别提出的是,fstream有两个子类:ifstream(input file stream)和
ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream
默认以输出方式打开文件。

  ifstream file2("c:\\pdos.def");//以输入方式打开文件
  ofstream file3("c:\\x.123");//以输出方式打开文件

  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入
方式打开,就用ifstream来定义;如果想以输出方式打开,就用 ofstream来定
义;如果想以输入/输出方式来打开,就用fstream来定义。

二、关闭文件
  打开的文件使用完成后一定要关闭,fstream提供了成员函数close()来完成此
操作,如:file1.close();就把file1相连的文件关闭。

三、读写文件
  读写文件分为文本文件和二进制文件的读取,对于文本文件的读取比较简单,
用插入器和析取器就可以了;而对于二进制的读取就要复杂些,下要就详细的介绍
这两种方式

  1、文本文件的读写
  文本文件的读写很简单:用插入器(<<)向文件输出;用析取器(>>)从文件输
入。假设file1是以输入方式打开, file2以输出打开。示例如下:

  file2<<"I Love You";//向文件写入字符串"I Love You"
  int i;
  file1>>i;//从文件输入一个整数值。

  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体
的格式有以下一些

操纵符 功能 输入/输出
dec 格式化为十进制数值数据 输入和输出
endl 输出一个换行符并刷新此流 输出
ends 输出一个空字符 输出
hex 格式化为十六进制数值数据 输入和输出
oct 格式化为八进制数值数据 输入和输出
setpxecision(int p) 设置浮点数的精度位数 输出

  比如要把123当作十六进制输出:file1<<<123;要把3.1415926以5位精度输
出:FILE1<< <3.1415926。

  2、二进制文件的读写
①put()
  put()函数向流写入一个字符,其原型是ofstream &put(char ch),使用也比
较简单,如file1.put('c');就是向流写一个字符'c'。

②get()
  get()函数比较灵活,有3种常用的重载形式:

  一种就是和put()对应的形式:ifstream &get(char &ch);功能是从流中读取
一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);
表示从文件中读取一个字符,并把读取的字符保存在x中。

  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如
果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。

  还有一种形式的原型是:ifstream &get(char *buf,int num,char
delim='\n');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符
或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行
符'\n'。例如:

  file2.get(str1,127,'A');//从文件中读取字符到字符串str1,当遇到字符
'A'或读取了127个字符时终止。

③读写数据块
  要读写二进制数据块,使用成员函数read()和write()成员函数,它们原型如下:

    read(unsigned char *buf,int num);
    write(const unsigned char *buf,int num);

  read()从文件中读取 num 个字符到 buf 指向的缓存中,如果在还未读入 num
个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际读取的字符
数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的
类型是 unsigned char *,有时可能需要类型转换。

例:

    unsigned char str1[]="I Love You";
    int n[5];
    ifstream in("xxx.xxx");
    ofstream out("yyy.yyy");
    out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中
    in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中读取指定个整
数,注意类型转换
    in.close();out.close();

四、检测EOF
  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返
回0。原型是int eof();

例:  if(in.eof())ShowMessage("已经到达文件尾!");

五、文件定位
  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指
针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写
操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定
位分为读位置和写位置的定位,对应的成员函数是 seekg()和 seekp(),seekg()
是设置读位置,seekp是设置写位置。它们最通用的形式如下:

    istream &seekg(streamoff offset,seek_dir origin);
    ostream &seekp(streamoff offset,seek_dir origin);

  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大
值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:

ios::beg:  文件开头
ios::cur:  文件当前位置
ios::end:  文件结尾
  这两个函数一般用于二进制文件,因为文本文件会因为系统对字符的解释而可
能与预想的值不同。

例:

     file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234
个字节
     file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234
个字节

在BCB中也提供了文件操作的函数,这些函数的功能和前面所介绍的大致相同,但
这类函数和BCB关系紧密,能使用BCB中的AnsiString等数据类型,在BCB中用这种
方式的文件操作是最方便的,下面我就把这种文件操作详细介绍。

  在BCB提供的这组文件操作函数中,可分为三种类型,就是:1、文件名函数,
2、文件管理函数;3、文件I/O函数。

VISA cleared

and also received last weekend...

Monday, June 04, 2007

fixed helicopter test-fly

Perform excellent, but entangled with a kite. The tail-airscrew was lost. Fortunately, I found it this morning. Hehe~~~ So I need more practice...

示范反手后场高远球等 zz

反手后场高远球
http://www.inforknow.com/viewthread.php?tid=927&extra=page%3D1
反手后场高吊球
http://www.inforknow.com/viewthread.php?tid=926&extra=page%3D1
羽毛球跳杀动作分解
http://www.jokedm.com/v/78957c6bbe82ec1096fd57b9dd6d5be0.html

helicopter fixed

On Saturday. Because there is no shop which sells the broken fittings, I had to fix it by myself.

Today, I order DC from joyo, Powershot A 570 IS. Thanks mdf and Guang. When it arrive, I will put photo of my fixed helicopter (electric tool, hehe).

Sunday, June 03, 2007

summer palace revisited

last day. Visiting almost every scenic spot, including 17-hole bridge, foguang ge, Suzhou street. We really had a good time, enjoying the view with friends~~~
but without DC, so no photo...

Friday, June 01, 2007

RMVB AVI RM VCD DVD FC6 ZZ

本方法在 Fedora Core 6 下测试通过:
(注意: 首先确定你能连接 internet)


第一部分:播放器安装

1. 安装 liva 源
# rpm -ivh http://rpm.livna.org/livna-release-6.rpm
# rpm --import http://rpm.livna.org/RPM-LIVNA-GPG-KEY

2. 卸载 totem
# yum -y remove totem

3. 安装 totem-xine, vlc, mplayer
# yum -y install totem-xine vlc xine-lib-extras-nonfree totem-xine-mozplugin mplayer-gui
4. 安装解码器
下载解码器,地址:
http://www4.mplayerhq.hu/MPlayer/rel...061022.tar.bz2
# tar jxvf all-20061022.tar.bz2
# mkdir /usr/lib/codecs
# mv all-20061022/* /usr/lib/codecs
# chmod 755 /usr/lib/codecs/*
# ln -s /usr/lib/codecs /usr/local/lib/codecs (这个给 mplayer 用)
(注:如果你已经安装了 codec,那就只需添加链接就可了)

5. 测试
a. 选择 应用程序 -> 影音 -> 电影播放机
看看能不能播放 real 格式,quicktime 格式的视频
b. 选择 应用程序 -> 影音 -> VLC Media Player
看看播放 dvd, vcd 能行不?
c. 浏览器支持
使用 mozilla 或 firefox 打开
http://www.apple.com/trailers/
选择一个视频就可以用 totem-xine 来播放了。

6. 安装 RealPlayer
安装了linux版本的RealPlayer,播放RMVB,有图象无声音。解决办法,安装最新的 nightly-build 版本:
a. 安装 RealPlayer
下载地址:
http://forms.helixcommunity.org/heli...alplay-current
# rpm -e RealPlayer
# exit (返回普通用户)
$ rm ~/.realplayerrc
# su (再 su 到 root)
# rpm -ivh RealPlayer*

b. 测试播放 rmvb
i. 本地视频播放测试
ii. 浏览器支持
重启 firefox 或 mozilla 打开:
http://www.npr.org/
点击“Hourly Newscast“
然后选择总是使用 /usr/bin/realplay 打开。
这就激活 RealPlayer 的 mozilla, firefox 插件了。

顺便说一个,如果你开着桌面效果(即 compiz)用 RealPlayer,你得把使用 xvideo 的勾去掉
如果在宽屏下使用 mplayer,你得修改
/etc/mplayer/mplayer.conf
把第 63 行前面的 # 去掉。
才能显示正常。

测试在线播放以及下载视频的网站:
http://www.redhat.com/truthhappens/videos/ourfilms.html
http://www.redhat.com/truthhappens/shows/
http://www.apple.com/trailers/
经过上面的安装后,这些视频都可以直接在 firefox 中播放。