Thread overview
COMSTL vs. MinGW: compiling error
Oct 14, 2008
Chinfu
Oct 14, 2008
Chinfu
Oct 15, 2008
Matthew Wilson
Oct 15, 2008
Matthew Wilson
Oct 15, 2008
Matthew Wilson
Driving MS Speech API (SAPI) (was Re: COMSTL vs. MinGW: compiling error)
Oct 15, 2008
Matthew Wilson
Re: Driving MS Speech API (SAPI) - FastFormat example
Oct 15, 2008
Matthew Wilson
Re: Driving MS Speech API (SAPI) - why SAPI example doesn't speak
Oct 15, 2008
Matthew Wilson
October 14, 2008
Hi,
    I encountered a problem while I tried to complile C++ source codes
(listed below). I use MinGW-5.1.4 [GCC 3.4.5 (mingw-vista special r3)]
for compiling under Windows XP Pro. (SP2) and STLSoft 1.9.57. The error
I got is as follows:

>\MinGW\bin\g++.exe -c -I\MinGW\include -I\stlsoft-1.9.57\include -I"\Microsoft
Speech SDK 5.1\Include" test.cpp

/stlsoft-1.9.57/include/comstl/util/creation_functions.hpp: In function `HRESULT stlsoft::comstl_project::co_create_instance(const CLSID&, I**, DWORD) [with I = ISpVoice]':

/stlsoft-1.9.57/include/comstl/util/creation_functions.hpp:222:   instantiated from `HRESULT stlsoft::comstl_project::co_create_instance(const CLSID&, stlsoft::ref_ptr<T, I, U>&, DWORD) [with T = ISpVoice, I = ISpVoice, U = ISpVoice]'

test.cpp:19:   instantiated from here

d:/cygwin/home/chinfu/Sandbox/stlsoft-1.9.57/include/comstl/util/creation_functions.hpp:128: error: incomplete type `stlsoft::comstl_project::IID_traits<ISpVoice>' used in nested name specifier

    I've tried googling but no luck. Could someone help me out?
Thanks in advance.

Chinfu

C++ source codes:
-----------------
#include <windows.h>
#include <servprov.h>
#include <sapi.h>
#include <string>
#include <iostream>
#include <comstl/error/exceptions.hpp>
#include <comstl/util/initialisers.hpp>
#include <comstl/util/creation_functions.hpp>
#include <stlsoft/smartptr/ref_ptr.hpp>
#include <winstl/conversion/char_conversions.hpp>

//COMSTL_IID_TRAITS_DEFINE(ISpVoice)

class mySpeech {
    public:
        mySpeech() {
            static comstl::com_initializer coinit;
            HRESULT hr;
            if(FAILED(hr = comstl::co_create_instance(CLSID_SpVoice,_pVoice)))
                throw comstl::com_exception("Failed to create SpVoice COM instance",hr);
        }
        int sayit(const char* s, int n) {
            std::string(s,n);
            _pVoice->Speak(winstl::a2w(s), SPF_ASYNC, 0);
            return n;
        }
        void setRate(long n) { _pVoice->SetRate(n); }
    private:
        stlsoft::ref_ptr<ISpVoice> _pVoice;
};
// main
int main() {
    class mySpeech *msp;
    try {
        msp = new mySpeech();
    } catch (comstl::com_exception &e){
        std::cerr<< "error";
    }
    string s("hello world");
    msp.sayit(s);
    return 0;
}
October 14, 2008
Hi,
   It's me again. I found my mistake. By adding "namespace stlsoft{ namespace comstl{...} }" around the macro COMSTL_IID_TRAITS_DEFINE(ISpVoice), I've compiled it without error.
(I also corrected some errors in souce codes in the previous post.)

But I got the following 'warning' while linking,
Warning: .drectve `/DEFAULTLIB:"uuid.lib" /DEFAULTLIB:"uuid.lib" ' unrecognized

And there is no output while I run the generated execution file. Any help is appreciated. The source codes are listed below.

Chinfu

---
#include <windows.h>
#include <servprov.h>
#include <sapi.h>
#include <string>
#include <iostream>
#include <comstl/error/exceptions.hpp>
#include <comstl/util/initialisers.hpp>
#include <comstl/util/creation_functions.hpp>
#include <stlsoft/smartptr/ref_ptr.hpp>
#include <winstl/conversion/char_conversions.hpp>

