diff --git a/clients/qt4/qt4client.cpp b/clients/qt4/qt4client.cpp index d0b4cbb9..b52b160b 100644 --- a/clients/qt4/qt4client.cpp +++ b/clients/qt4/qt4client.cpp @@ -22,8 +22,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include -#include +#include "qt4client.h" #include #ifdef _WINDOWS @@ -46,7 +45,7 @@ QtWindow::QtWindow() } QtWindow::QtWindow(const char* name, const char* description) - : Window(name), m_description(description), m_keysVisible(true) + : Window(name), m_description(description), m_keysVisible(true) { m_ringtone = new QSound("ring.wav", this); } @@ -1286,14 +1285,14 @@ void QtWindow::menu(int x, int y) QtClient::QtClient() - : Client("QtClient") + : Client("QtClient") { m_oneThread = Engine::config().getBoolValue("client","onethread",true); s_skinPath = Engine::config().getValue("client","skinbase"); if (s_skinPath.null()) - s_skinPath << Engine::modulePath() << Engine::pathSeparator() << "skin"; - s_skinPath << Engine::pathSeparator(); + s_skinPath << Engine::sharedPath() << Engine::pathSeparator() << "skins"; + s_skinPath << Engine::pathSeparator(); String skin(Engine::config().getValue("client","skin","default")); if (skin) diff --git a/clients/qt4/qt4client.h b/clients/qt4/qt4client.h index 3796a886..93c08ba3 100644 --- a/clients/qt4/qt4client.h +++ b/clients/qt4/qt4client.h @@ -25,7 +25,7 @@ #include #ifdef _WINDOWS - + #ifdef LIBYQT4_EXPORTS #define YQT4_API __declspec(dllexport) #else @@ -33,9 +33,9 @@ #define YQT4_API __declspec(dllimport) #endif #endif - + #endif /* _WINDOWS */ - + #ifndef YQT4_API #define YQT4_API #endif @@ -49,6 +49,12 @@ #include #include +#define QT_NO_DEBUG +#define QT_DLL +#define QT_GUI_LIB +#define QT_CORE_LIB +#define QT_THREAD_SUPPORT + #include #include diff --git a/engine/Client.cpp b/engine/Client.cpp index d51d31d7..076d6f98 100644 --- a/engine/Client.cpp +++ b/engine/Client.cpp @@ -434,10 +434,18 @@ Client::Client(const char *name) } Client::~Client() +{ + Engine::halt(0); +} + +void Client::cleanup() { m_windows.clear(); s_client = 0; - Engine::halt(0); + m_oneThread = false; + do + idleActions(); + while (ClientDriver::self() && !ClientDriver::self()->check(100000)); } void Client::run() diff --git a/modules/client/dsoundchan.cpp b/modules/client/dsoundchan.cpp index 96c373c6..25a59d7d 100644 --- a/modules/client/dsoundchan.cpp +++ b/modules/client/dsoundchan.cpp @@ -260,21 +260,22 @@ void DSoundPlay::run() if (m_owner) m_owner->m_dsound = this; DWORD writeOffs = 0; + DWORD margin = s_chunk/4; bool first = true; Debug(&__plugin,DebugInfo,"DSoundPlay is initialized and running"); while (m_owner) { msleep(1,true); if (first) { - if (m_buf.length() < s_minsize) + if ((m_buf.length() < s_minsize) || !m_dsb) continue; first = false; m_dsb->GetCurrentPosition(NULL,&writeOffs); - writeOffs = (s_chunk/4 + writeOffs) % m_buffSize; + writeOffs = (margin + writeOffs) % m_buffSize; Debug(&__plugin,DebugAll,"DSoundPlay has %u in buffer and starts playing at %u", m_buf.length(),writeOffs); m_start = Time::now(); } - while (m_dsb && (m_buf.length() >= s_chunk)) { + while (m_dsb) { DWORD playPos = 0; DWORD writePos = 0; bool adjust = false; @@ -288,11 +289,17 @@ void DSoundPlay::run() adjust = (writeOffs < writePos) || (playPos <= writeOffs) ; } if (adjust) { - DWORD adjOffs = (s_chunk/4 + writePos) % m_buffSize; - Debug(&__plugin,DebugInfo,"Slip detected, changing write offs from %u to %u, p=%u w=%u", + DWORD adjOffs = (margin + writePos) % m_buffSize; + Debug(&__plugin,DebugNote,"Slip detected, changing write offs from %u to %u, p=%u w=%u", writeOffs,adjOffs,playPos,writePos); writeOffs = adjOffs; } + bool hasData = (m_buf.length() >= s_chunk); + if (!(adjust || hasData)) { + // don't fill the buffer if we still have at least one chunk until underflow + if ((m_buffSize + writeOffs - writePos) % m_buffSize >= s_chunk) + break; + } void* buf = 0; void* buf2 = 0; DWORD len = 0; @@ -316,16 +323,28 @@ void DSoundPlay::run() continue; } lock(); - ::memcpy(buf,m_buf.data(),len); - if (buf2) - ::memcpy(buf2,((const char*)m_buf.data())+len,len2); + if (hasData) { + ::memcpy(buf,m_buf.data(),len); + if (buf2) + ::memcpy(buf2,((const char*)m_buf.data())+len,len2); + } + else { + ::memset(buf,0,len); + if (buf2) + ::memset(buf2,0,len2); + } m_dsb->Unlock(buf,len,buf2,len2); - writeOffs += s_chunk; - if (writeOffs >= m_buffSize) - writeOffs -= m_buffSize; m_total += s_chunk; m_buf.cut(-(int)s_chunk); unlock(); +#ifdef DEBUG + if (!hasData) + Debug(&__plugin,DebugInfo,"Underflow, filled %u bytes at %u, p=%u w=%u", + s_chunk,writeOffs,playPos,writePos); +#endif + writeOffs += s_chunk; + if (writeOffs >= m_buffSize) + writeOffs -= m_buffSize; XDebug(&__plugin,DebugAll,"Locked %p,%d %p,%d",buf,len,buf2,len2); } } diff --git a/windows/LibQt4.vcproj b/windows/LibQt4.vcproj index d868dcf5..b1a1ed5d 100644 --- a/windows/LibQt4.vcproj +++ b/windows/LibQt4.vcproj @@ -29,6 +29,7 @@ /> + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/Qt4Client.vcproj b/windows/Qt4Client.vcproj index 9118fabd..9cba7a6b 100644 --- a/windows/Qt4Client.vcproj +++ b/windows/Qt4Client.vcproj @@ -50,7 +50,7 @@ Optimization="2" InlineFunctionExpansion="1" AdditionalIncludeDirectories=".,..,../clients/qt4" - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS" + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;UNICODE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -74,7 +74,6 @@ /> + +#include +#include +#include + +__declspec(dllexport) int __cdecl crt_true(void) +{ + Sleep(50); + return (clock() != 0); +} diff --git a/windows/msvcrtest.vcproj b/windows/msvcrtest.vcproj new file mode 100644 index 00000000..a950170e --- /dev/null +++ b/windows/msvcrtest.vcproj @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/windows/yate.iss b/windows/yate.iss index e9463478..ad64f55e 100644 --- a/windows/yate.iss +++ b/windows/yate.iss @@ -25,10 +25,11 @@ Name: "engine"; Description: "Engine only (unlikely)" [Components] Name: "engine"; Description: "Engine library"; Types: full client server engine custom; Flags: fixed -Name: "client"; Description: "Client files"; Types: full client -Name: "client\run"; Description: "Client runtime libraries"; Types: full client -Name: "client\skin"; Description: "Client skins"; Types: full client -Name: "client\skin\skinned"; Description: "Graphical skin"; Types: full +Name: "client"; Description: "VoIP Clients"; Types: full client +Name: "client\qt"; Description: "Client based on Qt"; Types: full client +Name: "client\qt\run"; Description: "Qt runtime libraries"; Types: full client +Name: "client\gtk"; Description: "Client based on Gtk"; Types: full +Name: "client\gtk\skinned"; Description: "Graphical skin"; Types: full Name: "server"; Description: "Server files"; Types: full server Name: "server\cluster"; Description: "Server clustering modules"; Types: full Name: "driver"; Description: "Protocol drivers"; Types: full client server @@ -59,12 +60,14 @@ Name: "desktop"; Description: "Create a &Desktop icon"; GroupDescription: "Addit [Files] Source: "Release\libyate.dll"; DestDir: "{app}"; Components: engine -Source: "Release\libygtk2.dll"; DestDir: "{app}"; Components: client -Source: "Release\yate-gtk2.exe"; DestDir: "{app}"; Components: client +Source: "Release\libyqt4.dll"; DestDir: "{app}"; Components: client\qt +Source: "Release\yate-qt4.exe"; DestDir: "{app}"; Components: client\qt +Source: "Release\libygtk2.dll"; DestDir: "{app}"; Components: client\gtk +Source: "Release\yate-gtk2.exe"; DestDir: "{app}"; Components: client\gtk ;Source: "..\share\sounds\ring.wav"; DestDir: "{app}\sounds"; Components: client -;Source: "Runtimes\qtcore4.dll"; DestDir: "{app}"; Components: client\run -;Source: "Runtimes\qtgui4.dll"; DestDir: "{app}"; Components: client\run -;Source: "Runtimes\qtxml4.dll"; DestDir: "{app}"; Components: client\run +Source: "Runtimes\qtcore4.dll"; DestDir: "{app}"; Components: client\qt\run +Source: "Runtimes\qtgui4.dll"; DestDir: "{app}"; Components: client\qt\run +Source: "Runtimes\qtxml4.dll"; DestDir: "{app}"; Components: client\qt\run Source: "Release\yate-service.exe"; DestDir: "{app}"; Components: server Source: "Release\yate-console.exe"; DestDir: "{app}"; Components: debug @@ -129,12 +132,14 @@ Source: "..\conf.d\*.conf.sample"; DestDir: "{app}\conf.d" Source: "..\share\help\*.yhlp"; DestDir: "{app}\help"; Components: client Source: "..\conf.d\providers.conf.default"; DestName: "providers.conf"; DestDir: "{app}\conf.d"; Components: client -Source: "..\share\skins\default\gtk2client.??"; DestDir: "{app}\skins\default"; Components: client +Source: "..\share\skins\default\qt4client.??"; DestDir: "{app}\skins\default"; Components: client\qt +Source: "..\share\skins\default\gtk2client.??"; DestDir: "{app}\skins\default"; Components: client\gtk Source: "..\share\skins\default\*.png"; DestDir: "{app}\skins\default"; Components: client -Source: "..\share\skins\skinned\gtk2client.??"; DestDir: "{app}\skins\skinned"; Components: client\skin\skinned -Source: "..\share\skins\skinned\*.png"; DestDir: "{app}\skins\skinned"; Components: client\skin\skinned -Source: "..\conf.d\yate-gtk2.conf.default"; DestName: "yate-gtk2.conf"; DestDir: "{app}\conf.d"; Components: client\skin\skinned; Flags: skipifsourcedoesntexist +Source: "..\share\skins\skinned\gtk2client.??"; DestDir: "{app}\skins\skinned"; Components: client\gtk\skinned +Source: "..\share\skins\skinned\*.png"; DestDir: "{app}\skins\skinned"; Components: client\gtk\skinned +Source: "..\conf.d\yate-qt4.conf.default"; DestName: "yate-qt4.conf"; DestDir: "{app}\conf.d"; Components: client\qt; Flags: skipifsourcedoesntexist +Source: "..\conf.d\yate-gtk2.conf.default"; DestName: "yate-gtk2.conf"; DestDir: "{app}\conf.d"; Components: client\gtk\skinned; Flags: skipifsourcedoesntexist Source: "..\share\scripts\*.php"; DestDir: "{app}\scripts"; Components: external\php @@ -145,7 +150,7 @@ Source: "version.rc"; DestDir: "{app}\devel"; Components: devel Source: "..\clients\gtk2\gtk2client.h"; DestDir: "{app}\devel"; Components: devel Source: "Release\libygtk2.lib"; DestDir: "{app}\devel"; Components: devel Source: "..\clients\qt4\qt4client.h"; DestDir: "{app}\devel"; Components: devel -;Source: "Release\libyqt4.lib"; DestDir: "{app}\devel"; Components: devel +Source: "Release\libyqt4.lib"; DestDir: "{app}\devel"; Components: devel Source: "..\README"; DestName: "README.txt"; DestDir: "{app}\devel"; Components: devel Source: "..\ChangeLog"; DestName: "ChangeLog.txt"; DestDir: "{app}\devel"; Components: devel Source: "..\docs\*.html"; DestDir: "{app}\devel\docs"; Components: devel\doc @@ -153,27 +158,29 @@ Source: "..\docs\api\*.html"; DestDir: "{app}\devel\docs\api"; Components: devel Source: "..\docs\api\*.png"; DestDir: "{app}\devel\docs\api"; Components: devel\doc; Flags: skipifsourcedoesntexist Source: "..\docs\api\*.css"; DestDir: "{app}\devel\docs\api"; Components: devel\doc; Flags: skipifsourcedoesntexist +Source: "Release\msvcrtest.dll"; Flags: dontcopy +Source: "Runtimes\vcredist_x86.exe"; DestDir: "{app}"; Flags: skipifsourcedoesntexist dontcopy nocompression Source: "Runtimes\gtk+-2.6.9-setup.exe"; DestDir: "{app}"; Components: client; Flags: skipifsourcedoesntexist dontcopy nocompression [Icons] -Name: "{group}\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client -;Name: "{group}\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client +Name: "{group}\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client\gtk +Name: "{group}\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client\qt Name: "{group}\Yate Console"; Filename: "{app}\yate-console.exe"; Parameters: "-n yate-console -w ""{app}"""; Components: debug Name: "{group}\Register Service"; Filename: "{app}\yate-service.exe"; Parameters: "--install -w ""{app}"""; Components: server Name: "{group}\Unregister Service"; Filename: "{app}\yate-service.exe"; Parameters: "--remove"; Components: server Name: "{group}\Uninstall"; Filename: "{uninstallexe}" Name: "{group}\Yate Web Site"; Filename: "{app}\yate.url" Name: "{group}\Developer docs"; Filename: "{app}\devel\docs\index.html"; Components: devel\doc -Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client; Tasks: qlaunch -Name: "{userdesktop}\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client; Tasks: desktop -;Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client; Tasks: qlaunch -;Name: "{userdesktop}\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client; Tasks: desktop +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client\gtk; Tasks: qlaunch +Name: "{userdesktop}\Yate Client"; Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Components: client\gtk; Tasks: desktop +Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client\qt; Tasks: qlaunch +Name: "{userdesktop}\Yate Client"; Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Components: client\qt; Tasks: desktop [Run] Filename: "{app}\yate-service.exe"; Description: "Register service"; Parameters: "--install -w ""{app}"""; Components: server Filename: "net.exe"; Description: "Start service"; Components: server; Parameters: "start yate"; Flags: postinstall skipifsilent unchecked -Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Description: "Launch client"; Components: client; Flags: postinstall nowait skipifsilent unchecked -;Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Description: "Launch client"; Components: client; Flags: postinstall nowait skipifsilent unchecked +Filename: "{app}\yate-gtk2.exe"; Parameters: "-n yate-gtk2 -w ""{app}"""; Description: "Launch client"; Components: client\gtk; Flags: postinstall nowait skipifsilent unchecked +Filename: "{app}\yate-qt4.exe"; Parameters: "-n yate-qt4 -w ""{app}"""; Description: "Launch client"; Components: client\qt; Flags: postinstall nowait skipifsilent unchecked [UninstallRun] Filename: "net.exe"; Parameters: "stop yate"; Components: server @@ -185,8 +192,8 @@ var GtkRegistry : Boolean; GtkLoadable : Boolean; -function CrtClock() : Longint; -external 'clock@MSVCR80.DLL stdcall delayload setuponly'; +function CrtTrue() : Integer; +external 'crt_true@files:msvcrtest.dll cdecl delayload setuponly'; function GtkTrue() : Integer; external 'gtk_true@LIBGTK-WIN32-2.0-0.DLL stdcall delayload setuponly'; @@ -194,8 +201,8 @@ external 'gtk_true@LIBGTK-WIN32-2.0-0.DLL stdcall delayload setuponly'; function InitializeSetup() : Boolean; begin try - CrtLoadable := CrtClock() <> 0; - UnloadDLL('MSVCR80.DLL'); + CrtLoadable := CrtTrue() <> 0; + UnloadDLL('MSVCRTEST.DLL'); except CrtLoadable := False; end; @@ -224,20 +231,21 @@ begin if (err = IDCANCEL) and ExitSetupMsgBox() then Abort; until err <> IDCANCEL; if err = IDYES then begin - url := 'msvcr80-setup.exe'; + url := 'vcredist_x86.exe'; try ExtractTemporaryFile(url); url := ExpandConstant('{tmp}\') + url; - if FileExists(url) and ShellExec('open', url, '', '', SW_SHOW, ewWaitUntilTerminated, err) then - exit; + CrtLoadable := FileExists(url) and ShellExec('open', url, '', '', SW_SHOW, ewWaitUntilTerminated, err); except end; - url := 'http://yate.null.ro/msvcr80.php'; - if not ShellExec('open', url, '', '', SW_SHOW, ewNoWait, err) then - MsgBox('Browser failed. Please go to:' #13 + url,mbError,MB_OK); + if not CrtLoadable then begin + url := 'http://yate.null.ro/msvcr80.php'; + if not ShellExec('open', url, '', '', SW_SHOW, ewNoWait, err) then + MsgBox('Browser failed. Please go to:' #13 + url,mbError,MB_OK); + end; end; end; - if IsComponentSelected('client') and not (GtkRegistry and GtkLoadable) then begin + if IsComponentSelected('client\gtk') and not (GtkRegistry and GtkLoadable) then begin msg := 'Gtk2 client installation requested' #13 'but Gtk2 is not '; if GtkRegistry then msg := msg + 'loadable' else if GtkLoadable then msg := msg + 'in Registry' diff --git a/yatecbase.h b/yatecbase.h index aa0187ab..c0cbb65b 100644 --- a/yatecbase.h +++ b/yatecbase.h @@ -280,6 +280,7 @@ public: Client(const char *name = 0); virtual ~Client(); virtual void run(); + virtual void cleanup(); virtual void main() = 0; virtual void lock() = 0; virtual void unlock() = 0;