This commit is contained in:
John Preston 2015-06-01 14:15:30 +03:00
commit 175023b2dc
18 changed files with 811 additions and 57 deletions

View File

@ -1,10 +1,10 @@
@echo OFF
set "AppVersion=8017"
set "AppVersionStrSmall=0.8.17"
set "AppVersionStr=0.8.17"
set "AppVersionStrFull=0.8.17.0"
set "DevChannel=0"
set "AppVersion=8018"
set "AppVersionStrSmall=0.8.18"
set "AppVersionStr=0.8.18"
set "AppVersionStrFull=0.8.18.0"
set "DevChannel=1"
if %DevChannel% neq 0 goto preparedev

View File

@ -1543,6 +1543,7 @@ namespace App {
cSetStickerSets(StickerSets());
cSetStickerSetsOrder(StickerSetsOrder());
cSetLastStickersUpdate(0);
LOG(("Stickers: cleared everything!"));
::videoItems.clear();
::audioItems.clear();
::documentItems.clear();

View File

@ -96,6 +96,7 @@ bool _checkALError() {
void audioInit() {
if (!capture) {
capture = new AudioCapture();
cSetHasAudioCapture(capture->check());
}
uint64 ms = getms();
@ -202,6 +203,7 @@ void audioInit() {
avcodec_register_all();
LOG(("Audio init time: %1").arg(getms() - ms));
cSetHasAudioPlayer(true);
}
void audioPlayNotify() {
@ -240,6 +242,9 @@ void audioFinish() {
alcCloseDevice(audioDevice);
audioDevice = 0;
}
cSetHasAudioCapture(false);
cSetHasAudioPlayer(false);
}
AudioPlayer::AudioPlayer() : _current(0),
@ -421,6 +426,16 @@ void AudioCapture::stop(bool needResult) {
emit captureOnStop(needResult);
}
bool AudioCapture::check() {
if (const ALCchar *def = alcGetString(0, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) {
if (ALCdevice *dev = alcCaptureOpenDevice(def, AudioVoiceMsgFrequency, AL_FORMAT_MONO16, AudioVoiceMsgFrequency / 5)) {
alcCaptureCloseDevice(dev);
return _checkALCError();
}
}
return false;
}
AudioCapture::~AudioCapture() {
capture = 0;
_captureThread.quit();

View File

@ -119,6 +119,8 @@ public:
void start();
void stop(bool needResult);
bool check();
~AudioCapture();
signals:

View File

@ -17,9 +17,9 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
*/
#pragma once
static const int32 AppVersion = 8017;
static const wchar_t *AppVersionStr = L"0.8.17";
static const bool DevChannel = false;
static const int32 AppVersion = 8018;
static const wchar_t *AppVersionStr = L"0.8.18";
static const bool DevChannel = true;
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
static const wchar_t *AppName = L"Telegram Desktop";

View File

@ -1384,6 +1384,8 @@ void StickerPanInner::refreshStickers() {
_hovers.clear(); _hovers.reserve(sets.size() + 1);
_titles.clear(); _titles.reserve(sets.size() + 1);
LOG(("Stickers: refreshing pan, sets size: %1").arg(sets.size()));
refreshRecent(false);
appendSet(CustomStickerSetId);
@ -1429,10 +1431,12 @@ void StickerPanInner::preloadImages() {
}
void StickerPanInner::appendSet(uint64 setId) {
LOG(("Stickers: appending set %1..").arg(setId));
const StickerSets &sets(cStickerSets());
StickerSets::const_iterator it = sets.constFind(setId);
if (it == sets.cend() || it->stickers.isEmpty()) return;
LOG(("Stickers: set %1 found! %2 stickers there.").arg(setId).arg(it->stickers.size()));
StickerPack pack;
pack.reserve(it->stickers.size());
for (int32 i = 0, l = it->stickers.size(); i < l; ++i) {
@ -1448,6 +1452,7 @@ void StickerPanInner::appendSet(uint64 setId) {
void StickerPanInner::refreshRecent(bool performResize) {
clearSelection(true);
if (cGetRecentStickers().isEmpty()) {
LOG(("Stickers: no recent!"));
if (!_setIds.isEmpty() && _setIds.at(0) == RecentStickerSetId) {
_setIds.pop_front();
_sets.pop_front();
@ -1455,6 +1460,7 @@ void StickerPanInner::refreshRecent(bool performResize) {
_titles.pop_front();
}
} else {
LOG(("Stickers: %1 recent stickers!").arg(cGetRecentStickers().size()));
StickerPack recent;
recent.reserve(cGetRecentStickers().size());
for (int32 i = 0, l = cGetRecentStickers().size(); i < l; ++i) {
@ -2044,6 +2050,7 @@ void EmojiPan::onRemoveSetSure() {
++i;
}
}
LOG(("Stickers: removed one set, %1.").arg(_removingSetId));
cRefStickerSets().erase(it);
cRefStickerSetsOrder().removeOne(_removingSetId);
cSetStickersHash(QByteArray());

View File

@ -1710,18 +1710,20 @@ void HistoryWidget::start() {
void HistoryWidget::onTextChange() {
updateTyping();
if (_field.getLastText().isEmpty()) {
_previewCancelled = false;
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
} else if (!_field.isHidden()) {
_send.show();
setMouseTracking(false);
_recordAnim.stop();
_inRecord = _inField = false;
a_recordOver = a_recordDown = anim::fvalue(0, 0);
a_recordCancel = anim::cvalue(st::recordCancel->c, st::recordCancel->c);
if (cHasAudioCapture()) {
if (_field.getLastText().isEmpty()) {
_previewCancelled = false;
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
} else if (!_field.isHidden() && _send.isHidden()) {
_send.show();
setMouseTracking(false);
_recordAnim.stop();
_inRecord = _inField = false;
a_recordOver = a_recordDown = anim::fvalue(0, 0);
a_recordCancel = anim::cvalue(st::recordCancel->c, st::recordCancel->c);
}
}
if (!hist || _synthedTextUpdate) return;
@ -1849,6 +1851,8 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
cSetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
LOG(("Stickers: got from server!"));
if (stickers.type() != mtpc_messages_allStickers) return;
const MTPDmessages_allStickers &d(stickers.c_messages_allStickers());
@ -1857,6 +1861,8 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
const QVector<MTPDocument> &d_docs(d.vdocuments.c_vector().v);
const QVector<MTPStickerSet> &d_sets(d.vsets.c_vector().v);
LOG(("Stickers: clearing everything, got all stickers"));
QByteArray wasHash = cStickersHash();
cSetStickersHash(qba(d.vhash));
@ -1995,10 +2001,13 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
}
}
}
LOG(("Stickers: now %1 sets, %2 recent").arg(sets.size()).arg(recent.size()));
if (added || removed || cStickersHash() != wasHash) {
LOG(("Stickers: writing stickers from gotAll!"));
Local::writeStickers();
}
if (writeRecent) {
LOG(("Stickers: writing recent stickers from gotAll!"));
Local::writeUserSettings();
}
@ -2047,6 +2056,8 @@ void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
bool HistoryWidget::stickersFailed(const RPCError &error) {
if (error.type().startsWith(qsl("FLOOD_WAIT_"))) return false;
LOG(("App Fail: Failed to get stickers!"));
cSetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
return true;
@ -2329,7 +2340,7 @@ void HistoryWidget::updateControlsVisibility() {
_toHistoryEnd.show();
}
if (!histPeer->chat || !histPeer->asChat()->forbidden) {
if (_field.getLastText().isEmpty()) {
if (cHasAudioCapture() && _field.getLastText().isEmpty()) {
_send.hide();
setMouseTracking(true);
mouseMoveEvent(0);
@ -3019,7 +3030,7 @@ void HistoryWidget::mouseReleaseEvent(QMouseEvent *e) {
_attachDrag = DragStateNone;
updateDragAreas();
}
if (_recording && audioCapture()) {
if (_recording && cHasAudioCapture()) {
stopRecording(_inField);
}
}
@ -3796,7 +3807,7 @@ void HistoryWidget::mousePressEvent(QMouseEvent *e) {
_replyForwardPressed = QRect(0, _field.y() - st::replyHeight, st::replySkip, st::replyHeight).contains(e->pos());
if (_replyForwardPressed && !_replyForwardPreviewCancel.isHidden()) {
update(0, _field.y() - st::sendPadding - st::replyHeight, width(), st::replyHeight);
} else if (_inRecord && audioCapture()) {
} else if (_inRecord && cHasAudioCapture()) {
audioCapture()->start();
_recording = _inField = true;

View File

@ -105,7 +105,7 @@ void LocalImageLoaderPrivate::prepareImages() {
}
if (mime == "image/jpeg") {
filename = filedialogDefaultName(qsl("image"), qsl(".jpg"), QString(), true);
} else if (mime == "application/ogg" && type == ToPrepareAudio) {
} else if (type == ToPrepareAudio) {
filename = filedialogDefaultName(qsl("audio"), qsl(".ogg"), QString(), true);
mime = "audio/ogg";
} else {

View File

@ -2278,16 +2278,20 @@ namespace Local {
}
void importOldRecentStickers() {
LOG(("Stickers: importOldStickers()"));
if (!_recentStickersKeyOld) return;
FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, _recentStickersKeyOld)) {
LOG(("Stickers: could not readEncryptedFile(_recentStickersKeyOld)!"));
clearKey(_recentStickersKeyOld);
_recentStickersKeyOld = 0;
_writeMap();
return;
}
LOG(("Stickers: clearing everything in import-old!"));
StickerSets &sets(cRefStickerSets());
sets.clear();
cSetStickerSetsOrder(StickerSetsOrder());
@ -2334,6 +2338,7 @@ namespace Local {
}
if (recent.size() < StickerPanPerRow * StickerPanRowsPerPage && qAbs(value) > 1) recent.push_back(qMakePair(doc, qAbs(value)));
}
LOG(("Stickers: read %1 default stickers and %2 custom stickers").arg(def.stickers.size()).arg(custom.stickers.size()));
if (def.stickers.isEmpty()) sets.remove(DefaultStickerSetId);
if (custom.stickers.isEmpty()) sets.remove(CustomStickerSetId);
@ -2343,21 +2348,25 @@ namespace Local {
clearKey(_recentStickersKeyOld);
_recentStickersKeyOld = 0;
_writeMap();
LOG(("Stickers: writing stickers and clearing old-stickers"));
}
void readStickers() {
LOG(("Stickers: readStickers()"));
if (!_stickersKey) {
return importOldRecentStickers();
}
FileReadDescriptor stickers;
if (!readEncryptedFile(stickers, _stickersKey)) {
LOG(("Stickers: could not readEncryptedFile(_stickersKey)!"));
clearKey(_stickersKey);
_stickersKey = 0;
_writeMap();
return;
}
LOG(("Stickers: clearing everything in read"));
StickerSets &sets(cRefStickerSets());
sets.clear();
@ -2432,6 +2441,8 @@ namespace Local {
}
cSetStickersHash(hash);
LOG(("Stickers: read %1 sets").arg(sets.size()));
}
void writeBackground(int32 id, const QImage &img) {

View File

@ -66,6 +66,7 @@ void debugLogWrite(const char *file, int32 line, const QString &v) {
{
QMutexLocker lock(&debugLogMutex);
if (!cDebug() || !debugLogStream) return;
logsInitDebug(); // maybe need to reopen new file
@ -87,6 +88,7 @@ void tcpLogWrite(const QString &v) {
{
QMutexLocker lock(&debugLogMutex);
if (!cDebug() || !tcpLogStream) return;
logsInitDebug(); // maybe need to reopen new file
@ -100,6 +102,7 @@ void mtpLogWrite(int32 dc, const QString &v) {
{
QMutexLocker lock(&debugLogMutex);
if (!cDebug() || !mtpLogStream) return;
logsInitDebug(); // maybe need to reopen new file
@ -109,7 +112,7 @@ void mtpLogWrite(int32 dc, const QString &v) {
}
void logWrite(const QString &v) {
if (!mainLog.isOpen()) return;
if (!mainLogStream) return;
time_t t = time(NULL);
struct tm tm;
@ -117,6 +120,8 @@ void logWrite(const QString &v) {
{
QMutexLocker lock(&mainLogMutex);
if (!mainLogStream) return;
QString msg(QString("[%1.%2.%3 %4:%5:%6] %7\n").arg(tm.tm_year + 1900).arg(tm.tm_mon + 1, 2, 10, zero).arg(tm.tm_mday, 2, 10, zero).arg(tm.tm_hour, 2, 10, zero).arg(tm.tm_min, 2, 10, zero).arg(tm.tm_sec, 2, 10, zero).arg(v));
(*mainLogStream) << msg;
mainLogStream->flush();

View File

@ -84,6 +84,9 @@ QString gTimeFormat = qsl("hh:mm");
int32 gAutoLock = 3600;
bool gHasPasscode = false;
bool gHasAudioPlayer = true;
bool gHasAudioCapture = true;
DBIEmojiTab gEmojiTab = dbietRecent;
RecentEmojiPack gRecentEmojis;
RecentEmojisPreload gRecentEmojisPreload;

View File

@ -134,6 +134,9 @@ DeclareSetting(QString, TimeFormat);
DeclareSetting(int32, AutoLock);
DeclareSetting(bool, HasPasscode);
DeclareSetting(bool, HasAudioPlayer);
DeclareSetting(bool, HasAudioCapture);
inline void cChangeTimeFormat(const QString &newFormat) {
if (!newFormat.isEmpty()) cSetTimeFormat(newFormat);
}

View File

@ -11,7 +11,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.17</string>
<string>0.8.18</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>

Binary file not shown.

View File

@ -107,8 +107,8 @@
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\libogg-1.3.2\win32\VS2010\Win32\Release;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\opusfile\win32\VS2010\Win32\Release;.\..\..\Libraries\mpg123-1.22.1\ports\MSVC++\2010\libmpg123\Release;.\..\..\Libraries\faad2-2.7\libfaad\Release;.\..\..\Libraries\faad2-2.7\common\mp4ff\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;opusfile.lib;opus.lib;libogg_static.lib;libmpg123.lib;libfaad.lib;mp4ff.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers />
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>
<ProfileGuidedDatabase>$(IntDir)$(TargetName).pgd</ProfileGuidedDatabase>
@ -134,8 +134,8 @@
<Link>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(ProjectName).exe</OutputFile>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>.\..\..\Libraries\lzma\C\Util\LzmaLib\Release;.\..\..\Libraries\libexif-0.6.20\win32\Release;.\..\..\Libraries\ffmpeg-2.6.3;.\..\..\Libraries\opus\win32\VS2010\Win32\Release;.\..\..\Libraries\openal-soft\build\Release;.\..\..\Libraries\zlib-1.2.8\contrib\vstudio\vc11\x86\ZlibStatRelease;.\..\..\Libraries\OpenSSL-Win32\lib\VC\static;$(QTDIR)\lib;$(QTDIR)\plugins;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;shell32.lib;uuid.lib;ole32.lib;advapi32.lib;ws2_32.lib;gdi32.lib;comdlg32.lib;oleaut32.lib;imm32.lib;winmm.lib;qtmain.lib;glu32.lib;opengl32.lib;Strmiids.lib;Qt5Core.lib;Qt5Gui.lib;qtharfbuzzng.lib;Qt5Widgets.lib;Qt5Network.lib;Qt5PlatformSupport.lib;platforms\qwindows.lib;imageformats\qwebp.lib;libeay32MT.lib;ssleay32MT.lib;Crypt32.lib;zlibstat.lib;lib_exif.lib;UxTheme.lib;DbgHelp.lib;LzmaLib.lib;OpenAL32.lib;common.lib;libavformat\libavformat.a;libavcodec\libavcodec.a;libavutil\libavutil.a;libswresample\libswresample.a;opus.lib;celt.lib;silk_common.lib;silk_float.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ImageHasSafeExceptionHandlers>
</ImageHasSafeExceptionHandlers>
<ImportLibrary>$(SolutionDir)$(Platform)\$(Configuration)Intermediate\$(TargetName).lib</ImportLibrary>

View File

@ -1693,7 +1693,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.17;
CURRENT_PROJECT_VERSION = 0.8.18;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
@ -1711,7 +1711,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 0.8.17;
CURRENT_PROJECT_VERSION = 0.8.18;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_OPTIMIZATION_LEVEL = fast;
GCC_PREFIX_HEADER = ./SourceFiles/stdafx.h;
@ -1737,10 +1737,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.17;
CURRENT_PROJECT_VERSION = 0.8.18;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.17;
DYLIB_CURRENT_VERSION = 0.8.18;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@ -1764,14 +1764,9 @@
./SourceFiles,
./GeneratedFiles,
/usr/local/include,
"./../../Libraries/libogg-1.3.2/include",
./../../Libraries/opus/include,
./../../Libraries/opusfile/include,
"./../../Libraries/openal-soft/include",
"./../../Libraries/mpg123-1.22.1/src/libmpg123",
"./../../Libraries/libexif-0.6.20",
"./../../Libraries/faad2-2.7/include",
"./../../Libraries/faad2-2.7/common/mp4ff",
"/usr/local/Qt-5.4.0/include",
"/usr/local/Qt-5.4.0/include/QtMultimedia",
"/usr/local/Qt-5.4.0/include/QtWidgets",
@ -1855,14 +1850,9 @@
"-lz",
"-lm",
/usr/local/lib/libopenal.a,
/usr/local/lib/libopusfile.a,
/usr/local/lib/libopus.a,
/usr/local/lib/libogg.a,
/usr/local/lib/liblzma.a,
/usr/local/lib/libexif.a,
/usr/local/lib/libmpg123.a,
/usr/local/lib/libfaad.a,
/usr/local/lib/libmp4ff.a,
/usr/local/lib/libavcodec.a,
/usr/local/lib/libavformat.a,
/usr/local/lib/libswresample.a,
@ -1890,10 +1880,10 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 0.8.17;
CURRENT_PROJECT_VERSION = 0.8.18;
DEBUG_INFORMATION_FORMAT = dwarf;
DYLIB_COMPATIBILITY_VERSION = 0.8;
DYLIB_CURRENT_VERSION = 0.8.17;
DYLIB_CURRENT_VERSION = 0.8.18;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "";
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
@ -1917,14 +1907,9 @@
./SourceFiles,
./GeneratedFiles,
/usr/local/include,
"./../../Libraries/libogg-1.3.2/include",
./../../Libraries/opus/include,
./../../Libraries/opusfile/include,
"./../../Libraries/openal-soft/include",
"./../../Libraries/mpg123-1.22.1/src/libmpg123",
"./../../Libraries/libexif-0.6.20",
"./../../Libraries/faad2-2.7/include",
"./../../Libraries/faad2-2.7/common/mp4ff",
"/usr/local/Qt-5.4.0/include",
"/usr/local/Qt-5.4.0/include/QtMultimedia",
"/usr/local/Qt-5.4.0/include/QtWidgets",
@ -2007,14 +1992,9 @@
"-lz",
"-lm",
/usr/local/lib/libopenal.a,
/usr/local/lib/libopusfile.a,
/usr/local/lib/libopus.a,
/usr/local/lib/libogg.a,
/usr/local/lib/liblzma.a,
/usr/local/lib/libexif.a,
/usr/local/lib/libmpg123.a,
/usr/local/lib/libfaad.a,
/usr/local/lib/libmp4ff.a,
/usr/local/lib/libavcodec.a,
/usr/local/lib/libavformat.a,
/usr/local/lib/libswresample.a,

View File

@ -1,2 +1,2 @@
echo 8017 0.8.17 0
echo 8018 0.8.18 1
# AppVersion AppVersionStr DevChannel

View File

@ -0,0 +1,716 @@
/**
* OpenAL cross platform audio library
* Copyright (C) 1999-2007 by authors.
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>
#include <windows.h>
#include <mmsystem.h>
#include "alMain.h"
#include "alu.h"
#include "threads.h"
#ifndef WAVE_FORMAT_IEEE_FLOAT
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
typedef struct {
// MMSYSTEM Device
volatile ALboolean killNow;
althrd_t thread;
RefCount WaveBuffersCommitted;
WAVEHDR WaveBuffer[4];
union {
HWAVEIN In;
HWAVEOUT Out;
} WaveHandle;
WAVEFORMATEX Format;
RingBuffer *Ring;
} WinMMData;
TYPEDEF_VECTOR(al_string, vector_al_string)
static vector_al_string PlaybackDevices;
static vector_al_string CaptureDevices;
static void clear_devlist(vector_al_string *list)
{
VECTOR_FOR_EACH(al_string, *list, al_string_deinit);
VECTOR_RESIZE(*list, 0);
}
static void ProbePlaybackDevices(void)
{
al_string *iter, *end;
ALuint numdevs;
ALuint i;
clear_devlist(&PlaybackDevices);
numdevs = waveOutGetNumDevs();
VECTOR_RESERVE(PlaybackDevices, numdevs);
for(i = 0;i < numdevs;i++)
{
WAVEOUTCAPSW WaveCaps;
al_string dname;
AL_STRING_INIT(dname);
if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
{
ALuint count = 0;
do {
al_string_copy_wcstr(&dname, WaveCaps.szPname);
if(count != 0)
{
char str[64];
snprintf(str, sizeof(str), " #%d", count+1);
al_string_append_cstr(&dname, str);
}
count++;
iter = VECTOR_ITER_BEGIN(PlaybackDevices);
end = VECTOR_ITER_END(PlaybackDevices);
for(;iter != end;iter++)
{
if(al_string_cmp(*iter, dname) == 0)
break;
}
} while(iter != end);
TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
}
VECTOR_PUSH_BACK(PlaybackDevices, dname);
}
}
static void ProbeCaptureDevices(void)
{
al_string *iter, *end;
ALuint numdevs;
ALuint i;
clear_devlist(&CaptureDevices);
numdevs = waveInGetNumDevs();
VECTOR_RESERVE(CaptureDevices, numdevs);
for(i = 0;i < numdevs;i++)
{
WAVEINCAPSW WaveCaps;
al_string dname;
AL_STRING_INIT(dname);
if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
{
ALuint count = 0;
do {
al_string_copy_wcstr(&dname, WaveCaps.szPname);
if(count != 0)
{
char str[64];
snprintf(str, sizeof(str), " #%d", count+1);
al_string_append_cstr(&dname, str);
}
count++;
iter = VECTOR_ITER_BEGIN(CaptureDevices);
end = VECTOR_ITER_END(CaptureDevices);
for(;iter != end;iter++)
{
if(al_string_cmp(*iter, dname) == 0)
break;
}
} while(iter != end);
TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
}
VECTOR_PUSH_BACK(CaptureDevices, dname);
}
}
/*
WaveOutProc
Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
returns to the application (for more data)
*/
static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
{
ALCdevice *Device = (ALCdevice*)instance;
WinMMData *data = Device->ExtraData;
if(msg != WOM_DONE)
return;
DecrementRef(&data->WaveBuffersCommitted);
PostThreadMessage(data->thread, msg, 0, param1);
}
FORCE_ALIGN static int PlaybackThreadProc(void *arg)
{
ALCdevice *Device = (ALCdevice*)arg;
WinMMData *data = Device->ExtraData;
WAVEHDR *WaveHdr;
MSG msg;
SetRTPriority();
althrd_setname(althrd_current(), MIXER_THREAD_NAME);
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message != WOM_DONE)
continue;
if(data->killNow)
{
if(ReadRef(&data->WaveBuffersCommitted) == 0)
break;
continue;
}
WaveHdr = ((WAVEHDR*)msg.lParam);
aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength /
data->Format.nBlockAlign);
// Send buffer back to play more data
waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR));
IncrementRef(&data->WaveBuffersCommitted);
}
return 0;
}
/*
WaveInProc
Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
returns to the application (with more data)
*/
static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
{
ALCdevice *Device = (ALCdevice*)instance;
WinMMData *data = Device->ExtraData;
if(msg != WIM_DATA)
return;
DecrementRef(&data->WaveBuffersCommitted);
PostThreadMessage(data->thread, msg, 0, param1);
}
static int CaptureThreadProc(void *arg)
{
ALCdevice *Device = (ALCdevice*)arg;
WinMMData *data = Device->ExtraData;
WAVEHDR *WaveHdr;
MSG msg;
althrd_setname(althrd_current(), "alsoft-record");
if (!data->killNow) while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message != WIM_DATA)
continue;
/* Don't wait for other buffers to finish before quitting. We're
* closing so we don't need them. */
if(data->killNow)
break;
WaveHdr = ((WAVEHDR*)msg.lParam);
WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData,
WaveHdr->dwBytesRecorded/data->Format.nBlockAlign);
// Send buffer back to capture more data
waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR));
IncrementRef(&data->WaveBuffersCommitted);
}
return 0;
}
static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName)
{
WinMMData *data = NULL;
const al_string *iter, *end;
UINT DeviceID;
MMRESULT res;
if(VECTOR_SIZE(PlaybackDevices) == 0)
ProbePlaybackDevices();
// Find the Device ID matching the deviceName if valid
iter = VECTOR_ITER_BEGIN(PlaybackDevices);
end = VECTOR_ITER_END(PlaybackDevices);
for(;iter != end;iter++)
{
if(!al_string_empty(*iter) &&
(!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
{
DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices));
break;
}
}
if(iter == end)
return ALC_INVALID_VALUE;
data = calloc(1, sizeof(*data));
if(!data)
return ALC_OUT_OF_MEMORY;
Device->ExtraData = data;
retry_open:
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
if(Device->FmtType == DevFmtFloat)
{
data->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
data->Format.wBitsPerSample = 32;
}
else
{
data->Format.wFormatTag = WAVE_FORMAT_PCM;
if(Device->FmtType == DevFmtUByte || Device->FmtType == DevFmtByte)
data->Format.wBitsPerSample = 8;
else
data->Format.wBitsPerSample = 16;
}
data->Format.nChannels = ((Device->FmtChans == DevFmtMono) ? 1 : 2);
data->Format.nBlockAlign = data->Format.wBitsPerSample *
data->Format.nChannels / 8;
data->Format.nSamplesPerSec = Device->Frequency;
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
data->Format.nBlockAlign;
data->Format.cbSize = 0;
if((res=waveOutOpen(&data->WaveHandle.Out, DeviceID, &data->Format, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
if(Device->FmtType == DevFmtFloat)
{
Device->FmtType = DevFmtShort;
goto retry_open;
}
ERR("waveOutOpen failed: %u\n", res);
goto failure;
}
al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID));
return ALC_NO_ERROR;
failure:
if(data->WaveHandle.Out)
waveOutClose(data->WaveHandle.Out);
free(data);
Device->ExtraData = NULL;
return ALC_INVALID_VALUE;
}
static void WinMMClosePlayback(ALCdevice *device)
{
WinMMData *data = (WinMMData*)device->ExtraData;
// Close the Wave device
waveOutClose(data->WaveHandle.Out);
data->WaveHandle.Out = 0;
free(data);
device->ExtraData = NULL;
}
static ALCboolean WinMMResetPlayback(ALCdevice *device)
{
WinMMData *data = (WinMMData*)device->ExtraData;
device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
data->Format.nSamplesPerSec /
device->Frequency);
device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
device->NumUpdates = 4;
device->Frequency = data->Format.nSamplesPerSec;
if(data->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
{
if(data->Format.wBitsPerSample == 32)
device->FmtType = DevFmtFloat;
else
{
ERR("Unhandled IEEE float sample depth: %d\n", data->Format.wBitsPerSample);
return ALC_FALSE;
}
}
else if(data->Format.wFormatTag == WAVE_FORMAT_PCM)
{
if(data->Format.wBitsPerSample == 16)
device->FmtType = DevFmtShort;
else if(data->Format.wBitsPerSample == 8)
device->FmtType = DevFmtUByte;
else
{
ERR("Unhandled PCM sample depth: %d\n", data->Format.wBitsPerSample);
return ALC_FALSE;
}
}
else
{
ERR("Unhandled format tag: 0x%04x\n", data->Format.wFormatTag);
return ALC_FALSE;
}
if(data->Format.nChannels == 2)
device->FmtChans = DevFmtStereo;
else if(data->Format.nChannels == 1)
device->FmtChans = DevFmtMono;
else
{
ERR("Unhandled channel count: %d\n", data->Format.nChannels);
return ALC_FALSE;
}
SetDefaultWFXChannelOrder(device);
return ALC_TRUE;
}
static ALCboolean WinMMStartPlayback(ALCdevice *device)
{
WinMMData *data = (WinMMData*)device->ExtraData;
ALbyte *BufferData;
ALint BufferSize;
ALuint i;
data->killNow = AL_FALSE;
if(althrd_create(&data->thread, PlaybackThreadProc, device) != althrd_success)
return ALC_FALSE;
InitRef(&data->WaveBuffersCommitted, 0);
// Create 4 Buffers
BufferSize = device->UpdateSize*device->NumUpdates / 4;
BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
BufferData = calloc(4, BufferSize);
for(i = 0;i < 4;i++)
{
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
data->WaveBuffer[i].dwBufferLength = BufferSize;
data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
(data->WaveBuffer[i-1].lpData +
data->WaveBuffer[i-1].dwBufferLength));
waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
IncrementRef(&data->WaveBuffersCommitted);
}
return ALC_TRUE;
}
static void WinMMStopPlayback(ALCdevice *device)
{
WinMMData *data = (WinMMData*)device->ExtraData;
void *buffer = NULL;
int i;
if(data->killNow)
return;
// Set flag to stop processing headers
data->killNow = AL_TRUE;
althrd_join(data->thread, &i);
// Release the wave buffers
for(i = 0;i < 4;i++)
{
waveOutUnprepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = data->WaveBuffer[i].lpData;
data->WaveBuffer[i].lpData = NULL;
}
free(buffer);
}
static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
{
const al_string *iter, *end;
ALbyte *BufferData = NULL;
DWORD CapturedDataSize;
WinMMData *data = NULL;
ALint BufferSize;
UINT DeviceID;
MMRESULT res;
ALuint i;
if(VECTOR_SIZE(CaptureDevices) == 0)
ProbeCaptureDevices();
// Find the Device ID matching the deviceName if valid
iter = VECTOR_ITER_BEGIN(CaptureDevices);
end = VECTOR_ITER_END(CaptureDevices);
for(;iter != end;iter++)
{
if(!al_string_empty(*iter) &&
(!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
{
DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices));
break;
}
}
if(iter == end)
return ALC_INVALID_VALUE;
switch(Device->FmtChans)
{
case DevFmtMono:
case DevFmtStereo:
break;
case DevFmtQuad:
case DevFmtX51:
case DevFmtX51Side:
case DevFmtX61:
case DevFmtX71:
return ALC_INVALID_ENUM;
}
switch(Device->FmtType)
{
case DevFmtUByte:
case DevFmtShort:
case DevFmtInt:
case DevFmtFloat:
break;
case DevFmtByte:
case DevFmtUShort:
case DevFmtUInt:
return ALC_INVALID_ENUM;
}
data = calloc(1, sizeof(*data));
if(!data)
return ALC_OUT_OF_MEMORY;
Device->ExtraData = data;
memset(&data->Format, 0, sizeof(WAVEFORMATEX));
data->Format.wFormatTag = ((Device->FmtType == DevFmtFloat) ?
WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
data->Format.nChannels = ChannelsFromDevFmt(Device->FmtChans);
data->Format.wBitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
data->Format.nBlockAlign = data->Format.wBitsPerSample *
data->Format.nChannels / 8;
data->Format.nSamplesPerSec = Device->Frequency;
data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
data->Format.nBlockAlign;
data->Format.cbSize = 0;
if((res=waveInOpen(&data->WaveHandle.In, DeviceID, &data->Format, (DWORD_PTR)&WaveInProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
{
ERR("waveInOpen failed: %u\n", res);
goto failure;
}
// Allocate circular memory buffer for the captured audio
CapturedDataSize = Device->UpdateSize*Device->NumUpdates;
// Make sure circular buffer is at least 100ms in size
if(CapturedDataSize < (data->Format.nSamplesPerSec / 10))
CapturedDataSize = data->Format.nSamplesPerSec / 10;
data->Ring = CreateRingBuffer(data->Format.nBlockAlign, CapturedDataSize);
if(!data->Ring)
goto failure;
InitRef(&data->WaveBuffersCommitted, 0);
// Create 4 Buffers of 50ms each
BufferSize = data->Format.nAvgBytesPerSec / 20;
BufferSize -= (BufferSize % data->Format.nBlockAlign);
BufferData = calloc(4, BufferSize);
if(!BufferData)
goto failure;
for(i = 0;i < 4;i++)
{
memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
data->WaveBuffer[i].dwBufferLength = BufferSize;
data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
(data->WaveBuffer[i-1].lpData +
data->WaveBuffer[i-1].dwBufferLength));
data->WaveBuffer[i].dwFlags = 0;
data->WaveBuffer[i].dwLoops = 0;
waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
IncrementRef(&data->WaveBuffersCommitted);
}
if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success)
goto failure;
al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID));
return ALC_NO_ERROR;
failure:
if(BufferData)
{
for(i = 0;i < 4;i++)
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
free(BufferData);
}
if(data->Ring)
DestroyRingBuffer(data->Ring);
if(data->WaveHandle.In)
waveInClose(data->WaveHandle.In);
free(data);
Device->ExtraData = NULL;
return ALC_INVALID_VALUE;
}
static void WinMMCloseCapture(ALCdevice *Device)
{
WinMMData *data = (WinMMData*)Device->ExtraData;
void *buffer = NULL;
int i;
/* Tell the processing thread to quit and wait for it to do so. */
data->killNow = AL_TRUE;
PostThreadMessage(data->thread, WM_QUIT, 0, 0);
althrd_join(data->thread, &i);
/* Make sure capture is stopped and all pending buffers are flushed. */
waveInReset(data->WaveHandle.In);
// Release the wave buffers
for(i = 0;i < 4;i++)
{
waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
if(i == 0) buffer = data->WaveBuffer[i].lpData;
data->WaveBuffer[i].lpData = NULL;
}
free(buffer);
DestroyRingBuffer(data->Ring);
data->Ring = NULL;
// Close the Wave device
waveInClose(data->WaveHandle.In);
data->WaveHandle.In = 0;
free(data);
Device->ExtraData = NULL;
}
static void WinMMStartCapture(ALCdevice *Device)
{
WinMMData *data = (WinMMData*)Device->ExtraData;
waveInStart(data->WaveHandle.In);
}
static void WinMMStopCapture(ALCdevice *Device)
{
WinMMData *data = (WinMMData*)Device->ExtraData;
waveInStop(data->WaveHandle.In);
}
static ALCenum WinMMCaptureSamples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
{
WinMMData *data = (WinMMData*)Device->ExtraData;
ReadRingBuffer(data->Ring, Buffer, Samples);
return ALC_NO_ERROR;
}
static ALCuint WinMMAvailableSamples(ALCdevice *Device)
{
WinMMData *data = (WinMMData*)Device->ExtraData;
return RingBufferSize(data->Ring);
}
static inline void AppendAllDevicesList2(const al_string *name)
{
if(!al_string_empty(*name))
AppendAllDevicesList(al_string_get_cstr(*name));
}
static inline void AppendCaptureDeviceList2(const al_string *name)
{
if(!al_string_empty(*name))
AppendCaptureDeviceList(al_string_get_cstr(*name));
}
static const BackendFuncs WinMMFuncs = {
WinMMOpenPlayback,
WinMMClosePlayback,
WinMMResetPlayback,
WinMMStartPlayback,
WinMMStopPlayback,
WinMMOpenCapture,
WinMMCloseCapture,
WinMMStartCapture,
WinMMStopCapture,
WinMMCaptureSamples,
WinMMAvailableSamples,
ALCdevice_GetLatencyDefault
};
ALCboolean alcWinMMInit(BackendFuncs *FuncList)
{
VECTOR_INIT(PlaybackDevices);
VECTOR_INIT(CaptureDevices);
*FuncList = WinMMFuncs;
return ALC_TRUE;
}
void alcWinMMDeinit()
{
clear_devlist(&PlaybackDevices);
VECTOR_DEINIT(PlaybackDevices);
clear_devlist(&CaptureDevices);
VECTOR_DEINIT(CaptureDevices);
}
void alcWinMMProbe(enum DevProbe type)
{
switch(type)
{
case ALL_DEVICE_PROBE:
ProbePlaybackDevices();
VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2);
break;
case CAPTURE_DEVICE_PROBE:
ProbeCaptureDevices();
VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2);
break;
}
}