Hi!
SAPI - How can I detect the users default Language ID (langid)?
Best regards,
Nordwind
Win32API offers:
GetSystemDefaultLangID
GetUserDefaultLangID
Good all the way back to W95.
Regards, P1 :8)
Hi P1,
sorry, I'm speaking about SAPI stuff. Text2Speech and such things...
A User is A User is A User.
So how is a user's langid for the written part of the OS, going to be different than the spoken part of the text of the OS?
How is this any different than the screen readers for the blind work?
Just watch out for Hex vs. Decimal.
Regards, P1 :8)
Hi.
QuoteSo how is a user's langid for the written part of the OS, going to be different than the spoken part of the text of the OS?
How is this any different than the screen readers for the blind work?
Yes, sorry it is. I'm a german user, but MS Sam is the default speech in my system. The ID is 409h. To use a german speech, I had to install the german speech files. I must now detect, if the user had installed the german files or not. Thats not possible with GetSystemDefaultLangID/GetUserDefaultLangID, what only gives me 407h. Even, if MS Sam is the default users speech.
Sorry for my bad english...
Best regards,
Nordwind
From:
Quote from: Nordwind64 on June 21, 2006, 07:07:32 PMSAPI - How can I detect the users default Language ID (langid)?
To:
Quote from: Nordwind64 on June 22, 2006, 04:40:09 AMTo use a german speech, I had to install the german speech files. I must now detect, if the user had installed the german files or not.
So what you really want is to check for installed files for the LangID of the OS? And you want to know, if there is a SAPI function to enumerate the language options installed?
From a Quick Google search, what you want to do is Enumerate the Voices available to SAPI. Each Voice will have it's plain text descriptor and it's hex LangID, plus it's options, like male or female, etc..
M$ makes doing this in English as default, so it's fairly easy. But I understand where your fustration comes from with language options with M$ products.
Regards, P1 :8)
M$ = Microsoft
Hi.
QuoteSo what you really want is to check for installed files for the LangID of the OS? And you want to know, if there is a SAPI function to enumerate the language options installed?
I only want to know the actual LangID from the speech, the user have changed to. The language, the user is listen to in a Text2Speech program :U
QuoteFrom a Quick Google search, what you want to do is Enumerate the Voices available to SAPI. Each Voice will have it's plain text descriptor and it's hex LangID, plus it's options, like male or female, etc..
Yes, I know. But I don't know, how to get it work. I could get the token with GetVoice, but I cannot read it for informations.
Shit, my English is to bad...
Best regards,
Nordwind
Quick and dirty is to enumerate the Registry Here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\VOICES\TOKENS
Note: I have only English setup, But I had to go through a Voice setup, to have these voices available ( One male, One female ).
Otherwise, you need to work through developing code from MSDN site:
In both SpEnumTokens and ISpObjectTokenCategory::EnumTokens the following clauses are permitted in the ReqAttrs and OptAttrs strings, separated by semicolons.
When what you want, is not there, then you need to develope a setup routine for those German Languges files and Voice setup.
Regards, P1 :8)
PS: Loading German Files does not setup the Voice for you. I just did and I have no new voices to use.
QuotePS: Loading German Files does not setup the Voice for you. I just did and I have no new voices to use.
Because you must have Microsoft Reader installed...
I will try to use your tips. Thanks!
Best regards,
Nordwind
Could not get it working. Ok, in the registry there are tokens for all speeches and languages. But I cannot detect, which ist the one, SAPI talks with...
Sorry, I need help. :red
Nordwind
When enumerating the tokens, under the voice name is a sub key of "ATTRIBUTES", under which you will find "Language" and the hex in text value of the LangID.
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\VOICES\TOKENS\LHMICHAEL\ATTRIBUTES]
"Gender"="Male"
"Language"="409"
"Name"="LH Michael"
I know that some registries entries are language based, so I don't know if it will say any of the above is English Key words or you may adjust for German Key words.
The registry method is going to be quicker to implement, but the SAPI function method, I am sure it's more language independent.
Regards, P1 :8)
Hi.
I understand, what you mean. I can get all infos about all installed languages, no problem.
But I cannot see, which language is marked as default! That is, what i want to know... :P
[HKEY_CURRENT_USER\Software\Microsoft\Speech\Voices]
"DefaultTokenId"="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\LHMICHAEL"
"DefaultTTSRate"=dword:00000000
LHMICHAEL is my local name for my default voice.
Regards, P1 :8)
:U
That's it! I only looked in HKEY_LOCAL_MACHINE instead of looking in HKEY_CURRENT_USER. :dazzled:
Now I can read the default language parameters!
Thank you a lot! :cheekygreen:
Best regards,
Nordwind
Ihr Empfang!
Haben Sie ein nettes Wochenende! :U
Aber ich bin ängstlich Sie haben mehr Arbeit vor Ihnen, als hinter Ihnen. :eek
Beachtungen, P1 :8)
PS: Ich habe gedacht, dass ich ein freies Deutsch zu englischem Übersetzer ausprobieren würde.
Hi.
Hehe. Your German is as bad as my English... :bg
Most work is done. Thanks! :U
Best regards,
Nordwind
I know this is a long delay, but i´m slowling coming back.
Here is the full source inside sapi translated to assembly (RosAsm syntax). The function needs to remove some annoyances (useless code, such as SpHrFromWin32 or SpHrFromLastWin32Error)
The macros are the default user made RosAsm ones, but...this can be easily ported to masm as well. (Proc, Local, If, Else, Else_If seems to be similar as in masm as far i can remember masm syntax).
The function below should work on all windows versions since win95 to Win7 and newer. This is only the 1st version, i´ll review the code later.
If suceeded the function will return the language ID. ON error the function will return FALSE.
This function have no parameters.
[OSVersionInfo:
OSVersionInfo.Size: D$ ?
OSVersionInfo.MajorVersion: D$ ?
OSVersionInfo.MinorVersion: D$ ?
OSVersionInfo.BuildNumber: D$ ?
OSVersionInfo.PlatformId: D$ ?
OSVersionInfo.CSDVersion: B$ ? #128
OSVersionInfo.ServicePackMajor: W$ ?
OSVersionInfo.ServicePackMinor: W$ ?
OSVersionInfo.SuiteMask: W$ ?
OSVersionInfo.ProductType: B$ ?
OSVersionInfo.Reserved: B$ ?]
[OSVI_SIZE 148 OSVI_EX_SIZE 156]
[SzData: B$ 0 #32]
[SzData2: B$ 0 #64]
Proc SpGetUserDefaultUILanguage:
Local @hr, @hKey, @dwSize, @ValueName, @SzData
Uses edi, esi, ebx, ecx, edx
mov D$OSVersionInfo.Size OSVI_SIZE
call 'Kernel32.GetVersionExA' OSVersionInfo
...If eax = &FALSE
call SpHrFromLastWin32Error; This is just to retrieve the error code. It have no pratical use on this function.
call 'KERNEL32.GetUserDefaultLangID'
; Get the UI language by one of three methods, depending on the system
...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_NT
..If D$OSVersionInfo.MajorVersion <= 4 ; running on WinNT4 or earlier
lea eax D@hKey
call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.DEFAULT\Control Panel\International', 0}, 0, &KEY_READ, eax
call SpHrFromWin32 eax ; Function succeed return &ERROR_SUCCESS = 0
; This is just to retrieve the error code. It have no pratical use on this function.
.If eax = &SUCCEEDED
mov D@dwSize 64
lea edx D@dwSize
call 'ADVAPI32.RegQueryValueExA' D@hKey, {'Locale', 0}, &NULL, &NULL, SzData2, edx
mov D@hr eax ; Function succeed return &ERROR_SUCCESS = 0
call SpHrFromWin32 eax ; This is just to retrieve the error code. It have no pratical use on this function.
call 'ADVAPI32.RegCloseKey' D@hKey
If D@hr = &SUCCEEDED ; Convert string to number
C_Call 'msvcrt.wcstol' SzData2, &NULL, 16
movzx eax ax
mov D@hr eax
End_If
If D@hr = 0401; Arabic Language
mov eax 0409 ; English US
Else_If D@hr = 040F ; Hebrew
mov eax 0409 ; English US
Else_If D@hr = 041E ; Thai
mov eax 0409 ; English US
Else_If D@hr = 0
call 'KERNEL32.GetUserDefaultLangID'
End_If
.Else
call 'KERNEL32.GetUserDefaultLangID'
.End_If
..Else ; running on win2000 or later
call 'KERNEL32.LoadLibraryA' {B$ 'kernel32.dll', 0}
.If eax = &FALSE
call SpHrFromLastWin32Error ; This is just to retrieve the error code. It have no pratical use on this function.
call 'KERNEL32.GetUserDefaultLangID'
.Else
mov ebx eax
call 'KERNEL32.GetProcAddress' eax, {B$ "GetUserDefaultUILanguage", 0}
If eax = 0
call SpHrFromLastWin32Error ; This is just to retrieve the error code. It have no pratical use on this function.
xor eax eax
Else
call eax
End_If
movzx eax ax
mov D@hr eax
call 'KERNEL32.FreeLibrary' ebx
If D@hr = 0
call 'KERNEL32.GetUserDefaultLangID'
Else
mov eax D@hr
End_If
.End_If
..End_If
...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_WINDOWS ; Running on Win9X or earlier
lea eax D@hKey
call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.Default\Control Panel\desktop\ResourceLocale', 0}, 0, &KEY_READ, eax
call SpHrFromWin32 eax ; Function succeed return &ERROR_SUCCESS = 0
.If eax = &SUCCEEDED
mov D@dwSize 32
mov D@ValueName 0
lea eax D@ValueName
lea edx D@dwSize
call 'ADVAPI32.RegQueryValueExA' D@hKey, eax, &NULL, &NULL, SzData, edx
; Function succeed return &ERROR_SUCCESS = 0
call SpHrFromWin32 eax ; This is just to retrieve the error code. It have no pratical use on this function.
movzx eax ax
mov D@hr eax
call 'ADVAPI32.RegCloseKey' D@hKey
If D@hr = &SUCCEEDED ; Convert string to number
C_Call 'msvcrt.strtol' SzData, &NULL, 16
movzx eax ax
On eax <> 0, ExitP
End_If
.End_If
call 'KERNEL32.GetUserDefaultLangID'
...Else ; unsupported windows version. (Win3s or unknown)
xor eax eax
...End_If
EndP
_______________________
Proc SpHrFromLastWin32Error:
call 'KERNEL32.GetLastError'
If eax = 0
mov eax &E_FAIL
Else
call SpHrFromWin32 eax
End_If
EndP
_____________________________
[HRESULT_FROM_WIN32 | #If #1=reg
#Error 'Please use only an address, immediate value or constant on this macro'
#Else_If #1=str
#Error 'Please use only an address, immediate value or constant on this macro'
#Else
mov eax #1 | test eax eax | jle L1> | and eax 0FFFF | or eax (&FACILITY_WIN32 shl 16 or 080000000) | L1:
#End_If]
Proc SpHrFromWin32:
Arguments @dwErr
HRESULT_FROM_WIN32 D@dwErr
EndP
_____________________________
Note: Edgar, Steve, and any others...feel free to translate it to masm syntax if you like.
BestRegards,
Guga
Version 2.0
[OSVersionInfo:
OSVersionInfo.Size: D$ ?
OSVersionInfo.MajorVersion: D$ ?
OSVersionInfo.MinorVersion: D$ ?
OSVersionInfo.BuildNumber: D$ ?
OSVersionInfo.PlatformId: D$ ?
OSVersionInfo.CSDVersion: B$ ? #128
OSVersionInfo.ServicePackMajor: W$ ?
OSVersionInfo.ServicePackMinor: W$ ?
OSVersionInfo.SuiteMask: W$ ?
OSVersionInfo.ProductType: B$ ?
OSVersionInfo.Reserved: B$ ?]
[OSVI_SIZE 148 OSVI_EX_SIZE 156]
[SzData: B$ 0 #32]
[SzData2: B$ 0 #64]
Proc SpGetUserDefaultUILanguage:
Local @hr, @hKey, @dwSize, @ValueName
Uses edi, esi, ebx, ecx, edx
mov D$OSVersionInfo.Size OSVI_SIZE
call 'Kernel32.GetVersionExA' OSVersionInfo
...If eax = &FALSE
call 'KERNEL32.GetUserDefaultLangID'
; Get the UI language by one of three methods, depending on the system
...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_NT
..If D$OSVersionInfo.MajorVersion <= 4 ; running on WinNT4 or earlier
lea eax D@hKey
call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.DEFAULT\Control Panel\International', 0}, 0, &KEY_READ, eax
.If eax = &ERROR_SUCCESS
mov D@dwSize 64
lea edx D@dwSize
call 'ADVAPI32.RegQueryValueExA' D@hKey, {'Locale', 0}, &NULL, &NULL, SzData2, edx
mov D@hr eax
call 'ADVAPI32.RegCloseKey' D@hKey
If D@hr = &ERROR_SUCCESS ; Convert string to number
C_Call 'msvcrt.wcstol' SzData2, &NULL, 16
movzx eax ax
Else
xor eax eax
End_If
mov D@hr eax
If D@hr = 0401; Arabic Language
mov eax 0409 ; English US
Else_If D@hr = 040F ; Hebrew
mov eax 0409 ; English US
Else_If D@hr = 041E ; Thai
mov eax 0409 ; English US
Else_If D@hr = 0
call 'KERNEL32.GetUserDefaultLangID'
End_If
.Else
call 'KERNEL32.GetUserDefaultLangID'
.End_If
..Else ; running on win2000 or later
call 'KERNEL32.LoadLibraryA' {B$ 'kernel32.dll', 0}
.If eax = &FALSE
call 'KERNEL32.GetUserDefaultLangID'
.Else
mov ebx eax
call 'KERNEL32.GetProcAddress' eax, {B$ "GetUserDefaultUILanguage", 0}
If eax <> &NULL
call eax
End_If
mov D@hr eax
call 'KERNEL32.FreeLibrary' ebx
If D@hr = &NULL
call 'KERNEL32.GetUserDefaultLangID'
Else
mov eax D@hr
End_If
.End_If
..End_If
...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_WINDOWS ; Running on Win9X or earlier
lea eax D@hKey
call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.Default\Control Panel\desktop\ResourceLocale', 0}, 0, &KEY_READ, eax
.If eax = &ERROR_SUCCESS
mov D@dwSize 32
mov D@ValueName 0
lea eax D@ValueName
lea edx D@dwSize
call 'ADVAPI32.RegQueryValueExA' D@hKey, eax, &NULL, &NULL, SzData, edx
movzx eax ax
mov D@hr eax
call 'ADVAPI32.RegCloseKey' D@hKey
If D@hr = &ERROR_SUCCESS; Convert string to number
C_Call 'msvcrt.strtol' SzData, &NULL, 16
movzx eax ax
On eax <> 0, ExitP
End_If
.End_If
call 'KERNEL32.GetUserDefaultLangID'
...Else ; unsupported windows version. (Win3s or unknown)
xor eax eax
...End_If
EndP