Hello community, here is the log from the commit of package QMPlay2 for openSUSE:Factory checked in at 2016-10-23 12:51:23 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/QMPlay2 (Old) and /work/SRC/openSUSE:Factory/.QMPlay2.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "QMPlay2" Changes: -------- --- /work/SRC/openSUSE:Factory/QMPlay2/QMPlay2.changes 2016-09-26 12:36:35.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.QMPlay2.new/QMPlay2.changes 2016-10-23 12:51:25.000000000 +0200 @@ -1,0 +2,10 @@ +Sun Oct 16 09:24:24 UTC 2016 - [email protected] + +- Update to 16.10.14: + * Fix issue (deadlock/crash) if playback has been stopped + when FFmpeg resolves a hostname, + * PortAudio fixes, + * Better finding subtitles files for video, + * Bug fixes. + +------------------------------------------------------------------- Old: ---- QMPlay2-src-16.09.24.tar.xz New: ---- QMPlay2-src-16.10.14.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ QMPlay2.spec ++++++ --- /var/tmp/diff_new_pack.te4dpZ/_old 2016-10-23 12:51:26.000000000 +0200 +++ /var/tmp/diff_new_pack.te4dpZ/_new 2016-10-23 12:51:26.000000000 +0200 @@ -17,7 +17,7 @@ Name: QMPlay2 -Version: 16.09.24 +Version: 16.10.14 Release: 0 Summary: A Qt based media player, streamer and downloader License: LGPL-3.0+ ++++++ QMPlay2-src-16.09.24.tar.xz -> QMPlay2-src-16.10.14.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/ChangeLog new/QMPlay2-src-16.10.14/ChangeLog --- old/QMPlay2-src-16.09.24/ChangeLog 2016-09-24 16:42:21.000000000 +0200 +++ new/QMPlay2-src-16.10.14/ChangeLog 2016-10-14 15:25:40.000000000 +0200 @@ -1,3 +1,9 @@ +Changes in QMPlay2 build 16.10.14: + - fix issue (deadlock/crash) if playback has been stopped when FFmpeg resolves a hostname, + - PortAudio fixes (especially for Windows), + - better finding subtitles files for video, + - bugfix, + Changes in QMPlay2 build 16.09.24: - use namespace on libmodplug - don't mix system and QMPlay2 modplug, - fix screen saver inhibition regression, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/README.md new/QMPlay2-src-16.10.14/README.md --- old/QMPlay2-src-16.09.24/README.md 2016-09-21 20:36:07.000000000 +0200 +++ new/QMPlay2-src-16.10.14/README.md 2016-10-14 16:10:39.000000000 +0200 @@ -31,10 +31,6 @@ - [Download the newest Ubuntu DEB package](https://github.com/zaps166/QMPlay2/releases). -####Easy installation on Debian / Ubuntu / Mint (from unofficial repository) - -- [Follow installation instructions on OBS](https://software.opensuse.org/download.html?project=home%3Astevepassert&package=qmplay2). - ####Easy installation on Arch Linux / Manjaro Linux - Arch Linux only: Install AUR client (e.g. yaourt), @@ -63,6 +59,10 @@ ``` - Don't mix FFmpeg from different repositories! +####Easy installation on Gentoo Linux + +[Gentoo Linux repository](https://github.com/reagentoo/gentoo-overlay/tree/master/media-video/qmplay2) + ##YouTube You can change the default audio and video quality of YouTube contents. Click on the "Settings" icon on the left of the search bar, change the order of audio and/or video quality priorities and apply changes. @@ -186,7 +186,7 @@ - Common packages: ``` -$ sudo pacman -S cmake make gcc pkg-config ffmpeg libass libva libxv alsa-lib libcdio taglib libcddb libpulse libgme libsidplayfp xdg-utils +$ sudo pacman -S cmake make gcc pkg-config ffmpeg libass libva libxv alsa-lib libcdio taglib libcddb libpulse libgme libsidplayfp ``` - Qt: - for Qt5 build (recommend for Qt5 >= 5.6.1): `sudo pacman -S qt5-base qt5-tools`, @@ -199,7 +199,7 @@ - openSUSE 13.2: `sudo zypper ar http://packman.inode.at/suse/openSUSE_13.2 Packman` - Install dependencies: ``` -$ sudo zypper in cmake libqt4-devel gcc-c++ alsa-devel libpulse-devel libass-devel libtag-devel libcdio-devel libcddb-devel libXv-devel Mesa-devel libsidplayfp-devel libgme-devel libva-devel libvdpau-devel libavcodec-devel libavformat-devel libavutil-devel libswscale-devel libswresample-devel libavdevice-devel xdg-utils +$ sudo zypper in cmake libqt4-devel gcc-c++ alsa-devel libpulse-devel libass-devel libtag-devel libcdio-devel libcddb-devel libXv-devel Mesa-devel libsidplayfp-devel libgme-devel libva-devel libvdpau-devel libavcodec-devel libavformat-devel libavutil-devel libswscale-devel libswresample-devel libavdevice-devel ``` #####Ubuntu @@ -210,14 +210,14 @@ - Install dependencies from the package manager: ``` -$ sudo apt-get install cmake g++ libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libva-dev libvdpau-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libavdevice-dev xdg-utils +$ sudo apt-get install cmake g++ libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libva-dev libvdpau-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libavdevice-dev ``` #####Ubuntu 15.04 and 15.10 dependencies (Qt4 build) - Install dependencies from the package manager: ``` -$ sudo apt-get install cmake g++ libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libva-dev libvdpau-dev libavcodec-ffmpeg-dev libavformat-ffmpeg-dev libavutil-ffmpeg-dev libswscale-ffmpeg-dev libswresample-ffmpeg-dev libavdevice-ffmpeg-dev xdg-utils +$ sudo apt-get install cmake g++ libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libva-dev libvdpau-dev libavcodec-ffmpeg-dev libavformat-ffmpeg-dev libavutil-ffmpeg-dev libswscale-ffmpeg-dev libswresample-ffmpeg-dev libavdevice-ffmpeg-dev ``` #####Ubuntu 14.10 and older dependencies (Qt4 build) @@ -226,7 +226,7 @@ - Install dependencies from the package manager: ``` -$ sudo apt-get install cmake g++ yasm libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libssl-dev libva-dev libvdpau-dev xdg-utils +$ sudo apt-get install cmake g++ yasm libqt4-dev libasound2-dev libass-dev libcdio-dev libcddb2-dev libsidplayfp-dev libgme-dev libxv-dev libtag1-dev libpulse-dev libssl-dev libva-dev libvdpau-dev ``` - Remove LibAV devel files for the compilation time (this is mandatory, otherwise QMPlay2 will link to the old LibAV libraries and it will crash at runtime!): ``` @@ -247,7 +247,7 @@ - Install dependencies form the package manager: ``` -$ sudo pkg install cmake pkgconf libgme libsidplayfp libcdio libcddb libcdio libcddb libass portaudio taglib libvdpau libva xdg-utils +$ sudo pkg install cmake pkgconf libgme libsidplayfp libcdio libcddb libcdio libcddb libass portaudio taglib libvdpau libva ``` For Qt4 build install also `qt4` package. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/TODO new/QMPlay2-src-16.10.14/TODO --- old/QMPlay2-src-16.09.24/TODO 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/TODO 2016-10-14 01:32:12.000000000 +0200 @@ -1,3 +1,5 @@ +Improve YouTube support, use scripts for this +Playlist - directory browser and cover view User can type any aspect ratio and zoom Video preview on progress bar Improve radio stations @@ -17,7 +19,6 @@ - add DXVA2. Exporting audio during playback - ? -Touch screen support: scrolling - ? Users can resume downloading - ? MKV - ordered chapters - ? MIDI - ? diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/de.ts new/QMPlay2-src-16.10.14/lang/de.ts --- old/QMPlay2-src-16.09.24/lang/de.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/de.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1169,10 +1169,6 @@ <translation>ms</translation> </message> <message> - <source>Find default output device</source> - <translation>Finde das Standard-Audioausgabegerät</translation> - </message> - <message> <source>Voice removal</source> <translation>Stimme entfernen</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/es.ts new/QMPlay2-src-16.10.14/lang/es.ts --- old/QMPlay2-src-16.09.24/lang/es.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/es.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1405,10 +1405,6 @@ <translation>Frecuencia de muestreo</translation> </message> <message> - <source>Find default output device</source> - <translation>Buscar dispositivo de salida predeterminado</translation> - </message> - <message> <source>Very high</source> <translation>Muy alto</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/fr.ts new/QMPlay2-src-16.10.14/lang/fr.ts --- old/QMPlay2-src-16.09.24/lang/fr.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/fr.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1168,10 +1168,6 @@ <translation>ms</translation> </message> <message> - <source>Find default output device</source> - <translation>Trouver le périphérique de sortie par défaut</translation> - </message> - <message> <source>Voice removal</source> <translation>Suppression de voix</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/pl.ts new/QMPlay2-src-16.10.14/lang/pl.ts --- old/QMPlay2-src-16.09.24/lang/pl.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/pl.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1169,10 +1169,6 @@ <translation>ms</translation> </message> <message> - <source>Find default output device</source> - <translation>Znajdź domyślne urządzenie wyjścia dźwięku</translation> - </message> - <message> <source>Voice removal</source> <translation>Usuwanie głosu</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/ru.ts new/QMPlay2-src-16.10.14/lang/ru.ts --- old/QMPlay2-src-16.09.24/lang/ru.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/ru.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1169,10 +1169,6 @@ <translation>мс</translation> </message> <message> - <source>Find default output device</source> - <translation>Поиск устройства вывода по умолчанию</translation> - </message> - <message> <source>Voice removal</source> <translation>Удаление голоса</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/lang/zh.ts new/QMPlay2-src-16.10.14/lang/zh.ts --- old/QMPlay2-src-16.09.24/lang/zh.ts 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/lang/zh.ts 2016-10-12 22:14:10.000000000 +0200 @@ -1168,10 +1168,6 @@ <translation>毫秒</translation> </message> <message> - <source>Find default output device</source> - <translation>查找默认输出设备</translation> - </message> - <message> <source>Voice removal</source> <translation>去除人声</translation> </message> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/gui/DemuxerThr.cpp new/QMPlay2-src-16.10.14/src/gui/DemuxerThr.cpp --- old/QMPlay2-src-16.09.24/src/gui/DemuxerThr.cpp 2016-09-24 17:10:55.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/gui/DemuxerThr.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -51,7 +51,7 @@ return (avThr && avThr->writer) ? " - <i>" + decName + avThr->writer->name() + "</i>" : QString(); } -static inline QString getCoverFile(const QString &title, const QString &artist, const QString &album) +static QString getCoverFile(const QString &title, const QString &artist, const QString &album) { return QMPlay2Core.getSettingsDir() + "Covers/" + QCryptographicHash::hash((album.isEmpty() ? title.toUtf8() : album.toUtf8()) + artist.toUtf8(), QCryptographicHash::Md5).toHex(); } @@ -304,7 +304,8 @@ const QString fName = Functions::fileName(url, false).replace('_', ' '); foreach (const QString &subsFile, QDir(directory).entryList(filter, QDir::Files)) { - if (Functions::fileName(subsFile, false).replace('_', ' ').contains(fName, Qt::CaseInsensitive)) + const QString subsFName = Functions::fileName(subsFile, false).replace('_', ' '); + if (subsFName.contains(fName, Qt::CaseInsensitive) || fName.contains(subsFName, Qt::CaseInsensitive)) { const QString fileSubsUrl = Functions::Url(directory + subsFile); if (!playC.fileSubsList.contains(fileSubsUrl)) @@ -414,10 +415,10 @@ ( playC.waitForData && ( - playC.endOfStream || - bufferedAllPackets(vS, aS, forwardPackets) || //bufor pełny - (remainingDuration >= playIfBuffered) || - (qFuzzyIsNull(remainingDuration) && bufferedAllPackets(vS, aS, 2)) //bufor ma conajmniej 2 paczki, a nadal bez informacji o długości w [s] + playC.endOfStream || + bufferedAllPackets(vS, aS, forwardPackets) || //Buffer is full + (remainingDuration >= playIfBuffered) || + (qFuzzyIsNull(remainingDuration) && bufferedAllPackets(vS, aS, 2)) //Buffer has at least 2 packets, but still without length (in seconds) information ) ) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/CMakeLists.txt new/QMPlay2-src-16.10.14/src/modules/FFmpeg/CMakeLists.txt --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/CMakeLists.txt 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/CMakeLists.txt 2016-10-12 22:14:10.000000000 +0200 @@ -21,6 +21,7 @@ FFCommon.hpp FormatContext.hpp OggHelper.hpp + OpenThr.hpp ) set(FFmpeg_SRC @@ -32,6 +33,7 @@ FFCommon.cpp FormatContext.cpp OggHelper.cpp + OpenThr.cpp ) set(FFmpeg_RESOURCES diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFReader.cpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFReader.cpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFReader.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFReader.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -29,16 +29,44 @@ return aborted; } +class OpenAvioThr : public OpenThr +{ + AVIOContext *m_avioCtx; + +public: + inline OpenAvioThr(const QByteArray &url, AVDictionary *options, QSharedPointer<AbortContext> &abortCtx) : + OpenThr(url, options, abortCtx), + m_avioCtx(NULL) + { + start(); + } + + inline AVIOContext *getAvioCtx() const + { + return waitForOpened() ? m_avioCtx : NULL; + } + +private: + void run() + { + const AVIOInterruptCB interruptCB = {(int(*)(void*))::interruptCB, &m_abortCtx->isAborted}; + avio_open2(&m_avioCtx, m_url, AVIO_FLAG_READ, &interruptCB, &m_options); + if (!wakeIfNotAborted() && m_avioCtx) + avio_close(m_avioCtx); + } +}; + /**/ FFReader::FFReader() : avioCtx(NULL), - aborted(false), paused(false), canRead(false) + paused(false), canRead(false), + abortCtx(new AbortContext) {} bool FFReader::readyRead() const { - return canRead && !aborted; + return canRead && !abortCtx->isAborted; } bool FFReader::canSeek() const { @@ -83,7 +111,7 @@ } void FFReader::abort() { - aborted = true; + abortCtx->abort(); } qint64 FFReader::size() const @@ -103,10 +131,15 @@ { AVDictionary *options = NULL; const QString url = FFCommon::prepareUrl(getUrl(), options); - AVIOInterruptCB interruptCB = {(int(*)(void*))::interruptCB, &aborted}; - if (avio_open2(&avioCtx, url.toUtf8(), AVIO_FLAG_READ, &interruptCB, &options) >= 0) - return (canRead = true); - return false; + + OpenAvioThr *openThr = new OpenAvioThr(url.toUtf8(), options, abortCtx); + avioCtx = openThr->getAvioCtx(); + openThr->drop(); + + if (avioCtx) + canRead = true; + + return canRead; } FFReader::~FFReader() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFReader.hpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFReader.hpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFReader.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFReader.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -21,6 +21,8 @@ #include <Reader.hpp> +#include <OpenThr.hpp> + struct AVIOContext; class FFReader : public Reader @@ -48,7 +50,8 @@ ~FFReader(); AVIOContext *avioCtx; - bool aborted, paused, canRead; + bool paused, canRead; + QSharedPointer<AbortContext> abortCtx; }; #endif // FFREADER_HPP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFmpeg.pro new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFmpeg.pro --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FFmpeg.pro 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FFmpeg.pro 2016-10-12 22:14:10.000000000 +0200 @@ -34,8 +34,8 @@ INCLUDEPATH += . ../../qmplay2/headers DEPENDPATH += . ../../qmplay2/headers -HEADERS += FFmpeg.hpp FFDemux.hpp FFDec.hpp FFDecSW.hpp FFReader.hpp FFCommon.hpp FormatContext.hpp OggHelper.hpp -SOURCES += FFmpeg.cpp FFDemux.cpp FFDec.cpp FFDecSW.cpp FFReader.cpp FFCommon.cpp FormatContext.cpp OggHelper.cpp +HEADERS += FFmpeg.hpp FFDemux.hpp FFDec.hpp FFDecSW.hpp FFReader.hpp FFCommon.hpp FormatContext.hpp OggHelper.hpp OpenThr.hpp +SOURCES += FFmpeg.cpp FFDemux.cpp FFDec.cpp FFDecSW.cpp FFReader.cpp FFCommon.cpp FormatContext.cpp OggHelper.cpp OpenThr.cpp unix:!macx:!android { PKGCONFIG += libavdevice diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FormatContext.cpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FormatContext.cpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FormatContext.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FormatContext.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -134,19 +134,49 @@ { av_packet_unref(packet); } + private: AVPacket *packet; }; +class OpenFmtCtxThr : public OpenThr +{ + AVFormatContext *m_formatCtx; + AVInputFormat *m_inputFmt; + +public: + inline OpenFmtCtxThr(AVFormatContext *formatCtx, const QByteArray &url, AVInputFormat *inputFmt, AVDictionary *options, QSharedPointer<AbortContext> &abortCtx) : + OpenThr(url, options, abortCtx), + m_formatCtx(formatCtx), + m_inputFmt(inputFmt) + { + start(); + } + + inline AVFormatContext *getFormatCtx() const + { + return waitForOpened() ? m_formatCtx : NULL; + } + +private: + void run() + { + avformat_open_input(&m_formatCtx, m_url, m_inputFmt, &m_options); + if (!wakeIfNotAborted() && m_formatCtx) + avformat_close_input(&m_formatCtx); + } +}; + /**/ FormatContext::FormatContext(QMutex &avcodec_mutex) : isError(false), currPos(0.0), + abortCtx(new AbortContext), formatCtx(NULL), packet(NULL), oggHelper(NULL), - isPaused(false), isAborted(false), fixMkvAss(false), + isPaused(false), fixMkvAss(false), isMetadataChanged(false), lastTime(0.0), invalErrCount(0), errFromSeek(0), @@ -409,7 +439,7 @@ bool FormatContext::seek(int pos, bool backward) { bool isOk = false; - isAborted = false; + abortCtx->isAborted = false; if (!isStreamed) { const int len = length(); @@ -459,7 +489,7 @@ } bool FormatContext::read(Packet &encoded, int &idx) { - if (isAborted) + if (abortCtx->isAborted) { isError = true; return false; @@ -606,7 +636,7 @@ } void FormatContext::abort() { - isAborted = true; + abortCtx->abort(); } bool FormatContext::open(const QString &_url, const QString ¶m) @@ -668,7 +698,7 @@ formatCtx = avformat_alloc_context(); formatCtx->interrupt_callback.callback = (int(*)(void *))interruptCB; - formatCtx->interrupt_callback.opaque = &isAborted; + formatCtx->interrupt_callback.opaque = &abortCtx->isAborted; if (oggOffset >= 0) { @@ -679,7 +709,10 @@ av_dict_set(&options, "skip_initial_bytes", QString::number(oggOffset).toLatin1(), 0); } - if (avformat_open_input(&formatCtx, url.toUtf8(), inputFmt, &options) || !formatCtx || disabledDemuxers.contains(name())) + OpenFmtCtxThr *openThr = new OpenFmtCtxThr(formatCtx, url.toUtf8(), inputFmt, options, abortCtx); + formatCtx = openThr->getFormatCtx(); + openThr->drop(); + if (!formatCtx || disabledDemuxers.contains(name())) return false; #ifdef MP3_FAST_SEEK diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FormatContext.hpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FormatContext.hpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/FormatContext.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/FormatContext.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -19,12 +19,12 @@ #ifndef FORMATCONTEXT_HPP #define FORMATCONTEXT_HPP +#include <OpenThr.hpp> + #include <ChapterProgramInfo.hpp> #include <TimeStamp.hpp> #include <QCoreApplication> -#include <QVector> -#include <QMutex> extern "C" { @@ -78,6 +78,8 @@ StreamInfo *getStreamInfo(AVStream *stream) const; AVDictionary *getMetadata() const; + QSharedPointer<AbortContext> abortCtx; + QVector<int> index_map; QVector<AVStream *> streams; QVector<TimeStamp> streamsTS; @@ -87,7 +89,7 @@ OggHelper *oggHelper; - bool isPaused, isAborted, fixMkvAss; + bool isPaused, fixMkvAss; mutable bool isMetadataChanged; double lastTime, startTime; #ifndef MP3_FAST_SEEK diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/OpenThr.cpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/OpenThr.cpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/OpenThr.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/OpenThr.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -0,0 +1,71 @@ +/* + QMPlay2 is a video and audio player. + Copyright (C) 2010-2016 Błażej Szczygieł + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <OpenThr.hpp> + +#include <QCoreApplication> + +extern "C" +{ + #include <libavformat/avformat.h> +} + +void AbortContext::abort() +{ + QMutexLocker locker(&openMutex); + isAborted = true; + openCond.wakeOne(); +} + +/**/ + +void OpenThr::drop() +{ + moveToThread(qApp->thread()); //Execute "deleteLater()" in main thread, because in this thread "processEvents()" might not be called. +} + +OpenThr::OpenThr(const QByteArray &url, AVDictionary *options, QSharedPointer<AbortContext> &abortCtx) : + m_url(url), + m_options(options), + m_abortCtx(abortCtx), + m_finished(false) +{ + connect(this, SIGNAL(finished()), this, SLOT(deleteLater())); +} + +bool OpenThr::waitForOpened() const +{ + QMutexLocker locker(&m_abortCtx->openMutex); + if (!m_finished && !m_abortCtx->isAborted) + m_abortCtx->openCond.wait(&m_abortCtx->openMutex); + if (m_abortCtx->isAborted) + return false; + return true; +} + +bool OpenThr::wakeIfNotAborted() +{ + QMutexLocker locker(&m_abortCtx->openMutex); + if (!m_abortCtx->isAborted) + { + m_finished = true; + m_abortCtx->openCond.wakeOne(); + return true; + } + return false; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/FFmpeg/OpenThr.hpp new/QMPlay2-src-16.10.14/src/modules/FFmpeg/OpenThr.hpp --- old/QMPlay2-src-16.09.24/src/modules/FFmpeg/OpenThr.hpp 1970-01-01 01:00:00.000000000 +0100 +++ new/QMPlay2-src-16.10.14/src/modules/FFmpeg/OpenThr.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -0,0 +1,69 @@ +/* + QMPlay2 is a video and audio player. + Copyright (C) 2010-2016 Błażej Szczygieł + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef OPENTHR_HPP +#define OPENTHR_HPP + +#include <QSharedPointer> +#include <QWaitCondition> +#include <QThread> +#include <QMutex> + +class AbortContext +{ +public: + inline AbortContext() : + isAborted(false) + {} + + void abort(); + + QWaitCondition openCond; + QMutex openMutex; + bool isAborted; +}; + +/**/ + +struct AVFormatContext; +struct AVInputFormat; +struct AVDictionary; + +class OpenThr : public QThread +{ +public: + void drop(); + +protected: + OpenThr(const QByteArray &url, AVDictionary *options, QSharedPointer<AbortContext> &abortCtx); + + bool waitForOpened() const; + + bool wakeIfNotAborted(); + + const QByteArray m_url; + AVInputFormat *m_inputFmt; + AVDictionary *m_options; + + QSharedPointer<AbortContext> m_abortCtx; + +private: + bool m_finished; +}; + +#endif // OPENTHR_HPP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudio.cpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudio.cpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudio.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudio.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -24,7 +24,7 @@ { moduleImg = QImage(":/PortAudio"); - Pa_Initialize(); + initialized = (Pa_Initialize() == paNoError); init("WriterEnabled", true); #ifdef Q_OS_WIN init("Delay", 0.15); @@ -35,13 +35,14 @@ } PortAudio::~PortAudio() { - Pa_Terminate(); + if (initialized) + Pa_Terminate(); } QList<PortAudio::Info> PortAudio::getModulesInfo(const bool showDisabled) const { QList<Info> modulesInfo; - if (showDisabled || getBool("WriterEnabled")) + if (initialized && (showDisabled || getBool("WriterEnabled"))) modulesInfo += Info(PortAudioWriterName, WRITER, QStringList("audio")); return modulesInfo; } @@ -85,22 +86,12 @@ int idx = devicesB->findText(sets().getString("OutputDevice")); devicesB->setCurrentIndex(idx < 0 ? 0 : idx); - QPushButton *defaultDevs = new QPushButton; - defaultDevs->setText(tr("Find default output device")); - connect(defaultDevs, SIGNAL(clicked()), this, SLOT(defaultDevs())); - QFormLayout *layout = new QFormLayout(this); layout->addRow(enabledB); layout->addRow(tr("Playback device") + ": ", devicesB); - layout->addRow(QString(), defaultDevs); layout->addRow(tr("Delay") + ": ", delayB); } -void ModuleSettingsWidget::defaultDevs() -{ - devicesB->setCurrentIndex(PortAudioCommon::deviceIndexToOutputIndex(PortAudioCommon::getDefaultOutputDevice()) + 1); -} - void ModuleSettingsWidget::saveSettings() { sets().set("WriterEnabled", enabledB->isChecked()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudio.hpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudio.hpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudio.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudio.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -28,21 +28,23 @@ void *createInstance(const QString &); SettingsWidget *getSettingsWidget(); + + bool initialized; }; /**/ +#include <QCoreApplication> + class QDoubleSpinBox; class QCheckBox; class QComboBox; class ModuleSettingsWidget : public Module::SettingsWidget { - Q_OBJECT + Q_DECLARE_TR_FUNCTIONS(ModuleSettingsWidget) public: ModuleSettingsWidget(Module &); -private slots: - void defaultDevs(); private: void saveSettings(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioCommon.cpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioCommon.cpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioCommon.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioCommon.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -21,56 +21,59 @@ #include <portaudio.h> -#define getOutputDeviceName QString(hostApiInfo->name) + ": " + QString::fromLocal8Bit(deviceInfo->name) +static inline QString getOutputDeviceName(const PaDeviceInfo *deviceInfo) +{ + return QString(Pa_GetHostApiInfo(deviceInfo->hostApi)->name) + ": " + QString::fromLocal8Bit(deviceInfo->name); +} + +/**/ QStringList PortAudioCommon::getOutputDeviceNames() { QStringList outputDeviceNames; - int numDevices = Pa_GetDeviceCount(); + const int numDevices = Pa_GetDeviceCount(); for (int i = 0; i < numDevices; i++) { const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i); - if (deviceInfo) - { - const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi); - if (deviceInfo->maxOutputChannels > 0) - outputDeviceNames += getOutputDeviceName; - } + if (deviceInfo && deviceInfo->maxOutputChannels > 0) + outputDeviceNames += getOutputDeviceName(deviceInfo); } return outputDeviceNames; } -int PortAudioCommon::getDeviceIndexForOutput(const QString &name) +int PortAudioCommon::getDeviceIndexForOutput(const QString &name, const int chn) { - int numDevices = Pa_GetDeviceCount(); - for (int i = 0; i < numDevices; i++) + if (!name.isEmpty()) { - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i); - if (deviceInfo) + const int numDevices = Pa_GetDeviceCount(); + for (int i = 0; i < numDevices; i++) { - const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi); - if (deviceInfo->maxOutputChannels > 0 && name == getOutputDeviceName) + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i); + if (deviceInfo && deviceInfo->maxOutputChannels > 0 && getOutputDeviceName(deviceInfo) == name) return i; } } - return getDefaultOutputDevice(); -} -int PortAudioCommon::getDefaultOutputDevice() -{ -#ifdef Q_OS_LINUX - if (getOutputDeviceNames().contains("ALSA: default")) - return getDeviceIndexForOutput("ALSA: default"); -#endif - return Pa_GetDefaultOutputDevice(); -} -int PortAudioCommon::deviceIndexToOutputIndex(int dev) -{ - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(dev); - if (deviceInfo) + + //Find the default device +#if defined Q_OS_LINUX + if (chn > 0) + { + const char alsaDefault[] = "ALSA: default"; + if (getOutputDeviceNames().contains(alsaDefault)) + return getDeviceIndexForOutput(alsaDefault, 0); + } +#elif defined Q_OS_WIN + if (chn <= 2) { - const PaHostApiInfo *hostApiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi); - int idx = getOutputDeviceNames().indexOf(getOutputDeviceName); - if (idx > -1) - return idx; + const int numDevices = Pa_GetDeviceCount(); + for (int i = 0; i < numDevices; i++) + { + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i); + if (deviceInfo && deviceInfo->maxOutputChannels > 0 && Pa_GetHostApiInfo(deviceInfo->hostApi)->type == paMME) + return i; //First MME output device is a "WAVE_MAPPER". The "WAVE_MAPPER" doesn't support multi-channel. + } } - return dev; +#else + Q_UNUSED(chn) +#endif + return Pa_GetDefaultOutputDevice(); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioCommon.hpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioCommon.hpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioCommon.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioCommon.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -24,9 +24,7 @@ namespace PortAudioCommon { QStringList getOutputDeviceNames(); - int getDeviceIndexForOutput(const QString &); - int getDefaultOutputDevice(); - int deviceIndexToOutputIndex(int); + int getDeviceIndexForOutput(const QString &name, const int chn); } #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioWriter.cpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioWriter.cpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioWriter.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioWriter.cpp 2016-10-13 14:58:36.000000000 +0200 @@ -19,6 +19,10 @@ #include <PortAudioWriter.hpp> #include <QMPlay2Core.hpp> +#ifdef Q_OS_WIN + #define MMSYSERR_NODRIVER 6 +#endif + PortAudioWriter::PortAudioWriter(Module &module) : stream(NULL), sample_rate(0), @@ -29,7 +33,7 @@ addParam("rate"); addParam("drain"); - memset(&outputParameters, 0, sizeof(outputParameters)); + memset(&outputParameters, 0, sizeof outputParameters); outputParameters.sampleFormat = paFloat32; outputParameters.hostApiSpecificStreamInfo = NULL; @@ -43,11 +47,11 @@ bool PortAudioWriter::set() { bool restartPlaying = false; - int devIdx = PortAudioCommon::getDeviceIndexForOutput(sets().getString("OutputDevice")); - double delay = sets().getDouble("Delay"); - if (outputParameters.device != devIdx) + const double delay = sets().getDouble("Delay"); + const QString newOutputDevice = sets().getString("OutputDevice"); + if (outputDevice != newOutputDevice) { - outputParameters.device = devIdx; + outputDevice = newOutputDevice; restartPlaying = true; } if (outputParameters.suggestedLatency != delay) @@ -68,6 +72,14 @@ bool resetAudio = false; int chn = getParam("chn").toInt(); + + const int devIdx = PortAudioCommon::getDeviceIndexForOutput(outputDevice, chn); + if (outputParameters.device != devIdx) + { + outputParameters.device = devIdx; + resetAudio = true; + } + if (paramsCorrected) { const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(outputParameters.device); @@ -77,6 +89,7 @@ *paramsCorrected = true; } } + if (outputParameters.channelCount != chn) { resetAudio = true; @@ -93,14 +106,11 @@ if (resetAudio || err) { close(); - err = Pa_OpenStream(&stream, NULL, &outputParameters, sample_rate, 0, paDitherOff, NULL, NULL); - if (!err) + if (!openStream()) { - outputLatency = Pa_GetStreamInfo(stream)->outputLatency; - modParam("delay", outputLatency); - } - else QMPlay2Core.logError("PortAudio :: " + tr("Cannot open audio output stream")); + err = true; + } } return readyWrite(); @@ -111,16 +121,30 @@ return 0; if (Pa_IsStreamStopped(stream)) - Pa_StartStream(stream); - -#ifndef Q_OS_MAC //? - int diff = Pa_GetStreamWriteAvailable(stream) - outputLatency * sample_rate; - if (diff > 0) - Pa_WriteStream(stream, QByteArray(diff * outputParameters.channelCount * sizeof(float), 0).constData(), diff); + { + if (!startStream()) + return playbackError(); + fullBufferReached = false; + } +#ifndef Q_OS_MAC + else + { + const int diff = Pa_GetStreamWriteAvailable(stream) - outputLatency * sample_rate; + if (diff <= 0) + fullBufferReached = true; + else if (fullBufferReached) + { + //Reset stream to prevent potential short audio garbage on Windows + Pa_AbortStream(stream); + if (!startStream()) + return playbackError(); + fullBufferReached = false; + } + } #endif -#ifdef Q_OS_LINUX - int chn = outputParameters.channelCount; +#ifdef Q_OS_LINUX //FIXME: Does OSS on FreeBSD need channel swapping? Also don't do it on const data. + const int chn = outputParameters.channelCount; if (chn == 6 || chn == 8) { float *audio_buffer = (float *)arr.data(); @@ -136,12 +160,20 @@ } #endif - int e = Pa_WriteStream(stream, arr.constData(), arr.size() / outputParameters.channelCount / sizeof(float)); - if (e == paUnanticipatedHostError) + if (!writeStream(arr)) { - QMPlay2Core.logError("PortAudio :: " + tr("Playback error")); - err = true; - return 0; + bool isError = true; + +#ifdef Q_OS_WIN + if (isNoDriverError() && reopenStream()) //"writeStream()" must fail only on "paUnanticipatedHostError" + { + isError = !writeStream(arr); + fullBufferReached = false; + } +#endif + + if (isError) + return playbackError(); } return arr.size(); @@ -164,6 +196,61 @@ /**/ +bool PortAudioWriter::openStream() +{ + PaStream *newStream = NULL; + if (Pa_OpenStream(&newStream, NULL, &outputParameters, sample_rate, 0, paDitherOff, NULL, NULL) == paNoError) + { + stream = newStream; + outputLatency = Pa_GetStreamInfo(stream)->outputLatency; + modParam("delay", outputLatency); + return true; + } + return false; +} +bool PortAudioWriter::startStream() +{ + const PaError e = Pa_StartStream(stream); + if (e != paNoError) + { +#ifdef Q_OS_WIN + if (e == paUnanticipatedHostError && isNoDriverError()) + return reopenStream(); +#endif + return false; + } + return true; +} +inline bool PortAudioWriter::writeStream(const QByteArray &arr) +{ + const PaError e = Pa_WriteStream(stream, arr.data(), arr.size() / outputParameters.channelCount / sizeof(float)); + if (e != paNoError) + fullBufferReached = false; + return (e != paUnanticipatedHostError); +} +qint64 PortAudioWriter::playbackError() +{ + QMPlay2Core.logError("PortAudio :: " + tr("Playback error")); + err = true; + return 0; +} + +#ifdef Q_OS_WIN +bool PortAudioWriter::isNoDriverError() const +{ + const PaHostErrorInfo *errorInfo = Pa_GetLastHostErrorInfo(); + return errorInfo && errorInfo->hostApiType == paMME && errorInfo->errorCode == MMSYSERR_NODRIVER; +} +bool PortAudioWriter::reopenStream() +{ + Pa_CloseStream(stream); + if (openStream()) + return (Pa_StartStream(stream) == paNoError); + stream = NULL; + return false; +} +#endif + void PortAudioWriter::close() { if (stream) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioWriter.hpp new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioWriter.hpp --- old/QMPlay2-src-16.09.24/src/modules/PortAudio/PortAudioWriter.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PortAudio/PortAudioWriter.hpp 2016-10-13 14:44:26.000000000 +0200 @@ -45,13 +45,24 @@ /**/ + bool openStream(); + bool startStream(); + inline bool writeStream(const QByteArray &arr); + qint64 playbackError(); + +#ifdef Q_OS_WIN + bool isNoDriverError() const; + bool reopenStream(); +#endif + void close(); + QString outputDevice; PaStreamParameters outputParameters; PaStream *stream; int sample_rate; double outputLatency; - bool err; + bool err, fullBufferReached; }; #define PortAudioWriterName "PortAudio" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PulseAudio/Pulse.cpp new/QMPlay2-src-16.10.14/src/modules/PulseAudio/Pulse.cpp --- old/QMPlay2-src-16.09.24/src/modules/PulseAudio/Pulse.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PulseAudio/Pulse.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -126,11 +126,13 @@ } } -bool Pulse::write(const QByteArray &arr) +bool Pulse::write(const QByteArray &arr, bool &showError) { int error = 0; writing = true; const bool ret = pa_simple_write(pulse, arr.data(), arr.size(), &error) >= 0; writing = false; + if (error == PA_ERR_KILLED) + showError = false; return (ret || error == PA_ERR_INVALID); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PulseAudio/Pulse.hpp new/QMPlay2-src-16.10.14/src/modules/PulseAudio/Pulse.hpp --- old/QMPlay2-src-16.09.24/src/modules/PulseAudio/Pulse.hpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PulseAudio/Pulse.hpp 2016-10-12 22:14:10.000000000 +0200 @@ -41,7 +41,7 @@ bool start(); void stop(bool drain = false); - bool write(const QByteArray &); + bool write(const QByteArray &, bool &showError); double delay; uchar channels; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/modules/PulseAudio/PulseAudioWriter.cpp new/QMPlay2-src-16.10.14/src/modules/PulseAudio/PulseAudioWriter.cpp --- old/QMPlay2-src-16.09.24/src/modules/PulseAudio/PulseAudioWriter.cpp 2016-09-05 01:22:20.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/modules/PulseAudio/PulseAudioWriter.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -83,10 +83,12 @@ if (!arr.size() || !readyWrite()) return 0; - err = !pulse.write(arr); + bool showError = true; + err = !pulse.write(arr, showError); if (err) { - QMPlay2Core.logError("PulseAudio :: " + tr("Playback error")); + if (showError) + QMPlay2Core.logError("PulseAudio :: " + tr("Playback error")); return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/qmplay2/Functions.cpp new/QMPlay2-src-16.10.14/src/qmplay2/Functions.cpp --- old/QMPlay2-src-16.09.24/src/qmplay2/Functions.cpp 2016-09-17 22:53:36.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/qmplay2/Functions.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -42,7 +42,7 @@ QDate Functions::parseVersion(const QString &dateTxt) { - QStringList l = dateTxt.split('.'); + const QStringList l = dateTxt.split('.'); int y = 0, m = 0, d = 0; if (l.count() == 3) { @@ -155,13 +155,13 @@ while (f.endsWith("/")) f.chop(1); const QString n = f.right(f.length() - f.lastIndexOf('/') - 1); - if (extension || !f.startsWith("file://")) + if (extension || (!f.startsWith("file://") && f.contains("://"))) return n; return n.mid(0, n.lastIndexOf('.')); } QString Functions::fileExt(const QString &f) { - int idx = f.lastIndexOf('.'); + const int idx = f.lastIndexOf('.'); if (idx > -1) return f.mid(idx+1); return QString(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/qmplay2/InDockW.cpp new/QMPlay2-src-16.10.14/src/qmplay2/InDockW.cpp --- old/QMPlay2-src-16.09.24/src/qmplay2/InDockW.cpp 2016-09-17 22:53:36.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/qmplay2/InDockW.cpp 2016-10-12 22:14:10.000000000 +0200 @@ -111,6 +111,16 @@ } if ((w = _w)) { +#if QT_VERSION < 0x050000 + //Workaround for BUG in Qt4 + QWidget *mainWidget = window(); + if (mainWidget && mainWidget->isMinimized() && w->internalWinId() && !internalWinId()) + { + mainWidget->hide(); + mainWidget->show(); + } +#endif + w->setMinimumSize(2, 2); w->setParent(this); resizeEvent(NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/QMPlay2-src-16.09.24/src/qmplay2/headers/Version.hpp new/QMPlay2-src-16.10.14/src/qmplay2/headers/Version.hpp --- old/QMPlay2-src-16.09.24/src/qmplay2/headers/Version.hpp 2016-09-24 16:42:37.000000000 +0200 +++ new/QMPlay2-src-16.10.14/src/qmplay2/headers/Version.hpp 2016-10-14 15:25:52.000000000 +0200 @@ -19,7 +19,7 @@ #ifndef VERSION_HPP #define VERSION_HPP -#define QMPlay2Version "16.09.24" +#define QMPlay2Version "16.10.14" #define QMPlay2UserAgent ("QMPlay2/" QMPlay2Version) #endif // VERSION_HPP
