wall_john 发表于 2005-10-22 12:43:21

站内邮件和催人的邮件和kanker

KanKer:
    你好!因为最近忙于生计,一直没时间好好完善kaffeine的播放问题,
实在不好意思,下面说一下最近的研究成果。(另外最近在研究freebsd,
该系统不能在论坛上发言,发送时告诉我请求不能识别,怪怪的。后来用
“瘟到死”才看到你留的站内邮件不好意思!)
   
1.如何让kaffeine_part支持javasript
在KDE中KParts::LiveConnectExtension这个类能使一个kpart的东西支持
javascript。

在下面的补丁中一个该类的实作
头文件部分
#include <kparts/browserextension.h>
class KaffeinePartLiveConnectExtension : public KParts::LiveConnectExtension {
    Q_OBJECT
public:
    KaffeinePartLiveConnectExtension(KaffeinePart * parent);

    bool get (const unsigned long objid, const QString & field, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, QString & value);
    bool put(const unsigned long, const QString & field, const QString & value);
    bool call (const unsigned long , const QString & func, const QStringList & args, KParts::LiveConnectExtension::Type & type, unsigned long & retobjid, QString & value);
    void unregister (const unsigned long objid);

private:
    KaffeinePart * m_parent;
};

实作代码部分
KaffeinePartLiveConnectExtension::KaffeinePartLiveConnectExtension(KaffeinePart * parent)
: KParts::LiveConnectExtension (parent, "KaffeinePart LiveConnect Extension"), m_parent (parent)
{}
//kde的javascrip执行引擎,遇到比如kaffeine_object.play()函数时会先解析该play函数名,
//于是根据kaffeine_object这个kpart,发现它有绑定了LiveConnectExtension这个类时,就会
//调用该类的虚拟方法bool get (...)从而获得这个play的具体定义。
//前面提到的kaffeine_object由html中object 用classid指定(名称是随便定义的)。具体id是
//多少我忘记了,反正就是windows中播放媒体工具com对象的几个id,好像这个:
// kdelibs_src/khtml/rendering/render_frames.cpp 文件中有做判断
bool KaffeinePartLiveConnectExtension::get (
      const unsigned long objid, const QString & name,
      KParts::LiveConnectExtension::Type & type,
      unsigned long & rid, QString & value)
{
    kdDebug(6074) << "KaffeinePartLiveConnectExtension::get"
      << " objid:" << objid
      << " name :" << name
      << " type :" << type
      << " rid:" << rid
      << " value:" << value
      << endl;
    QString data = name.lower();
    if (data == "play" || data == "stop" || data == "pause") {
      type = LiveConnectExtension::TypeFunction; //告诉javascript引擎play()、stop()、pause()是三个函数
      rid = LiveConnectExtension::TypeVoid;
      value = "";
      return true;
    } else if (data == "mute") {                  //告诉javascript引擎mute是个属性值,这样调用的var mut=kaffeine_object.mute;
      type = LiveConnectExtension::TypeBool;
      value = QString::number(m_parent->slotMuteState());
      return true;
    } else if (data == "duration") {            //大意同上
      type = LiveConnectExtension::TypeNumber;
      value = QString::number(m_parent->slotDuration());
      return true;
    } else if (data == "currentposition") {       //大意同上
      type = LiveConnectExtension::TypeNumber;
      value = QString::number(m_parent->slotCurPosition());
      return true;
    } else if (data == "playstate") {             //大意同上
      type = LiveConnectExtension::TypeNumber;
      if (m_parent->isPlaying()) {
            value = QString::number(2);
      } else if (m_parent->isPaused()) {
            value = QString::number(1);
      } else {
            value = QString::number(0);
      }
      return true;
    }
    return false;
}
//put方法在javascript中对某一对象的属性赋值时被调用
bool KaffeinePartLiveConnectExtension::put(
    const unsigned long objid,
    const QString & name, const QString & value)
{

    kdDebug(6074) << "KaffeinePartLiveConnectExtension::put"
      << " objid:" << objid
      << " name :" << name
      << " value:" << value
      << endl;
    QString data = name.lower();
    if (data == "mute") {                     //当这样时kaffeine_object.mute=mut时被调用
      bool val = (value.lower() == "true");
      if (val != m_parent->slotMuteState()) {
            m_parent->slotMute();
      }
    } else if (data == "currentposition") {
      bool ok;
      double pos = value.toDouble(&ok);
      int len = m_parent->slotDuration();
      if (len <= 0) {
            return false;
      }
      pos = pos * 65535 / len;
      if (!ok || pos < 0) {
            return false;
      }
      m_parent->slotCurPosition((int)pos);
    } else if (data == "filename") {
      m_parent->slotStop();
      if (!m_parent->openURL(MRL(value)))
            return false;
    }
    return true;
}
//call方法在javasript中调用某一函数时被调用
bool KaffeinePartLiveConnectExtension::call(
    const unsigned long objid, const QString & func,
    const QStringList & fargs, KParts::LiveConnectExtension::Type & type,
    unsigned long & rid, QString & value )
{

    kdDebug(6074) << "KaffeinePartLiveConnectExtension::call"
      << " objid:" << objid
      << " func :" << func
      << " type :" << type
      << " rid:" << rid
      << " value:" << value
      << endl;
    kdDebug(6074) << "args:" << endl;
    for (unsigned int i = 0; i < fargs.count() ; ++i) {
      kdDebug(6074) << fargs << endl;
    }
    kdDebug(6074) << endl;

    QString action = func.lower();
    if (action == "play") {                      //当这样时kaffeine_object.play()时被调用
      if (m_parent->isPaused()) {
            m_parent->slotTogglePause();
      } else
            m_parent->slotPlay();
    } else if (action == "stop") {
      m_parent->slotStop();
    } else if (action == "pause") {
      if (!m_parent->isPaused()) {
            m_parent->slotTogglePause();
      }
    } else
      return false;
      
    return true;
}

