Browsed by
Tag: qt

Error: “此流的格式错误。”

Error: “此流的格式错误。”

最近在移植 miniSIPPhone 到 Linux 系统时,遇到一个奇怪的错误:播放 wav 语音文件时提示“此流的格式错误”,无论是采用 QSound 还是 QMediaPlayer 播放 wav 文件都出现了这个错误。按照我们一贯以来的要求,miniSIPServer 和 miniSIPPhone 的语音文件都采用了同样的格式:

CCITT A-Law, 8KHZ, 8Bit, 7KB/sec, 单通道

换用 VLC 播放没有任何问题,在 Windows 系统上播放也没有任何问题。考虑到 Qt 在 Linux 系统上实际是调用 GStreamer 的 plugins 来解码和播放各种语音格式,而我们的录制格式是如此的普通和平平无奇,实在想不通为什么会出现格式错误。

遍历了各种可能原因后忽然想到,或许 GStreamer 默认不支持 A-Law?这个格式在通信领域用得比较多,而一般语音播放、音乐等软件可能不太会关注这种格式。将语音文件格式转换成以下格式:

CCITT PCM, 8KHZ, 8Bit, 7KB/sec, 单通道

然后果然成功了,miniSIPPhone 在 Linux 平台也可以正常播放各种提示音。

could not find a Qt installation of ”

could not find a Qt installation of ”

最近重新搭建了一套 Debian 系统的开发环境,使用 qmake 编译 pro 文件时,提示了标题中的错误。检查qmake 文件,发现以下信息:

 /usr/bin/qmake -> qtchooser

这是因为系统提供了两套 Qt 开发环境,比如 Qt6 和 Qt5 等,因此需要指定默认采用哪一套。网络上的解决方案大多数比较粗暴,手工修改 /usr/bin/qmake 的文件链接,链接到真实的 qmake 文件即可。

但实际上系统提供了更简单的方式,比如我们默认采用 Qt5 的开发环境,则使用以下命令:

sudo apt install qt5-default
装机 – Ubuntu16.04

装机 – Ubuntu16.04

老婆公司有个让人惊讶的规定:员工笔记本三年后归自己个人所有,公司重新配新电脑! 这是多么让人热爱的公司!老婆工作这几年,家里多了几台笔记本,一水的ThinkPad。上周又过了三年,拿回一台T430。以前拿回电脑时,会恢复到Thinkpad出厂时安装的window系统,这次这台T430居然只是低格了,没有系统?!

当然可以从网上扒一个windows恢复盘下来重装,不过考虑到家里已经有几台windows的笔记本和台式机,实在没有必要再增加一台,因此这次打算装Linux系统试试。

选择发行版本

“Linux发行版本”之争在程序员迷之争论中绝对可以位列前三位!好在是给自己的笔记本选发行版,因此有幸避免了与别人的争论,只要考虑自己的需求就好了。我的基本原则其实很简单:

(1)发行版要有强大的、历史悠久的社区。

(2)或者,有商业背景企业发布的版本。

以上两点只确保一个问题:若干年后,依然能活着并得到强有力的支持。绝大多数妖艳的Linux发行版本,比如Arch等,基本不用考虑了。符合要求的版本大致也就是:Debian、CentOS、Ubuntu等寥寥数种而已。

CentOS的软件实在太老旧了点,有时候不得不自己去编译各类软件,与其这样,还不如用Arch或者Gentoo等版本来得直接。公司做项目时基本都是采用Debian系统做服务器,很满意,但是Debian桌面系统就差强人意。不知道是Debian的问题,还是KDE的问题,使用时总有各种烦人的小毛病,比如鼠标问题等。

因此这次就选择了Ubuntu 16.04 (Unity7),谁会做死去选择Ubuntu的非LTS版本呢?

安装软件

安装Ubuntu系统实在没什么可以说的,下载iso文件,录制u盘,直接安装即可,比装windows还简单,过程枯燥乏味。下面只是记录一些安装应用软件方面需要注意的地方。

安装virtualBox与Windows环境下稍有不同,扩展功能包也收录在软件中心,因此实际执行命令一起安装:

sudo apt-get install virtualbox virtualbox-ext-pack

将其他计算机中的vbox客机导出到新计算机中,U盘必须采用exFat格式才能支持超过4G大小的文件,ubuntu默认没提供对该格式的支持,因此也需要单独安装:

sudo apt-get install exfat-utils

qt开发工具集升级到qt5了,采用以下命令安装:

sudo apt-get install qt5-default
掉坑里了

掉坑里了

Qt无疑是个非常好的framework,我们一直用TA。虽然不敢说已经是行家里手,不过好歹也开发这么久程序了,渐渐地有些自负起来,因此掉坑里了。

