Dear all,
I currently try to convert and compile ASIO source code from Otachan with ASIOSDK2.3 and latest Foobar SDK.
I almost manage to make it works.
However, I don't undertstand how to register the output service with the current SDK.
I currently have the code below and I have the following errors in VS console.
Would a nice soul do help me ?
Regards.
1>------ Build started: Project: foo_output_asio, Configuration: Debug Win32 ------
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.CppBuild.targets(936,5): warning MSB8027: Two or more files with the name of stdafx.cpp will produce outputs to the same location. This can lead to an incorrect build result. The files involved are ..\..\pfc\stdafx.cpp, ..\..\SDK\stdafx.cpp.
1> foo_output_asio.cpp
1>c:\sdk\fb2k\foo_output_asio(dll)_051\shared\fb2kdebug.h(80): warning C4838: conversion from 'int' to 'const ULONG_PTR' requires a narrowing conversion
1>c:\sdk\fb2k\sdk\output.h(175): error C2039: 'g_advanced_settings_query': is not a member of 'output_asio'
1> c:\sdk\fb2k\foo_output_asio(dll)_051\source\foo_output_asio.h(56): note: see declaration of 'output_asio'
1> c:\sdk\fb2k\sdk\output.h(173): note: while compiling class template member function 't_uint32 output_entry_impl_t<T,output_entry>::get_config_flags(void)'
1> with
1> [
1> T=output_asio
1> ]
1> c:\sdk\fb2k\sdk\service.h(620): note: see reference to class template instantiation 'output_entry_impl_t<T,output_entry>' being compiled
1> with
1> [
1> T=output_asio
1> ]
1> c:\sdk\fb2k\sdk\output.h(186): note: see reference to class template instantiation 'service_factory_single_t<output_entry_impl_t<T,output_entry>>' being compiled
1> with
1> [
1> T=output_asio
1> ]
1> c:\sdk\fb2k\foo_output_asio(dll)_051\source\foo_output_asio.cpp(25): note: see reference to class template instantiation 'output_factory_t<output_asio>' being compiled
1>c:\sdk\fb2k\sdk\output.h(175): error C3861: 'g_advanced_settings_query': identifier not found
1>c:\sdk\fb2k\sdk\output.h(176): error C2039: 'g_needs_bitdepth_config': is not a member of 'output_asio'
1> c:\sdk\fb2k\foo_output_asio(dll)_051\source\foo_output_asio.h(56): note: see declaration of 'output_asio'
1>c:\sdk\fb2k\sdk\output.h(176): error C3861: 'g_needs_bitdepth_config': identifier not found
1>c:\sdk\fb2k\sdk\output.h(177): error C2039: 'g_needs_dither_config': is not a member of 'output_asio'
1> c:\sdk\fb2k\foo_output_asio(dll)_051\source\foo_output_asio.h(56): note: see declaration of 'output_asio'
1>c:\sdk\fb2k\sdk\output.h(177): error C3861: 'g_needs_dither_config': identifier not found
1>c:\sdk\fb2k\sdk\output.h(178): error C2039: 'g_needs_device_list_prefixes': is not a member of 'output_asio'
1> c:\sdk\fb2k\foo_output_asio(dll)_051\source\foo_output_asio.h(56): note: see declaration of 'output_asio'
1>c:\sdk\fb2k\sdk\output.h(178): error C3861: 'g_needs_device_list_prefixes': identifier not found
/*
** foo_output_asio - ASIO output for foobar2000
**
** 2006/2/25 Written by Otachan
** http://otachan.com/
*/
#define STRICT
#include <windows.h>
#include <process.h>
#include "foo_output_asio.h"
#include "pcmasio.h"
extern HINSTANCE WSLhInstance;
extern AsioDrivers* asioDrivers;
//service_factory_single_t<initquit, initquit_output_asio> foo;
//service_factory_t<output, output_asio> foo2;
initquit_factory_t<initquit_output_asio> foo;
output_factory_t<output_asio> foo2;
//service_factory_single_t<initquit_output_asio> foo;
//service_factory_t<output_asio> foo2;
DECLARE_COMPONENT_VERSION(
NAME,
VER,
NAME " v" VER "\n\n"
"Copyright (C) 2003-2006 Otachan\n"
"http://otachan.com/\n\n"
"ASIO Technology by Steinberg.");
// {38B5B07D-532B-472B-B406-A484630A5021}
static const GUID guid_cfg_device =
{ 0x38b5b07d, 0x532b, 0x472b,{ 0xb4, 0x6, 0xa4, 0x84, 0x63, 0xa, 0x50, 0x21 } };
// {1D2540D2-5941-4787-AA60-E756ABCF32E5}
static const GUID guid_cfg_thread_priority =
{ 0x1d2540d2, 0x5941, 0x4787,{ 0xaa, 0x60, 0xe7, 0x56, 0xab, 0xcf, 0x32, 0xe5 } };
// {FD8C6045-CF61-4188-A0EA-12BB9D69062F}
static const GUID guid_cfg_buffer_size =
{ 0xfd8c6045, 0xcf61, 0x4188,{ 0xa0, 0xea, 0x12, 0xbb, 0x9d, 0x69, 0x6, 0x2f } };
// {8F295CD2-55AD-4771-95CA-3242871D5A4C}
static const GUID guid_cfg_shift_channels =
{ 0x8f295cd2, 0x55ad, 0x4771,{ 0x95, 0xca, 0x32, 0x42, 0x87, 0x1d, 0x5a, 0x4c } };
// {9E3A57CF-5D71-4667-AAFF-2F6E95212612}
static const GUID guid_direct_input_monitor =
{ 0x9e3a57cf, 0x5d71, 0x4667,{ 0xaa, 0xff, 0x2f, 0x6e, 0x95, 0x21, 0x26, 0x12 } };
cfg_int cfg_device(guid_cfg_device, 0);
cfg_int cfg_thread_priority(guid_cfg_thread_priority, 3);
cfg_int cfg_buffer_size(guid_cfg_buffer_size, 7);
cfg_int cfg_shift_channels(guid_cfg_shift_channels, 0);
cfg_int cfg_direct_input_monitor(guid_direct_input_monitor, 0);
CRITICAL_SECTION CriticalSectionInit;
PcmAsio* pPcmAsio;
HANDLE hThread;
HANDLE EventReadyThread;
HANDLE EventDestroyThread;
bool InitDLL;
BOOL WINAPI
DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
::InitializeCriticalSection(&CriticalSectionInit);
WSLhInstance = hinstDLL;
InitDLL = false;
break;
case DLL_PROCESS_DETACH:
::DeleteCriticalSection(&CriticalSectionInit);
break;
}
return true;
}
unsigned int __stdcall
ThreadProc(void* /*Param*/)
{
asioDrivers = new AsioDrivers;
pPcmAsio = new PcmAsio;
::SetEvent(EventReadyThread);
while(::WaitForSingleObjectEx(EventDestroyThread, INFINITE, true) != WAIT_OBJECT_0);
delete pPcmAsio;
delete asioDrivers;
_endthreadex(0);
return 0;
}
void CALLBACK
ApcProc(ULONG_PTR dwParam)
{
ParamMsg* const Param = reinterpret_cast<ParamMsg*>(dwParam);
switch(Param->Msg) {
case MSG_CLOSE_DRIVER:
pPcmAsio->CloseDriver();
break;
case MSG_OPEN:
Param->RetMsg = pPcmAsio->MsgOpen(Param->Param1, Param->Param2, Param->Param3, Param->Param4);
break;
case MSG_CAN_WRITE:
Param->RetMsg = pPcmAsio->MsgCanWrite();
break;
case MSG_WRITE:
Param->RetMsg = pPcmAsio->MsgWrite(Param->Param1, Param->Buff);
break;
case MSG_PAUSE:
pPcmAsio->MsgPause(Param->Param1);
break;
case MSG_PLAY:
pPcmAsio->MsgPlay();
break;
case MSG_FLUSH:
Param->RetMsg = pPcmAsio->MsgFlush();
break;
}
Param->UnPause();
}
ParamMsg::ParamMsg(int _Msg)
{
Msg = _Msg;
}
ParamMsg::ParamMsg(int _Msg, int _Param1)
{
Msg = _Msg;
Param1 = _Param1;
}
ParamMsg::ParamMsg(int _Msg, int _Param1, int _Param2, int _Param3, int _Param4)
{
Msg = _Msg;
Param1 = _Param1;
Param2 = _Param2;
Param3 = _Param3;
Param4 = _Param4;
}
ParamMsg::ParamMsg(int _Msg, int _Param1, unsigned char* _Buff)
{
Msg = _Msg;
Param1 = _Param1;
Buff = _Buff;
}
int
ParamMsg::Call(void)
{
EventWaitThread = ::CreateEvent(NULL, false, false, NULL);
::QueueUserAPC(&ApcProc, hThread, reinterpret_cast<ULONG_PTR>(this));
::WaitForSingleObject(EventWaitThread, INFINITE);
::CloseHandle(EventWaitThread);
return RetMsg;
}
void
ParamMsg::UnPause(void)
{
::SetEvent(EventWaitThread);
}
void
Init(void)
{
::EnterCriticalSection(&CriticalSectionInit);
if(InitDLL == false) {
EventDestroyThread = ::CreateEvent(NULL, false, false, NULL);
EventReadyThread = ::CreateEvent(NULL, false, false, NULL);
unsigned int dwThread;
hThread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, ThreadProc, NULL, 0, &dwThread));
::WaitForSingleObject(EventReadyThread, INFINITE);
::CloseHandle(EventReadyThread);
InitDLL = true;
}
::LeaveCriticalSection(&CriticalSectionInit);
}
inline void
Quit(void)
{
::SetEvent(EventDestroyThread);
if(::WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) {
if(::TerminateThread(hThread, 0)) {
::WaitForSingleObject(hThread, 3000);
}
}
::CloseHandle(hThread);
::CloseHandle(EventDestroyThread);
}
void
initquit_output_asio::on_init(void)
{
Init();
}
void
initquit_output_asio::on_quit(void)
{
Quit();
}
// ********************************** /
// output_asio
//
output_asio::output_asio(void)
{
Init();
OpenDriver = false;
}
output_asio::~output_asio(void)
{
if(OpenDriver) ParamMsg(MSG_CLOSE_DRIVER).Call();
}
int
output_asio::open_ex(int srate, int bps, int nch, int format_code)
{
const int RetCode = ParamMsg(MSG_OPEN, srate, format_code, bps, nch).Call();
OpenDriver = RetCode != 0;
return RetCode;
}
int
output_asio::can_write(void)
{
return ParamMsg(MSG_CAN_WRITE).Call();
}
int
output_asio::write(const char* data, int bytes)
{
return ParamMsg(MSG_WRITE, bytes,
reinterpret_cast<unsigned char*>(const_cast<char*>(data))).Call();
}
int
output_asio::get_latency_bytes(void)
{
return pPcmAsio->MsgGetLatency();
}
void
output_asio::pause(int state)
{
ParamMsg(MSG_PAUSE, state).Call();
}
void
output_asio::force_play(void)
{
ParamMsg(MSG_PLAY).Call();
}
int
output_asio::do_flush(void)
{
return ParamMsg(MSG_FLUSH).Call();
}
int
output_asio::is_playing(void)
{
return !!pPcmAsio->MsgGetLatency();
}