the program runs less than 2 sec - c++

I got this code from MSDN to change the Text to speech and I did all the sitting which were in the tutorial the code works without errors but when I run the code the code run for less than 2 second and then come back to the main code without read the code. my question here is what is the problem exactly?
this is the code:
#include "stdafx.h"
#include <sapi.h>
#include <initguid.h>
int main(int argc, char* argv[])
{
ISpVoice * pVoice = NULL;
if (FAILED(::CoInitialize(NULL)))
return FALSE;
HRESULT hr = CoCreateInstance(__uuidof(SpVoice), NULL, CLSCTX_ALL, __uuidof(SpVoice), (void **)&pVoice);
if( SUCCEEDED( hr ) )
{
hr = pVoice->Speak(L"Hello world", 0, NULL);
hr = pVoice->Speak(L"This sounds normal <pitch middle = '-10'/> but the pitch drops half way through", SPF_IS_XML, NULL );
pVoice->Release();
pVoice = NULL;
}
::CoUninitialize();
return TRUE;
}

Your call to CoCreateInstance() is wrong. You are passing the CLSID of the SpVoice CoClass where the IID of the ISpVoice interface is expected instead (so it should be failing with an E_NOINTERFACE error).
Try this instead:
CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
Alternatively:
CoCreateInstance(__uuidof(SpVoice), NULL, CLSCTX_ALL, IID_PPV_ARGS(&pVoice));

Related

How to Initialize HRESULT for SetMasterVolume?

#include <iostream>
#include <windows.h>
#include <Audioclient.h>
int main(){
ShellExecute(NULL, "open", "https://www.youtube.com/watch?v=zf2VYAtqRe0", NULL, NULL, SW_SHOWNORMAL);
HRESULT SetMasterVolume(1.0, NULL);
return();
}
Okay so I'm trying to code this program, that opens a YouTube song, and turns up the volume at the same time. I don´t understand the error I get.
ERROR : C2440 ´initializing´: cannot convert from ´initializer list´ to ´HRESULT´
So therefore my question is: how do I initialize HRESULT so SetMasterVolume works? Or, how to setup SetMasterVolume? And please, if possible, explain why I cant just write
SetMasterVolume(1.0,NULL);
When I have included audioclient.h
ISimpleAudioVolume::SetMasterVolume is a COM method, it is not a regular WinAPI. You get a compile error when you just type in the function. Adding HRESULT in front of it will cause a different C++ error.
Use this code instead, with SetMasterVolumeLevelScalar
Based on code from:
Change Master Volume in Visual C++
#include <Windows.h>
#include <Mmdeviceapi.h>
#include <Endpointvolume.h>
BOOL ChangeVolume(float nVolume)
{
HRESULT hr = NULL;
IMMDeviceEnumerator *deviceEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator), (LPVOID *)&deviceEnumerator);
if(FAILED(hr))
return FALSE;
IMMDevice *defaultDevice = NULL;
hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &defaultDevice);
deviceEnumerator->Release();
if(FAILED(hr))
return FALSE;
IAudioEndpointVolume *endpointVolume = NULL;
hr = defaultDevice->Activate(__uuidof(IAudioEndpointVolume),
CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
defaultDevice->Release();
if(FAILED(hr))
return FALSE;
hr = endpointVolume->SetMasterVolumeLevelScalar(nVolume, NULL);
endpointVolume->Release();
return SUCCEEDED(hr);
}
int main()
{
CoInitialize(NULL);
ChangeVolume(0.5);
CoUninitialize();
return 0;
}
You need to give it a name and assign to it.
HRESULT hResult = SetMasterVolume(1.0, NULL);

WMI CPUTemp Always Returns Same Value

I'm trying to get my CPU's temperature from WMI. But when i execute code from admin command prompt. It always returns same value;
"CPU = 39.050000 C".
I don't know where i've made mistake. My OS is Windows 10 64-bit and I use Visual Studio 2017 15.1 .I wrote same code on C# and it returns same value too just 39. I did some research but I'm still not sure how to approach this.
#define _WIN32_DCOM
#include <iostream>
#include "stdafx.h"
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
HRESULT GetCpuTemperature(LPLONG pTemperature)
{
if (pTemperature == NULL)
return E_INVALIDARG;
*pTemperature = -1;
HRESULT ci = CoInitialize(NULL);
HRESULT hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
if (SUCCEEDED(hr))
{
IWbemLocator *pLocator;
hr = CoCreateInstance(CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&pLocator);
if (SUCCEEDED(hr))
{
IWbemServices *pServices;
BSTR ns = SysAllocString(L"root\\WMI");
hr = pLocator->ConnectServer(ns, NULL, NULL, NULL, 0, NULL, NULL, &pServices);
pLocator->Release();
SysFreeString(ns);
if (SUCCEEDED(hr))
{
BSTR query = SysAllocString(L"SELECT * FROM MSAcpi_ThermalZoneTemperature");
BSTR wql = SysAllocString(L"WQL");
IEnumWbemClassObject *pEnum;
hr = pServices->ExecQuery(wql, query, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pEnum);
SysFreeString(wql);
SysFreeString(query);
pServices->Release();
if (SUCCEEDED(hr))
{
IWbemClassObject *pObject;
ULONG returned;
hr = pEnum->Next(WBEM_INFINITE, 1, &pObject, &returned);
pEnum->Release();
if (SUCCEEDED(hr))
{
BSTR temp = SysAllocString(L"CurrentTemperature");
VARIANT v;
VariantInit(&v);
hr = pObject->Get(temp, 0, &v, NULL, NULL);
pObject->Release();
SysFreeString(temp);
if (SUCCEEDED(hr))
{
*pTemperature = V_I4(&v);
}
VariantClear(&v);
}
}
}
if (ci == S_OK)
{
CoUninitialize();
}
}
}
return hr;
}
Here is my main code
int main(int argc, char **argv)
{
LONG temp;
GetCpuTemperature(&temp);
printf("CPU = %lf °C\n", ((double)temp / 10 - 273.15));
getc(stdin);
return 0;
}
Edit:Wrong info.
In my opinion,it is none of VARIANT's business, because of this command line in Windows:
"wmic /namespace:\\root\wmi PATH MSAcpi_ThermalZoneTemperature get CurrentTemperature"
This command needs Administrator role, then you will always see the same values.

