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 &param)
@@ -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


Reply via email to