坑来自Qt最经典的设计:signal-slot。我以前的理解这是异步的,常用于模块间解耦。在windows平台,这个理解似乎没错,signal-slot底层依赖window的message机制。而在linux平台,其实现方式默认仍然是callback机制。

callback机制在多线程编程里最容易出问题的就是“锁”。这次掉坑里,就是在slot中应用“锁”时不小心,导致了死锁。

这次竟然忘了这点! :-(

qt network中的一点问题

qt network中的一点问题

在一个小应用中使用了qt的network模块,调用网站的一个接口(HTTP GET方式),获得相应的结果。操作非常简单,可是却出现了问题。

首先是在windows上,运行程序后,提示无法定位libeay32.dll。这个是openSSL的动态链接库,不明白为什么qt4.8.5(windows)默认链接了这个库。查看文档,貌似缺省情况下是不编译进SSL功能的,而且我们用的包并不是自己编译的,是直接从qt网站下载安装的。解决方法也简单,无非就是安装openssl的库,copy相应的dll到exe文件同一目录下即可。

接着又出现了问题,调用HTTP后,服务器返回“406 NOT acceptable”。直接将链接放在浏览器中执行又没有任何问题。检查server上的log,发现apache启动了ModSecurity模块,该模块检查了User-Agent头,如果太简单则认为是假请求(spam请求?),拒绝该HTTP请求。

用wireshark抓了一下包,发现QNetworkRequest默认的User-Agent的确非常简单:

User-Agent: Mozilla/5.0

解决方式同样简单,我们强行修改为稍微复杂一点即可,例如:

QNetworkRequest netReq;
netReq.setUrl(destUrl);
netReq.setRawHeader("User-Agent","Mozilla/5.0 (X11; Linux x86_64)");

这样就可以绕开apache模块的检查。

qt编译中抑制特定告警信息

qt编译中抑制特定告警信息

在编译某些代码时,我们希望抑制掉一些VC的编译告警,例如C4244(丢失精度告警)。我们可以直接修改mkspecs目录下对应的配置文件,但这样做会影响到所有工程,而我们实际上只希望对某些特定的工程关闭该告警。

可以直接修改pro文件,加入以下内容即可:

QMAKE_CFLAGS += /wd4244

如果是cpp文件,则指定以下参数即可:

QMAKE_CXXFLAGS += /wd4244
Phonon程序无法播放语音文件的问题

Phonon程序无法播放语音文件的问题

问题基本情况如下:我们开发并发布了一个软终端产品,当然其中采用QT以及Phonon模块。在我们的开发环境中,一切都很美好,能正常地播放音乐。可是安装到客户的计算机上,出现问题了,无法播放提示语音(wav文件录制)。

这个问题的实质是我们没有将Phonon的插件一同打包进安装文件。Phonon实质上只是个前端封装模块,具体工作有赖于后台的解码器。在windows系统中,Phonon缺省采用DirectX作为后台解码器部分,具体实现为一个plugin。如果不安装这个plugin,则phonon无法正常播放语音文件。

假设QT安装在d:\qt\4.8.4目录下,则上述plugin可以在以下目录中找到:D:\Qt\4.8.4\plugins\phonon_backend\phonon_ds94.dll。

注意,不是简单地将这个文件拷贝到程序目录下即可,而是要拷贝到程序目录的phonon_backend子目录下。例如,我们的程序安装在d:\minisipphone目录,则上述dll应当拷贝为:d:\minisipphone\phonon_backend\phonon_ds94.dll。

另外需要注意的是,不同版本的QT要采用各自版本的phonon_ds94.dll,例如qt 4.6.2的程序就不能采用qt 4.8.4的phonon_ds94.dll,否则还是会出现放音错误。

QT程序自动重启

QT程序自动重启

一行代码就可以了:

// restart application
QProcess::startDetached(qApp->applicationFilePath(), QStringList());
QT程序与gprof

QT程序与gprof

gprof能分析出函数的调用关系以及占用时间,对分析程序性能瓶颈很有帮助。

在采用QT开发时,如果程序分成若干个库,那么仅仅在编译时加入-pg选项是不能产生gmon.out文件,还必须在链接选项中也加入-pg才可以。在pro文件中做如下设置即可:

QMAKE_CXXFLAGS += -pg
QMAKE_LFLAGS += -pg

让人比较郁闷的是,gprof不支持动态链接库和Multi-Thread程序。这实在是非常大的局限。

修改QT的编译开关

修改QT的编译开关

linux系统环境的qmake工具生成的makefile文件,缺省没有打开优化开关-o2,我们可以修改pro文件来打开这个开关,如下:

unix {
QMAKE_CXXFLAGS += -o2
}

如果是采用gcc编译,则需要根据版本情况,设置QMAKE_CFLAGS_RELEASE或者QMAKE_CFLAGS_DEBUG即可。

以上配置基于Kubuntu 11.04环境。