namespace stlsoft {
namespace comstl_project {
    COMSTL_IID_TRAITS_DEFINE(ISpVoice)
}
}

class mySpeech {
    public:
        mySpeech() {
            static comstl::com_initializer coinit;
            HRESULT hr;
            if(FAILED(hr = comstl::co_create_instance(CLSID_SpVoice,_pVoice)))
                throw comstl::com_exception("Failed to create SpVoice COM instance",hr);
        }
        int sayit(const char* s, int n) {
            std::string(s,n);
            _pVoice->Speak(winstl::a2w(s), SPF_ASYNC, 0);
            return n;
        }
        void setRate(long n) { _pVoice->SetRate(n); }
    private:
        //COM object smart pointer
        stlsoft::ref_ptr<ISpVoice> _pVoice;
};
// Main
int main() {
    class mySpeech *msp;
    try {
        msp = new mySpeech();
    } catch (comstl::com_exception &e){
        std::cerr<< "error";
    }
    const char* str="hello, world";
    msp->sayit(str,13);
    return 0;
}

October 15, 2008
Am taking a look at this now.

btw, have you looked at VOLE: http://vole.sourceforge.net/. It simplifies the use of COM Automation a whole lot

Matt

"Chinfu" <chinfu.ku@gmail.com> wrote in message news:gd1kht$1otn$1@digitalmars.com...
> Hi,
>    It's me again. I found my mistake. By adding "namespace stlsoft{ namespace comstl{...} }" around the macro
COMSTL_IID_TRAITS_DEFINE(ISpVoice), I've compiled it without error.
> (I also corrected some errors in souce codes in the previous post.)
>
> But I got the following 'warning' while linking,
> Warning: .drectve `/DEFAULTLIB:"uuid.lib" /DEFAULTLIB:"uuid.lib" ' unrecognized
>
> And there is no output while I run the generated execution file. Any help is appreciated. The source codes are listed below.
>
> Chinfu
>
> ---
> #include <windows.h>
> #include <servprov.h>
> #include <sapi.h>
> #include <string>
> #include <iostream>
> #include <comstl/error/exceptions.hpp>
> #include <comstl/util/initialisers.hpp>
> #include <comstl/util/creation_functions.hpp>
> #include <stlsoft/smartptr/ref_ptr.hpp>
> #include <winstl/conversion/char_conversions.hpp>
>
> namespace stlsoft {
> namespace comstl_project {
>     COMSTL_IID_TRAITS_DEFINE(ISpVoice)
> }
> }
>
> class mySpeech {
>     public:
>         mySpeech() {
>             static comstl::com_initializer coinit;
>             HRESULT hr;
>             if(FAILED(hr = comstl::co_create_instance(CLSID_SpVoice,_pVoice)))
>                 throw comstl::com_exception("Failed to create SpVoice COM instance",hr);
>         }
>         int sayit(const char* s, int n) {
>             std::string(s,n);
>             _pVoice->Speak(winstl::a2w(s), SPF_ASYNC, 0);
>             return n;
>         }
>         void setRate(long n) { _pVoice->SetRate(n); }
>     private:
>         //COM object smart pointer
>         stlsoft::ref_ptr<ISpVoice> _pVoice;
> };
> // Main
> int main() {
>     class mySpeech *msp;
>     try {
>         msp = new mySpeech();
>     } catch (comstl::com_exception &e){
>         std::cerr<< "error";
>     }
>     const char* str="hello, world";
>     msp->sayit(str,13);
>     return 0;
> }
>


October 15, 2008
"Matthew Wilson" <matthew@hat.stlsoft.dot.org> wrote in message news:gd5jmp$1p2f$1@digitalmars.com...
> Am taking a look at this now.
>
> btw, have you looked at VOLE: http://vole.sourceforge.net/. It simplifies the use of COM Automation a whole lot

Scratch that. SAPI does not support automation (IDispatch). Sorry for the misdirect


October 15, 2008
"Matthew Wilson" <matthew@hat.stlsoft.dot.org> wrote in message news:gd5l7s$1rlt$1@digitalmars.com...
>
> "Matthew Wilson" <matthew@hat.stlsoft.dot.org> wrote in message news:gd5jmp$1p2f$1@digitalmars.com...
> > Am taking a look at this now.
> >
> > btw, have you looked at VOLE: http://vole.sourceforge.net/. It simplifies the use of COM Automation a whole lot
>
> Scratch that. SAPI does not support automation (IDispatch). Sorry for the misdirect

Doh! Wrong again. It does.

I'm writing a couple of examples of how to do all this ... be with you shortly.

Matt


October 15, 2008
> > > btw, have you looked at VOLE: http://vole.sourceforge.net/. It simplifies the use of COM Automation a whole lot
>
> I'm writing a couple of examples of how to do all this ... be with you shortly.

I've written up an example using ISpVoice directly, and it fails to talk for me also. I will try and find out why.

In the meantime, here's an example using VOLE.



#include <vole/vole.hpp>

#include <comstl/util/initialisers.hpp>

#include <iostream>

int main(int /* argc */, char** /* argv */)
{
    try
    {
        comstl::com_initialiser coinit;

        vole::object    speaker = vole::object::create("SAPI.SpVoice");

#if defined(STLSOFT_COMPILER_IS_MSVC) && \
    _MSC_VER < 1310

        // VC++ 6 cannot use the "normal" VOLE way of explicitly
        // specialising the method function template on return type, so
        // we have to use invoke_method_v()

        speaker.invoke_method_v(L"Speak", "I have something to say!", 0);

#else /* ? _DEBUG */

        // The "normal" VOLE way

        speaker.invoke_method<void>(L"Speak", "I have something to say!", 0);

#endif /* _DEBUG */

        return EXIT_SUCCESS;
    }
    catch(std::bad_alloc&)
    {
        std::cerr << "out of memory" << std::endl;
    }
    catch(vole::vole_exception& x)
    {
        std::cerr << "operation failed: " << x.what() << ": " << winstl::error_desc_a(x.hr()) << std::endl;
    }
    catch(std::exception& x)
    {
        std::cerr << "operation failed: " << x.what() << std::endl;
    }
    catch(...)
    {
        std::cerr << "unexpected condition" << std::endl;
    }

    return EXIT_FAILURE;
}


I'm also doing a FastFormat version.

I'll put them all up on the STLSoft wiki site shortly.

HTH

Matt



October 15, 2008
Here's the FastFormat example (with error-handling elided)



#include <fastformat/fastformat.hpp>
#include <fastformat/sinks/speech.hpp>

int main(int argc, char** argv)
{
    {   // Say one thing only

        fastformat::write(fastformat::speech_sink(), "I have something to say!");

    }

    {   // Say several things

        fastformat::speech_sink speaker;

        fastformat::write(speaker, "I have something to say!");

        fastformat::write(speaker, "I have something else to say!");
    }

    return EXIT_SUCCESS;
}





October 15, 2008
If you look again at the code

class mySpeech {
    public:
        mySpeech() {
            static comstl::com_initializer coinit;
            HRESULT hr;
            if(FAILED(hr = comstl::co_create_instance(CLSID_SpVoice,_pVoice)))
                throw comstl::com_exception("Failed to create SpVoice COM instance",hr);
        }
        int sayit(const char* s, int n) {
            std::string(s,n);
            _pVoice->Speak(winstl::a2w(s), SPF_ASYNC, 0);
            return n;
        }
        void setRate(long n) { _pVoice->SetRate(n); }
    private:
        //COM object smart pointer
        stlsoft::ref_ptr<ISpVoice> _pVoice;
};
// Main
int main() {
    class mySpeech *msp;
    try {
        msp = new mySpeech();
    } catch (comstl::com_exception &e){
        std::cerr<< "error";
    }
    const char* str="hello, world";
    msp->sayit(str,13);
    return 0;
}


This fails to speak because:
- the call to sayit() is made immediately before the program exits.
- the Speak() command is passed the SPF_ASYNC flag, which causes the speech to be executed on a worker thread

So the reason if fails to speak is because the program exits before it can get it out.

There are two ways to make this speak:
- add a Sleep() call after sayit() - 1.5 seconds is required on my system to get out the whole sentence
- change SFP_ASYNC to SPF_DEFAULT, causing the Speak() call to be synchronous

HTH

Matt