Play Audio Stream Using Windows APIs in C++

To play an .mp3 file in Windows using (in this case) DirectShow you only need:
#include <dshow.h>
#include <cstdio>
// For IID_IGraphBuilder, IID_IMediaControl, IID_IMediaEvent
#pragma comment(lib, "strmiids.lib")
const wchar_t* filePath = L"C:/Users/Public/Music/Sample Music/Sleep Away.mp3";
int main()
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent *pEvent = NULL;
// Initialize the COM library.
HRESULT hr = ::CoInitialize(NULL);
if (FAILED(hr))
{
::printf("ERROR - Could not initialize COM library");
return 0;
}
// Create the filter graph manager and query for interfaces.
hr = ::CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
::printf("ERROR - Could not create the Filter Graph Manager.");
return 0;
}
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph.
hr = pGraph->RenderFile(filePath, NULL);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
// Clean up in reverse order.
pEvent->Release();
pControl->Release();
pGraph->Release();
::CoUninitialize();
}
I can't find a way to have something like this, but to be able to play an .asx instead, like for example: http://listen.radiotunes.com/public5/solopiano.asx
In MSDN I can only find ways to do this in C# making a Forms application and inserting a WindowsMediaPlayer control in a form.
Any ideas?
An .asx file is actually a playlist. See here some information about the format.
.asx is not supported by DirectShow. See here for the supported formats.
You might parse the file, as it is XML, and find the actual URL of the stream, and then play it, or you could use the Windows Media Player SDK. You can see some sample code for WM SDK here.
OK, got it to work with this example taken from here and adding this extra line: hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");:
#include "atlbase.h"
#include "atlwin.h"
#include "wmp.h"
#include <cstdio>
int _tmain(int argc, _TCHAR* argv[])
{
CoInitialize(NULL);
HRESULT hr = S_OK;
CComBSTR bstrVersionInfo; // Contains the version string.
CComPtr<IWMPPlayer> spPlayer; // Smart pointer to IWMPPlayer interface.
hr = spPlayer.CoCreateInstance(__uuidof(WindowsMediaPlayer), 0, CLSCTX_INPROC_SERVER);
if (SUCCEEDED(hr))
{
hr = spPlayer->get_versionInfo(&bstrVersionInfo);
hr = spPlayer->put_URL(L"http://listen.radiotunes.com/public5/solopiano.asx");
}
if (SUCCEEDED(hr))
{
// Show the version in a message box.
COLE2T pStr(bstrVersionInfo);
MessageBox(NULL, (LPCSTR)pStr, _T("Windows Media Player Version"), MB_OK);
}
// Clean up.
spPlayer.Release();
CoUninitialize();
return 0;
}

How to use DirectShow and webcam to preview an image