void KaffeinePartLiveConnectExtension::unregister(const unsigned long objid)
{
    kdDebug(6074) << "KaffeinePartLiveConnectExtension::unregister"
      << " objid:" << objid
      << endl;
}

kaffeinepart必须绑定上面这个类才能支持javascript的调用
具体内容见补丁中,这个补丁只能支持一些比较低级的javasript的调用,很多网站还不行:<,
主要是对一些javascript播放语句比如duration之类的不甚了了,希望有智者能帮忙解决。


2.如何让drkonqi在程序出错时打印堆栈出来,而不是问号
drkonqi在程序出现比如段错误时,会捕获这个signal(信号),这个是linux的处理机制,
一段程序出错就只能退出,不像windows下面比如delphi,try... except,在try段中的程序
部分即算出错也能回到except或finally部分继续执行像java,不过java的异常处理都是虚拟
机自己实现的,所以在linux照样能用。
drkonqi俘获一个signal后就会调用gdb的bt功能(backtrace)去打印错误线程的堆栈,然后
显示出来。不过可能是因为linux内核中断门使用vsyscall的原因,gdb没有把符号表装载进
内存中必须在调用gdb时手工加一点指令:
add-symbol-file-from-memory 0xffffe000 就ok,具体内容到gdb官方的bug列表中去找吧,
所以我在drkonqi中动了点手脚,使其在执行这个语句,自然就能打印出东西来了,不像现在
的全是问号了。

demonlj 发表于 2005-10-22 14:24:40

偶菜,这东东又要话偶一些时间来读了 :cry:

谁比我菜? 发表于 2005-10-22 14:38:34

仰慕一下住顶楼的高人……

KanKer 发表于 2005-10-22 14:47:34

感谢,牛人啊:P
我把这几天做的跟播放有关的补丁也贴出来:
用 kde 的 nspluginloader 装载插件时,如果窗口的高度或宽度为零,会引起 widget 创建错误而无法装载。