I'm trying to use C++ and DirectShow to display my webcam... but I'm having some troubles.
The following code gives me a segmentation fault on:
m_pDF->EnumPins(&pinEnum);
my cpp code:
#include <tchar.h>
#include <strsafe.h>
#include <dshow.h>
#include <atlbase.h>
#include <d3d9.h>
#include <vmr9.h>
#pragma comment(lib,"Strmiids.lib")
#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum)
{
// Create the System Device Enumerator.
ICreateDevEnum *pDevEnum; // Video and Audio interface object
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); // Creates the system device enumerator
if (SUCCEEDED(hr))
{
// Create an enumerator for the category.
hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); // Enumeration of 'category' objects
if (hr == S_FALSE)
{
hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error.
}
pDevEnum->Release(); // Deletes Enumeration object
}
return hr;
}
void main(void)
{
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL; // contains methods for stopping and starting the graph
IMediaEvent *pEvent = NULL; // methods for getting events from the Filter Graph Manager
IPin *m_pCamOutPin;
IBaseFilter *m_pDF=NULL;
IMoniker *pM;
IEnumMoniker *pEnum; // Enumerator object
// Initialize the COM library.
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("ERROR - Could not initialize COM library");
return;
}
// Create the filter graph manager and query for interfaces.
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
// Bind
hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum);
pEnum->Next(1, &pM, NULL);
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF);
pM->Release();
hr=pGraph->AddFilter(m_pDF, L"Video Capture");
CComPtr<IEnumPins> pinEnum;
m_pDF->EnumPins(&pinEnum);
hr = pinEnum->Reset();
hr = pinEnum->Next(1, &m_pCamOutPin, NULL);
if (FAILED(hr))
return;
// control
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
// Build the graph. IMPORTANT: Change this string to a file on your system.
hr = pGraph->Render(m_pCamOutPin);
if (SUCCEEDED(hr))
{
// Run the graph.
hr = pControl->Run();
if (SUCCEEDED(hr))
{
// Wait for completion.
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely.
}
}
SAFE_RELEASE(pControl);
SAFE_RELEASE(pEvent);
SAFE_RELEASE(pGraph);
CoUninitialize();
}
Any ideas on what am I doing wrong and what do I have to do to get this to work?
m_pDF is a pointer to IBaseFilter:
IBaseFilter *m_pDF=NULL;
BindToObject last parameter is a pointer to a pointer. Which means this functioncall is wrong:
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF);
Instead you need to pass the address of m_pDF to get a pointer to a pointer:
pM->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pDF);
It is not a problem to cast IBaseFilter** to void**, but you can't cast IBaseFilter* to void**.
The crash should be related m_pDF, it not be a valid pointer.
you should add check for pM->BindToObject(0, 0, IID_IBaseFilter, (void**)m_pDF); to know that m_pDF is initialize sucess or not.
and you should also check hr=pGraph->AddFilter(m_pDF, L"Video Capture"); hr is ok or not.
if fail, you can get the error code know the reason.

Subsequent SpVoice instances are silent

Discovered key to the problem/crash, see the bottom of the post.
When creating instances of ISpVoice using CoCreateInstance, it seems like instances after the first one cannot speak as soon as the first one has spoken. That is, if pVoice speaks first, pVoice2 will not speak. If pVoice2 speaks first, pVoice will not speak. The order of creation/allocation does not seem to matter.
When I say "will not speak", I mean: calls to ISpVoice::Speak return immediately with the result S_OK; no voice was synthesized.
Correction: the above happens in the D version when the debugger is not attached. When the Visual Studio debugger is attached, an access violation occurs at vtjpnsapi50.dll!10004e65. Also, the access violation happens in the C++ version regardless of whether a debugger is attached or debug information is generated.
Inserting a call to sleep inbetween the calls to Speak does not change anything (except, of course, that it inserts a delay).
Reproduction in D (C++ equivalent is below):
import std.c.windows.com;
import core.sys.windows.windows;
import speech.windows.sapi;
import std.stdio;
int main()
{
if (FAILED(CoInitialize(null)))
return 1;
scope(exit) CoUninitialize();
ISpVoice pVoice;
HRESULT hr = CoCreateInstance(&CLSID_SpVoice, null, CLSCTX_ALL, &IID_ISpVoice, cast(void**)&pVoice);
assert(hr == S_OK);
hr = pVoice.Speak("Hello world", 0, null); // This speaks fine
assert(hr == S_OK);
ISpVoice pVoice2;
hr = CoCreateInstance(&CLSID_SpVoice, null, CLSCTX_ALL, &IID_ISpVoice, cast(void**)&pVoice2);
assert(hr == S_OK);
hr = pVoice2.Speak("hello again", 0, null); // This returns immediately
assert(hr == S_OK); // Yet it still returns S_OK
hr = pVoice.Speak("first voice again", 0, null); // This speaks fine too, immediately after "hello world" finishes
assert(hr == S_OK);
// The two objects are indeed at different memory addresses
writefln("voice 1: %s, voice 2: %s", cast(void*)pVoice, cast(void*)pVoice2);
pVoice.Release();
pVoice = null;
pVoice2.Release();
pVoice2 = null;
return 0;
}
This is the equivalent C++ program:
#include <sapi.h>
#include<Windows.h>
int main()
{
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
return 1;
ISpVoice* pVoice;
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
hr = pVoice->Speak(L"Hello world", 0, NULL); // This speaks fine
ISpVoice* pVoice2;
hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice2);
hr = pVoice2->Speak(L"hello again", 0, NULL); // This causes an access violation
hr = pVoice->Speak(L"first voice again", 0, NULL);
pVoice->Release();
pVoice = NULL;
pVoice2->Release();
pVoice2 = NULL;
CoUninitialize();
return 0;
}
In the above example, both voices are allocated with the same parameters, and the first voice to speak works properly. In the D version when a debugger is not attached, the second call to Speak on pVoice also works.
If anyone has any idea what could cause this, or know about any open source software where multiple voice objects are used, please let me know, thanks!
edit
This only happens with NeoSpeech's voices. It works fine with Microsoft's and eSpeak's voices. I'd still like to know if there's anything I could do to remedy the problem (NeoSpeech has some really, really good voices...).