--- kdebase-3.4.3.bak/nsplugins/viewer/nsplugin.cpp        2005-10-05 21:38:27.000000000 +0800
+++ kdebase-3.4.3/nsplugins/viewer/nsplugin.cpp        2005-10-21 19:40:23.000000000 +0800
@@ -912,6 +912,10 @@

    _win.x = 0;
    _win.y = 0;
+   //_height and _width can't equal to zero.
+   if (_height==0 || _width==0)
+        return NPERR_NO_ERROR;
+
    _win.height = _height;
    _win.width = _width;
    _win.type = NPWindowTypeWindow;

顺便把konqueror 右键菜单上的 netscape plugin viewer 的一个乱码错误给去掉:

--- kdebase-3.4.3.bak/nsplugins/pluginscan.cpp.orig        2005-10-05 21:38:27.000000000 +0800
+++ kdebase-3.4.3.bak/nsplugins/pluginscan.cpp        2005-10-20 18:26:44.000000000 +0800
@@ -184,7 +184,7 @@
         if (!description.isEmpty())
             ts << "Name=" << description << endl;
         else
-            ts << "Name=" << i18n("Netscape plugin mimeinfo") << endl;
+            ts << "Name=" << "Netscape plugin mimeinfo" << endl;

         f.close();
   }
@@ -489,10 +489,10 @@
         QTextStream ts(&f);

         ts << "[Desktop Entry]" << endl;
-      ts << "Name=" << i18n("Netscape plugin viewer") << endl;
+      ts << "Name=" << "Netscape plugin viewer" << endl;
         ts << "Type=Service" << endl;
         ts << "Icon=netscape" << endl;
-      ts << "Comment=" << i18n("Netscape plugin viewer") << endl;
+      ts << "Comment=" << "Netscape plugin viewer" << endl;
         ts << "X-KDE-Library=libnsplugin" << endl;
         ts << "InitialPreference=0" << endl;
         ts << "ServiceTypes=KParts/ReadOnlyPart,Browser/View" << endl;

konqueror 不能播放 www.qq163.com 里的歌曲,经过分析,是因为 www.qq163.com 在 object 标签内加了个错误的 embed 标签。因为embed 的 src 内容应与 object 的相同,故设定 khtml 兼容 IE 的情况下优先使用 object 以解决这个问题:

--- kdelibs-3.4.3/khtml/rendering/render_frames.cpp.orig        2005-10-05 21:40:35.000000000 +0800
+++ kdelibs-3.4.3/khtml/rendering/render_frames.cpp        2005-10-22 21:05:06.000000000 +0800
@@ -652,11 +653,12 @@
       else { // if(element()->id() == ID_OBJECT || element()->id() == ID_APPLET)

         // check for embed child object
-          for (NodeImpl *child = objbase->firstChild(); child; child = child->nextSibling())
-            if ( child->id() == ID_EMBED ) {
-                  embed = static_cast<HTMLEmbedElementImpl *>( child );
-                  break;
-            }
+          if (! document()->inCompatMode() || objbase->classId.isEmpty())
+            for (NodeImpl *child = objbase->firstChild(); child; child = child->nextSibling())
+               if ( child->id() == ID_EMBED ) {
+                   embed = static_cast<HTMLEmbedElementImpl *>( child );
+                   break;
+               }

         params.append( QString::fromLatin1("__KHTML__CLASSID=\"%1\"").arg( objbase->classId ) );
         params.append( QString::fromLatin1("__KHTML__CODEBASE=\"%1\"").arg( objbase->getAttribute(ATTR_CODEBASE).string() ) );

tingxx 发表于 2005-10-22 14:51:25

高,实在是高呀

:mrgreen::mrgreen:

再见情人 发表于 2005-10-22 15:32:58

高,实在是高呀

:mrgreen::mrgreen:
学习中

KDE 发表于 2005-10-22 22:15:10

大家辛苦呀!
页: [1]
查看完整版本: 站内邮件和催人的邮件和kanker