[Win32] Add media client, server, GUI examples
authorDavid Antler <david.a.antler@intel.com>
Wed, 24 Feb 2016 00:49:46 +0000 (16:49 -0800)
committerDavid Antler <david.a.antler@intel.com>
Thu, 2 Jun 2016 17:41:03 +0000 (17:41 +0000)
Change-Id: Ia4c4861ba932692a4ea40c5a2bff46f8791935fa
Signed-off-by: David Antler <david.a.antler@intel.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/5693
Reviewed-by: Daniel Jay Ferguson <daniel.j.ferguson@intel.com>
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
resource/examples/SConscript
resource/examples/mediaserver.cpp [new file with mode: 0644]
resource/examples/winuiclient.cpp [new file with mode: 0644]
resource/examples/winuiclient.h [new file with mode: 0644]
resource/examples/winuiclientgui.cpp [new file with mode: 0644]

index fc95143..a1f3c7d 100644 (file)
@@ -75,6 +75,10 @@ if target_os in ['darwin', 'ios']:
 
 if env.get('LOGGING'):
        examples_env.AppendUnique(CPPDEFINES = ['TB_LOG'])
+
+if target_os in ['msys_nt', 'windows']:
+       examples_env.AppendUnique(LIBS = ['Comctl32', 'Gdi32', 'User32'])
+
 ######################################################################
 # Source files and Targets
 ######################################################################
@@ -102,7 +106,8 @@ clientjson = examples_env.Install(env.get('BUILD_DIR') + '/resource/examples/',
                                env.get('SRC_DIR') + '/resource/examples/' + 'oic_svr_db_client.dat')
 serverjson = examples_env.Install(env.get('BUILD_DIR') + '/resource/examples/',
                                env.get('SRC_DIR') + '/resource/examples/' + 'oic_svr_db_server.dat')
-Alias("examples", [simpleserver, simpleclient,
+
+examples_array = [simpleserver, simpleclient,
                simpleserverHQ, simpleclientHQ,
                fridgeserver, fridgeclient,
                presenceserver, presenceclient,
@@ -113,5 +118,14 @@ Alias("examples", [simpleserver, simpleclient,
                devicediscoveryserver, devicediscoveryclient,
                threadingsample,
                serverjson, clientjson
-     ])
+     ]
+
+# Add platform-specific examples
+
+if target_os in ['msys_nt', 'windows']:
+       winUIClient = examples_env.Program('winUIClient', ['winuiclientgui.cpp', 'winuiclient.cpp'])
+       mediaserver = examples_env.Program('mediaserver', 'mediaserver.cpp')
+       examples_array += [winUIClient, mediaserver]
+
+Alias("examples", examples_array)
 env.AppendTarget('examples')
diff --git a/resource/examples/mediaserver.cpp b/resource/examples/mediaserver.cpp
new file mode 100644 (file)
index 0000000..0711e7f
--- /dev/null
@@ -0,0 +1,642 @@
+/* ****************************************************************
+ *
+ * Copyright 2016 Intel Corporation All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+///
+/// This sample provides steps to define an interface for a resource
+/// (properties and methods) and host this resource on the server.
+///
+
+#include <functional>
+#include <mutex>
+#if defined(__msys_nt__)
+#include <unistd.h>
+#elif defined(_VS2015_)
+//#include <win32alias.h>
+#define sleep(SECS)   Sleep(1000*(SECS))
+#endif
+#include <condition_variable>
+
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include <windows.h>
+#include <objbase.h>
+
+#include <commctrl.h>
+#include <mmdeviceapi.h>
+#include <endpointvolume.h>
+#include <stdio.h>
+#include <math.h>       /* log */
+
+#define SAFE_RELEASE(x)  \
+              if ((x) != NULL)  \
+                { (x)->Release(); (x) = NULL; }
+
+using namespace OC;
+using namespace std;
+namespace PH = std::placeholders;
+
+int gObservation = 0;
+void * ChangeMediaRepresentation (void *param);
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest);
+void playPause(void);
+void setVolume(int vol);
+int getVolume(void);
+
+// Specifies where to notify all observers or list of observers
+// false: notifies all observers
+// true: notifies list of observers
+bool isListOfObservers = false;
+
+// Specifies secure or non-secure
+// false: non-secure resource
+// true: secure resource
+bool isSecure = false;
+
+/// Specifies whether Entity handler is going to do slow response or not
+bool isSlowResponse = false;
+
+
+// Forward declaring the entityHandler
+
+/// This class represents a single resource named 'MediaResource'. This resource has
+/// two simple properties named 'state' and 'volume'
+
+class MediaResource
+{
+
+public:
+    /// Access this property from a TB client
+    std::string m_name;
+    bool m_state;
+    int m_volume;
+    std::string m_mediaUri;
+    OCResourceHandle m_resourceHandle;
+    OCRepresentation m_mediaRep;
+    ObservationIds m_interestedObservers;
+
+public:
+    /// Constructor
+    MediaResource()
+        :m_name("Media Player"), m_state(false), m_volume(0), m_mediaUri("/a/media"),
+                m_resourceHandle(nullptr)
+    {
+        // Initialize representation
+        m_mediaRep.setUri(m_mediaUri);
+
+        m_mediaRep.setValue("state", m_state);
+        m_mediaRep.setValue("volume", m_volume);
+        m_mediaRep.setValue("name", m_name);
+    }
+
+    /* Note that this does not need to be a member function: for classes you do not have
+    access to, you can accomplish this with a free function: */
+
+    /// This function internally calls registerResource API.
+    void createResource()
+    {
+        //URI of the resource
+        std::string resourceURI = m_mediaUri;
+        //resource type name. In this case, it is media
+        std::string resourceTypeName = "core.media";
+        // resource interface.
+        std::string resourceInterface = DEFAULT_INTERFACE;
+
+        // OCResourceProperty is defined ocstack.h
+        uint8_t resourceProperty;
+        if(isSecure)
+        {
+            resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE | OC_SECURE;
+        }
+        else
+        {
+            resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+        }
+        EntityHandler cb = std::bind(&MediaResource::entityHandler, this,PH::_1);
+
+        // This will internally create and register the resource.
+        OCStackResult result = OCPlatform::registerResource(
+                                    m_resourceHandle, resourceURI, resourceTypeName,
+                                    resourceInterface, cb, resourceProperty);
+
+        if (OC_STACK_OK != result)
+        {
+            cout << "Resource creation was unsuccessful\n";
+        }
+    }
+
+    OCResourceHandle getHandle()
+    {
+        return m_resourceHandle;
+    }
+
+    // Puts representation.
+    // Gets values from the representation and
+    // updates the internal state
+    void put(OCRepresentation& rep)
+    {
+        try
+        {
+            if (rep.getValue("state", m_state))
+            {
+                cout << "\t\t\t\t" << "state: " << m_state << endl;
+                if(m_state)
+                {
+                    playPause();
+                }
+            }
+            else
+            {
+                cout << "\t\t\t\t" << "state not found in the representation" << endl;
+            }
+
+            if (rep.getValue("volume", m_volume))
+            {
+                cout << "\t\t\t\t" << "volume: " << m_volume << endl;
+                if((0 <= m_volume) && (m_volume <= 100))
+                {
+                    setVolume(m_volume);
+                }
+            }
+            else
+            {
+                cout << "\t\t\t\t" << "volume not found in the representation" << endl;
+            }
+        }
+        catch (exception& e)
+        {
+            cout << e.what() << endl;
+        }
+
+    }
+
+    // Post representation.
+    // Post can create new resource or simply act like put.
+    // Gets values from the representation and
+    // updates the internal state
+    OCRepresentation post(OCRepresentation& rep)
+    {
+        put(rep);
+        return get();
+    }
+
+
+    // gets the updated representation.
+    // Updates the representation with latest internal state before
+    // sending out.
+    OCRepresentation get()
+    {
+        m_mediaRep.setValue("state", m_state);
+        m_mediaRep.setValue("volume", m_volume);
+
+        return m_mediaRep;
+    }
+
+    void addType(const std::string& type) const
+    {
+        OCStackResult result = OCPlatform::bindTypeToResource(m_resourceHandle, type);
+        if (OC_STACK_OK != result)
+        {
+            cout << "Binding TypeName to Resource was unsuccessful\n";
+        }
+    }
+
+    void addInterface(const std::string& intf) const
+    {
+        OCStackResult result = OCPlatform::bindInterfaceToResource(m_resourceHandle, intf);
+        if (OC_STACK_OK != result)
+        {
+            cout << "Binding TypeName to Resource was unsuccessful\n";
+        }
+    }
+
+private:
+// This is just a sample implementation of entity handler.
+// Entity handler can be implemented in several ways by the manufacturer
+OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
+{
+    cout << "\tIn Server CPP entity handler:\n";
+    OCEntityHandlerResult ehResult = OC_EH_ERROR;
+    if(request)
+    {
+        // Get the request type and request flag
+        std::string requestType = request->getRequestType();
+        int requestFlag = request->getRequestHandlerFlag();
+
+        if(requestFlag & RequestHandlerFlag::RequestFlag)
+        {
+            cout << "\t\trequestFlag : Request\n";
+            auto pResponse = std::make_shared<OC::OCResourceResponse>();
+            pResponse->setRequestHandle(request->getRequestHandle());
+            pResponse->setResourceHandle(request->getResourceHandle());
+
+            // Check for query params (if any)
+            QueryParamsMap queries = request->getQueryParameters();
+
+            if (!queries.empty())
+            {
+                cout << "\nQuery processing upto entityHandler" << std::endl;
+            }
+            for (auto it : queries)
+            {
+                cout << "Query key: " << it.first << " value : " << it.second
+                        << std::endl;
+            }
+
+            // If the request type is GET
+            if(requestType == "GET")
+            {
+                cout << "\t\t\trequestType : GET\n";
+                if(isSlowResponse) // Slow response case
+                {
+                    static int startedThread = 0;
+                    if(!startedThread)
+                    {
+                        std::thread t(handleSlowResponse, (void *)this, request);
+                        startedThread = 1;
+                        t.detach();
+                    }
+                    ehResult = OC_EH_SLOW;
+                }
+                else // normal response case.
+                {
+                    pResponse->setErrorCode(200);
+                    pResponse->setResponseResult(OC_EH_OK);
+                    pResponse->setResourceRepresentation(get());
+                    if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                    {
+                        ehResult = OC_EH_OK;
+                    }
+                }
+            }
+            else if(requestType == "PUT")
+            {
+                cout << "\t\t\trequestType : PUT\n";
+                OCRepresentation rep = request->getResourceRepresentation();
+
+                // Do related operations related to PUT request
+                // Update the mediaResource
+                put(rep);
+                pResponse->setErrorCode(200);
+                pResponse->setResponseResult(OC_EH_OK);
+                pResponse->setResourceRepresentation(get());
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
+            }
+            else if(requestType == "POST")
+            {
+                cout << "\t\t\trequestType : POST\n";
+
+                OCRepresentation rep = request->getResourceRepresentation();
+
+                // Do related operations related to POST request
+                OCRepresentation rep_post = post(rep);
+                pResponse->setResourceRepresentation(rep_post);
+                pResponse->setErrorCode(200);
+                if(rep_post.hasAttribute("createduri"))
+                {
+                    pResponse->setResponseResult(OC_EH_RESOURCE_CREATED);
+                    pResponse->setNewResourceUri(rep_post.getValue<std::string>("createduri"));
+                }
+                else
+                {
+                    pResponse->setResponseResult(OC_EH_OK);
+                }
+
+                if(OC_STACK_OK == OCPlatform::sendResponse(pResponse))
+                {
+                    ehResult = OC_EH_OK;
+                }
+            }
+            else if(requestType == "DELETE")
+            {
+                cout << "Delete request received" << endl;
+            }
+        }
+
+        if(requestFlag & RequestHandlerFlag::ObserverFlag)
+        {
+            ObservationInfo observationInfo = request->getObservationInfo();
+            if(ObserveAction::ObserveRegister == observationInfo.action)
+            {
+                m_interestedObservers.push_back(observationInfo.obsId);
+            }
+            else if(ObserveAction::ObserveUnregister == observationInfo.action)
+            {
+                m_interestedObservers.erase(std::remove(
+                                                            m_interestedObservers.begin(),
+                                                            m_interestedObservers.end(),
+                                                            observationInfo.obsId),
+                                                            m_interestedObservers.end());
+            }
+
+            cout << "\t\trequestFlag : Observer\n";
+            gObservation = 1;
+            static int startedThread = 0;
+
+            // Observation happens on a different thread in ChangeMediaRepresentation function.
+            // If we have not created the thread already, we will create one here.
+
+            if(!startedThread)
+            {
+                std::thread t(ChangeMediaRepresentation, (void *)this);
+                startedThread = 1;
+                t.detach();
+            }
+
+            ehResult = OC_EH_OK;
+        }
+    }
+    else
+    {
+        cout << "Request invalid" << std::endl;
+    }
+
+    return ehResult;
+}
+
+};
+
+// ChangeMediaRepresentaion is an observation function,
+// which notifies any changes to the resource to stack
+// via notifyObservers
+void * ChangeMediaRepresentation (void *param)
+{
+    int prevVolume = 0;
+    MediaResource* mediaPtr = (MediaResource*) param;
+
+    // This function continuously monitors for the changes
+    while (1)
+    {
+        Sleep(100);
+
+        if (gObservation)
+        {
+            prevVolume = mediaPtr->m_volume;
+            mediaPtr->m_volume = getVolume();
+            if (prevVolume == mediaPtr->m_volume)
+                continue;
+
+            cout << "Volume changed from " << prevVolume << "% to " << mediaPtr->m_volume << "%\n";
+
+            // If under observation if there are any changes to the media resource
+            // we call notifyObservors
+            //
+            // For demostration we are changing the volume value and notifying.
+
+            cout << "\nVolume updated to : " << mediaPtr->m_volume << endl;
+            cout << "Notifying observers with resource handle: " << mediaPtr->getHandle() << endl;
+
+            OCStackResult result = OC_STACK_OK;
+
+            if(isListOfObservers)
+            {
+                std::shared_ptr<OCResourceResponse> resourceResponse =
+                            {std::make_shared<OCResourceResponse>()};
+
+                resourceResponse->setErrorCode(200);
+                resourceResponse->setResourceRepresentation(mediaPtr->get(), DEFAULT_INTERFACE);
+
+                result = OCPlatform::notifyListOfObservers(  mediaPtr->getHandle(),
+                                                             mediaPtr->m_interestedObservers,
+                                                             resourceResponse);
+            }
+            else
+            {
+                result = OCPlatform::notifyAllObservers(mediaPtr->getHandle());
+            }
+
+            if(OC_STACK_NO_OBSERVERS == result)
+            {
+                cout << "No More observers, stopping notifications" << endl;
+                gObservation = 0;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+void * handleSlowResponse (void *param, std::shared_ptr<OCResourceRequest> pRequest)
+{
+    // This function handles slow response case
+    MediaResource* mediaPtr = (MediaResource*) param;
+    // Induce a case for slow response by using sleep
+    cout << "SLOW response" << std::endl;
+    sleep (10);
+
+    auto pResponse = std::make_shared<OC::OCResourceResponse>();
+    pResponse->setRequestHandle(pRequest->getRequestHandle());
+    pResponse->setResourceHandle(pRequest->getResourceHandle());
+    pResponse->setResourceRepresentation(mediaPtr->get());
+    pResponse->setErrorCode(200);
+    pResponse->setResponseResult(OC_EH_OK);
+
+    // Set the slow response flag back to false
+    isSlowResponse = false;
+    OCPlatform::sendResponse(pResponse);
+    return NULL;
+}
+
+void PrintUsage()
+{
+    cout << std::endl;
+    cout << "Usage : mediaserver <value>\n";
+    cout << "    Default - Non-secure resource and notify all observers\n";
+    cout << "    1 - Non-secure resource and notify list of observers\n\n";
+    cout << "    2 - Secure resource and notify all observers\n";
+    cout << "    3 - Secure resource and notify list of observers\n\n";
+    cout << "    4 - Non-secure resource, GET slow response, notify all observers\n";
+}
+
+static FILE* client_open(const char* /*path*/, const char *mode)
+{
+    return fopen("./oic_svr_db_server.json", mode);
+}
+
+void playPause()
+{
+    INPUT ip;
+
+    // Set up a generic keyboard event.
+    ip.type = INPUT_KEYBOARD;
+    ip.ki.wScan = 0; // hardware scan code for key
+    ip.ki.time = 0;
+    ip.ki.dwExtraInfo = 0;
+    ip.ki.wVk = VK_MEDIA_PLAY_PAUSE; // virtual-key code for the "a" key
+    ip.ki.dwFlags = 0; // 0 for key press
+
+    SendInput(1, &ip, sizeof(INPUT));
+    // Release the "Play/Pause" key
+    ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
+    SendInput(1, &ip, sizeof(INPUT));
+}
+
+int getVolume()
+{
+    IAudioEndpointVolume *g_pEndptVol = NULL;
+    HRESULT hr = S_OK;
+    IMMDeviceEnumerator *pEnumerator = NULL;
+    IMMDevice *pDevice = NULL;
+    OSVERSIONINFO VersionInfo;
+
+    ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO));
+    VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&VersionInfo);
+    CoInitialize(NULL);
+
+    // Get enumerator for audio endpoint devices.
+    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
+                          NULL, CLSCTX_INPROC_SERVER,
+                          __uuidof(IMMDeviceEnumerator),
+                          (void**)&pEnumerator);
+
+    // Get default audio-rendering device.
+    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
+
+    hr = pDevice->Activate(__uuidof(IAudioEndpointVolume),
+                           CLSCTX_ALL, NULL, (void**)&g_pEndptVol);
+    float currentVal;
+    hr = g_pEndptVol->GetMasterVolumeLevelScalar(&currentVal);
+    fflush(stdout); // just in case
+
+    SAFE_RELEASE(pEnumerator)
+    SAFE_RELEASE(pDevice)
+    SAFE_RELEASE(g_pEndptVol)
+    CoUninitialize();
+    return ((int) round(100 * currentVal));
+
+}
+
+void setVolume(int vol)
+{
+    IAudioEndpointVolume *g_pEndptVol = NULL;
+    HRESULT hr = S_OK;
+    IMMDeviceEnumerator *pEnumerator = NULL;
+    IMMDevice *pDevice = NULL;
+    OSVERSIONINFO VersionInfo;
+
+    ZeroMemory(&VersionInfo, sizeof(OSVERSIONINFO));
+    VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+    GetVersionEx(&VersionInfo);
+    CoInitialize(NULL);
+
+    // Get enumerator for audio endpoint devices.
+    hr = CoCreateInstance(__uuidof(MMDeviceEnumerator),
+                          NULL, CLSCTX_INPROC_SERVER,
+                          __uuidof(IMMDeviceEnumerator),
+                          (void**)&pEnumerator);
+
+    // Get default audio-rendering device.
+    hr = pEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &pDevice);
+
+    hr = pDevice->Activate(__uuidof(IAudioEndpointVolume),
+                           CLSCTX_ALL, NULL, (void**)&g_pEndptVol);
+    float got = (float)vol/100.0; // needs to be within 1.0 to 0.0
+    hr = g_pEndptVol->SetMasterVolumeLevelScalar(got, NULL);
+    fflush(stdout); // just in case
+
+    SAFE_RELEASE(pEnumerator)
+    SAFE_RELEASE(pDevice)
+    SAFE_RELEASE(g_pEndptVol)
+    CoUninitialize();
+}
+
+int main(int argc, char* argv[])
+{
+    OCPersistentStorage ps {client_open, fread, fwrite, fclose, unlink };
+
+    if (argc == 1)
+    {
+        isListOfObservers = false;
+        isSecure = false;
+    }
+    else if (argc == 2)
+    {
+        int value = atoi(argv[1]);
+        switch (value)
+        {
+            case 1:
+                isListOfObservers = true;
+                isSecure = false;
+                break;
+            case 2:
+                isListOfObservers = false;
+                isSecure = true;
+                break;
+            case 3:
+                isListOfObservers = true;
+                isSecure = true;
+                break;
+            case 4:
+                isSlowResponse = true;
+                break;
+            default:
+                PrintUsage();
+                break;
+       }
+     }
+    else
+    {
+        PrintUsage();
+        return -1;
+    }
+
+    // Create PlatformConfig object
+    PlatformConfig cfg {
+        OC::ServiceType::InProc,
+        OC::ModeType::Server,
+        "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
+        0,         // Uses randomly available port
+        OC::QualityOfService::LowQos,
+        &ps
+    };
+
+    OCPlatform::Configure(cfg);
+    try
+    {
+        // Create the instance of the resource class
+        // (in this case instance of class 'MediaResource').
+        MediaResource myMedia;
+
+        // Invoke createResource function of class media.
+        myMedia.createResource();
+        cout << "Created resource." << std::endl;
+
+        // A condition variable will free the mutex it is given, then do a non-
+        // intensive block until 'notify' is called on it.  In this case, since we
+        // don't ever call cv.notify, this should be a non-processor intensive version
+        // of while(true);
+        std::mutex blocker;
+        std::condition_variable cv;
+        std::unique_lock<std::mutex> lock(blocker);
+        cout <<"Waiting" << std::endl;
+        cv.wait(lock, []{return false;});
+    }
+    catch(OCException &e)
+    {
+        cout << "OCException in main : " << e.what() << endl;
+    }
+
+    // No explicit call to stop the platform.
+    // When OCPlatform::destructor is invoked, internally we do platform cleanup
+
+    return 0;
+}
+
diff --git a/resource/examples/winuiclient.cpp b/resource/examples/winuiclient.cpp
new file mode 100644 (file)
index 0000000..59e5d21
--- /dev/null
@@ -0,0 +1,439 @@
+/* ****************************************************************\r
+ *\r
+ * Copyright 2016 Intel Corporation All Rights Reserved.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ *\r
+ ******************************************************************/\r
+\r
+#include <string>\r
+#include "winuiclient.h"\r
+#include <Windows.h>\r
+#include <Commctrl.h>\r
+#include <functional>\r
+\r
+extern int g_CurSliderVal;\r
+extern HWND hwndVolumeSlider, hwndVolumeExpectedLabel;\r
+using namespace WinUIClient;\r
+void LabelPrintf (HWND hwndEdit, TCHAR * szFormat, ...);\r
+\r
+WinUIClientApp::WinUIClientApp(OCPersistentStorage ps)\r
+    : persistentStorage(ps),\r
+      OBSERVE_TYPE_TO_USE(ObserveType::Observe)\r
+{\r
+\r
+}\r
+\r
+WinUIClientApp::~WinUIClientApp()\r
+{\r
+\r
+}\r
+\r
+void WinUIClientApp::Initialize()\r
+{\r
+    // Create PlatformConfig object\r
+    PlatformConfig cfg {\r
+        OC::ServiceType::InProc,\r
+        OC::ModeType::Both,\r
+        "0.0.0.0",\r
+        0,\r
+        OC::QualityOfService::LowQos,\r
+        &persistentStorage\r
+    };\r
+\r
+    OCPlatform::Configure(cfg);\r
+}\r
+\r
+void WinUIClientApp::Run()\r
+{\r
+    try\r
+    {\r
+        // makes it so that all boolean values are printed as 'true/false' in this stream\r
+        std::cout.setf(std::ios::boolalpha);\r
+        // Find all resources\r
+        std::ostringstream requestURI;// << "?rt=core.media";\r
+        std::string s = OC_RSRVD_WELL_KNOWN_URI;\r
+        requestURI << s;\r
+\r
+        OCPlatform::findResource("", requestURI.str(),\r
+                CT_DEFAULT, std::bind(&WinUIClientApp::foundResource, this, std::placeholders::_1));\r
+        std::cout<< "Finding Resource... " <<std::endl;\r
+\r
+        // Find resource is done twice so that we discover the original resources a second time.\r
+        // These resources will have the same uniqueidentifier (yet be different objects), so that\r
+        // we can verify/show the duplicate-checking code in foundResource(above);\r
+        OCPlatform::findResource("", requestURI.str(),\r
+                CT_DEFAULT, std::bind(&WinUIClientApp::foundResource, this, std::placeholders::_1));\r
+        std::cout<< "Finding Resource for second time..." << std::endl;\r
+\r
+    }catch(OCException& e)\r
+    {\r
+        std::cerr << "Exception in main: "<<e.what();\r
+    }\r
+}\r
+\r
+void WinUIClientApp::FindResources()\r
+{\r
+    std::ostringstream requestURI;\r
+    requestURI << OC_RSRVD_WELL_KNOWN_URI;// << "?rt=core.media";\r
+    OCPlatform::findResource("", requestURI.str(),\r
+                            CT_DEFAULT, std::bind(&WinUIClientApp::foundResource, this, std::placeholders::_1));\r
+}\r
+\r
+\r
+// Callback to found resources\r
+void WinUIClientApp::foundResource(std::shared_ptr<OCResource> resource)\r
+{\r
+    std::cout << "In foundResource\n";\r
+    std::string resourceURI;\r
+    std::string hostAddress;\r
+    try\r
+    {\r
+        {\r
+            std::lock_guard<std::mutex> lock(curResourceLock);\r
+            if (discoveredResources.find(resource->uniqueIdentifier()) == discoveredResources.end())\r
+            {\r
+                std::cout << "Found resource " << resource->uniqueIdentifier() <<\r
+                    " for the first time on server with ID: "<< resource->sid()<<std::endl;\r
+                discoveredResources[resource->uniqueIdentifier()] = resource;\r
+            }\r
+            else\r
+            {\r
+                std::cout<<"Found resource "<< resource->uniqueIdentifier() << " again!"<<std::endl;\r
+            }\r
+\r
+            if (curResource)\r
+            {\r
+                std::cout << "Found another resource, ignoring"<<std::endl;\r
+                return;\r
+            }\r
+        }\r
+\r
+        // Do some operations with resource object.\r
+        if (resource)\r
+        {\r
+            std::cout<<"DISCOVERED Resource:"<<std::endl;\r
+            // Get the resource URI\r
+            resourceURI = resource->uri();\r
+            std::cout << "\tURI of the resource: " << resourceURI << std::endl;\r
+\r
+            // Get the resource host address\r
+            hostAddress = resource->host();\r
+            std::cout << "\tHost address of the resource: " << hostAddress << std::endl;\r
+\r
+            // Get the resource types\r
+            std::cout << "\tList of resource types: " << std::endl;\r
+            for(auto &resourceTypes : resource->getResourceTypes())\r
+            {\r
+                std::cout << "\t\t" << resourceTypes << std::endl;\r
+            }\r
+\r
+            // Get the resource interfaces\r
+            std::cout << "\tList of resource interfaces: " << std::endl;\r
+            for(auto &resourceInterfaces : resource->getResourceInterfaces())\r
+            {\r
+                std::cout << "\t\t" << resourceInterfaces << std::endl;\r
+            }\r
+\r
+            if (resourceURI == "/a/media")\r
+            {\r
+                curResource = resource;\r
+                // Call a local function which will internally invoke get API on the resource pointer\r
+                this->GetMediaRepresentation();\r
+                this->BeginObserving();\r
+            }\r
+        }\r
+        else\r
+        {\r
+            // Resource is invalid\r
+            std::cout << "Resource is invalid" << std::endl;\r
+        }\r
+\r
+    }\r
+    catch(std::exception& e)\r
+    {\r
+        std::cerr << "Exception in foundResource: "<< e.what() << std::endl;\r
+    }\r
+}\r
+\r
+// Local function to get representation of media resource\r
+void WinUIClientApp::GetMediaRepresentation()\r
+{\r
+    if (curResource)\r
+    {\r
+        std::cout << "Getting Media Representation..."<<std::endl;\r
+        // Invoke resource's get API with the callback parameter\r
+\r
+        QueryParamsMap test;\r
+        curResource->get(test, std::bind(&WinUIClientApp::onGet, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));\r
+\r
+    }\r
+    else\r
+    {\r
+        std::cout << "No Current Resource to GetMediaRepresentation..."<<std::endl;\r
+    }\r
+}\r
+\r
+// Callback handler on GET request\r
+void WinUIClientApp::onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)\r
+{\r
+    try\r
+    {\r
+        if (eCode == OC_STACK_OK)\r
+        {\r
+            std::cout << "GET request was successful" << std::endl;\r
+            std::cout << "Resource URI: " << rep.getUri() << std::endl;\r
+\r
+            rep.getValue("state", mymedia.m_state);\r
+            rep.getValue("volume", mymedia.m_volume);\r
+            rep.getValue("name", mymedia.m_name);\r
+\r
+            std::cout << "\tstate: " << mymedia.m_state << std::endl;\r
+            std::cout << "\tvolume: " << mymedia.m_volume << std::endl;\r
+            std::cout << "\tname: " << mymedia.m_name << std::endl;\r
+\r
+            g_CurSliderVal = mymedia.m_volume;\r
+            SendMessage(hwndVolumeSlider, TBM_SETPOS, TRUE, g_CurSliderVal);\r
+            LabelPrintf(hwndVolumeExpectedLabel,"Volume: %i", g_CurSliderVal);\r
+\r
+        }\r
+        else\r
+        {\r
+            std::cout << "onGET Response error: " << eCode << std::endl;\r
+            std::exit(-1);\r
+        }\r
+    }\r
+    catch(std::exception& e)\r
+    {\r
+        std::cout << "Exception: " << e.what() << " in onGet" << std::endl;\r
+    }\r
+}\r
+\r
+// Local function to put a different state for this resource\r
+void WinUIClientApp::PutMediaRepresentation()\r
+{\r
+    if (curResource)\r
+    {\r
+        OCRepresentation rep;\r
+\r
+        std::cout << "Putting media representation..."<<std::endl;\r
+\r
+        rep.setValue("state", mymedia.m_state);\r
+        rep.setValue("volume", mymedia.m_volume);\r
+\r
+        // Invoke resource's put API with rep, query map and the callback parameter\r
+        curResource->put(rep, QueryParamsMap(), std::bind(&WinUIClientApp::onPut, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));\r
+    }\r
+}\r
+\r
+// callback handler on PUT request\r
+void WinUIClientApp::onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode)\r
+{\r
+    try\r
+    {\r
+        if (eCode == OC_STACK_OK)\r
+        {\r
+            std::cout << "PUT request was successful" << std::endl;\r
+\r
+            rep.getValue("state", mymedia.m_state);\r
+            rep.getValue("volume", mymedia.m_volume);\r
+            rep.getValue("name", mymedia.m_name);\r
+\r
+            std::cout << "\tstate: " << mymedia.m_state << std::endl;\r
+            std::cout << "\tvolume: " << mymedia.m_volume << std::endl;\r
+            std::cout << "\tname: " << mymedia.m_name << std::endl;\r
+\r
+        }\r
+        else\r
+        {\r
+            std::cout << "onPut Response error: " << eCode << std::endl;\r
+            std::exit(-1);\r
+        }\r
+    }\r
+    catch(std::exception& e)\r
+    {\r
+        std::cout << "Exception: " << e.what() << " in onPut" << std::endl;\r
+    }\r
+}\r
+\r
+// Local function to put a different state for this resource\r
+void WinUIClientApp::PostMediaRepresentation()\r
+{\r
+    if (curResource)\r
+    {\r
+        OCRepresentation rep;\r
+\r
+        std::cout << "Posting media representation..."<<std::endl;\r
+\r
+        rep.setValue("state", mymedia.m_state);\r
+        rep.setValue("volume", mymedia.m_volume);\r
+\r
+        // Invoke resource's post API with rep, query map and the callback parameter\r
+        curResource->post(rep, QueryParamsMap(), std::bind(&WinUIClientApp::onPost, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));\r
+    }\r
+}\r
+\r
+void WinUIClientApp::onPost(const HeaderOptions& /*headerOptions*/,\r
+        const OCRepresentation& rep, const int eCode)\r
+{\r
+    try\r
+    {\r
+        if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)\r
+        {\r
+            std::cout << "POST request was successful" << std::endl;\r
+\r
+            if (rep.hasAttribute("createduri"))\r
+            {\r
+                std::cout << "\tUri of the created resource: "\r
+                    << rep.getValue<std::string>("createduri") << std::endl;\r
+            }\r
+            else\r
+            {\r
+                rep.getValue("state", mymedia.m_state);\r
+                rep.getValue("volume", mymedia.m_volume);\r
+                rep.getValue("name", mymedia.m_name);\r
+\r
+                std::cout << "\tstate: " << mymedia.m_state << std::endl;\r
+                std::cout << "\tvolume: " << mymedia.m_volume << std::endl;\r
+                std::cout << "\tname: " << mymedia.m_name << std::endl;\r
+            }\r
+\r
+        }\r
+        else\r
+        {\r
+            std::cout << "onPost Response error: " << eCode << std::endl;\r
+            std::exit(-1);\r
+        }\r
+    }\r
+    catch (std::exception& e)\r
+    {\r
+        std::cout << "Exception: " << e.what() << " in onPost" << std::endl;\r
+    }\r
+}\r
+\r
+void WinUIClientApp::onPost2(const HeaderOptions& /*headerOptions*/,\r
+        const OCRepresentation& rep, const int eCode)\r
+{\r
+    try\r
+    {\r
+        if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CREATED)\r
+        {\r
+            std::cout << "POST request was successful" << std::endl;\r
+\r
+            if (rep.hasAttribute("createduri"))\r
+            {\r
+                std::cout << "\tUri of the created resource: "\r
+                    << rep.getValue<std::string>("createduri") << std::endl;\r
+            }\r
+            else\r
+            {\r
+                rep.getValue("state", mymedia.m_state);\r
+                rep.getValue("volume", mymedia.m_volume);\r
+                rep.getValue("name", mymedia.m_name);\r
+\r
+                std::cout << "\tstate: " << mymedia.m_state << std::endl;\r
+                std::cout << "\tvolume: " << mymedia.m_volume << std::endl;\r
+                std::cout << "\tname: " << mymedia.m_name << std::endl;\r
+            }\r
+\r
+        }\r
+        else\r
+        {\r
+            std::cout << "onPost2 Response error: " << eCode << std::endl;\r
+            std::exit(-1);\r
+        }\r
+    }\r
+    catch(std::exception& e)\r
+    {\r
+        std::cout << "Exception: " << e.what() << " in onPost2" << std::endl;\r
+    }\r
+\r
+}\r
+\r
+void WinUIClientApp::onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep,\r
+                    const int& eCode, const int& sequenceNumber)\r
+{\r
+    try\r
+    {\r
+        if (eCode == OC_STACK_OK && sequenceNumber != OC_OBSERVE_NO_OPTION)\r
+        {\r
+            if (sequenceNumber == OC_OBSERVE_REGISTER)\r
+            {\r
+                std::cout << "Observe registration action is successful" << std::endl;\r
+            }\r
+            else if (sequenceNumber == OC_OBSERVE_DEREGISTER)\r
+            {\r
+                std::cout << "Observe De-registration action is successful" << std::endl;\r
+            }\r
+\r
+            std::cout << "OBSERVE RESULT:"<<std::endl;\r
+            std::cout << "\tSequenceNumber: "<< sequenceNumber << std::endl;\r
+            rep.getValue("state", mymedia.m_state);\r
+            rep.getValue("volume", mymedia.m_volume);\r
+            rep.getValue("name", mymedia.m_name);\r
+\r
+            std::cout << "\tstate: " << mymedia.m_state << std::endl;\r
+            std::cout << "\tvolume: " << mymedia.m_volume << std::endl;\r
+            std::cout << "\tname: " << mymedia.m_name << std::endl;\r
+\r
+            g_CurSliderVal = mymedia.m_volume;\r
+            SendMessage(hwndVolumeSlider, TBM_SETPOS, TRUE, g_CurSliderVal);\r
+            LabelPrintf(hwndVolumeExpectedLabel,"Volume: %i", g_CurSliderVal);\r
+        }\r
+        else\r
+        {\r
+            if (sequenceNumber == OC_OBSERVE_NO_OPTION)\r
+            {\r
+                std::cout << "Observe registration or de-registration action is failed" << std::endl;\r
+            }\r
+            else\r
+            {\r
+                std::cout << "onObserve Response error: " << eCode << std::endl;\r
+                std::exit(-1);\r
+            }\r
+        }\r
+    }\r
+    catch (std::exception& e)\r
+    {\r
+        std::cout << "Exception: " << e.what() << " in onObserve" << std::endl;\r
+    }\r
+\r
+}\r
+\r
+void WinUIClientApp::BeginObserving()\r
+{\r
+    if (OBSERVE_TYPE_TO_USE == ObserveType::Observe)\r
+        std::cout << std::endl << "Observe is used." << std::endl << std::endl;\r
+    else if (OBSERVE_TYPE_TO_USE == ObserveType::ObserveAll)\r
+        std::cout << std::endl << "ObserveAll is used." << std::endl << std::endl;\r
+\r
+    curResource->observe(OBSERVE_TYPE_TO_USE, QueryParamsMap(), std::bind(&WinUIClientApp::onObserve, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));\r
+}\r
+\r
+void WinUIClientApp::CancelObserving()\r
+{\r
+    std::cout<<"Cancelling Observe..."<<std::endl;\r
+    OCStackResult result = curResource->cancelObserve();\r
+}\r
+\r
+std::shared_ptr<OCResource> WinUIClientApp::GetResource()\r
+{\r
+    return curResource;\r
+}\r
+\r
+int WinUIClientApp::observe_count()\r
+{\r
+    static int oc = 0;\r
+    return ++oc;\r
+}\r
+\r
diff --git a/resource/examples/winuiclient.h b/resource/examples/winuiclient.h
new file mode 100644 (file)
index 0000000..b052e4e
--- /dev/null
@@ -0,0 +1,89 @@
+/* ****************************************************************
+ *
+ * Copyright 2016 Intel Corporation All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#ifndef WINUICLIENT_H_
+#define WINUICLIENT_H_
+
+#include <memory>
+#include <mutex>
+#include <map>
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCResource.h"
+
+using namespace OC;
+namespace WinUIClient{
+
+    class Media
+    {
+        public:
+
+            bool m_state;
+            int m_volume;
+            std::string m_name;
+
+            Media() : m_state(false), m_volume(0), m_name("")
+            {
+            }
+    };
+
+    class WinUIClientApp
+    {
+        public:
+            WinUIClientApp(OCPersistentStorage ps);
+            ~WinUIClientApp();
+
+            void Initialize();
+            void Run();
+            void FindResources();
+            void GetMediaRepresentation();
+            void PutMediaRepresentation();
+            void PostMediaRepresentation();
+            void BeginObserving();
+            void CancelObserving();
+
+            std::shared_ptr<OCResource> GetResource();
+            Media GetMedia(){return mymedia;}
+            void SetMedia(bool state, int volume){mymedia.m_state = state; mymedia.m_volume=volume;}
+            bool observing;
+
+        private:
+            void foundResource(std::shared_ptr<OCResource> resource);
+            void onGet(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode);
+            void onPut(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode);
+            void onPost(const HeaderOptions& /*headerOptions*/, const OCRepresentation& rep, const int eCode);
+            void onPost2(const HeaderOptions& /*headerOptions*/,const OCRepresentation& rep, const int eCode);
+            void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation& rep, const int& eCode, const int& sequenceNumber);
+        private:
+            int observe_count();
+
+        private:
+            typedef std::map<OCResourceIdentifier, std::shared_ptr<OCResource>> DiscoveredResourceMap;
+
+            OCPersistentStorage persistentStorage;
+            Media mymedia;
+            DiscoveredResourceMap discoveredResources;
+            std::shared_ptr<OCResource> curResource;
+            ObserveType OBSERVE_TYPE_TO_USE;
+            std::mutex curResourceLock;
+    };
+
+}
+
+#endif
+
diff --git a/resource/examples/winuiclientgui.cpp b/resource/examples/winuiclientgui.cpp
new file mode 100644 (file)
index 0000000..c8273a8
--- /dev/null
@@ -0,0 +1,368 @@
+/* ****************************************************************
+ *
+ * Copyright 2016 Intel Corporation All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************/
+
+#include <string>
+#include "winuiclient.h"
+
+#include <Windows.h>
+#include <Commctrl.h>
+
+#define ID_TRACKBAR             0x50505
+#define ID_BUTTONPLAYPAUSE      0xFFF0
+#define ID_BUTTONFIND           0xFFF1
+#define ID_BUTTONGET            0xFFF2
+#define ID_BUTTONPUT            0xFFF3
+#define ID_BUTTONPOST           0xFFF4
+#define ID_BUTTONBEGINOBSERVE   0xFFF5
+#define ID_BUTTONCANCELOBSERVE  0xFFF6
+
+int g_CurSliderVal = 0;
+
+HWND hwnd, icon_button, hwndVolumeSlider, hwndVolumeExpectedLabel;
+HWND hwndButtonPlayPause, hwndButtonFind, hwndButtonGet, hwndButtonPut, hwndButtonPost, hwndButtonBeginObserve, hwndButtonCancelObserve;
+HINSTANCE hInstance, g_hinstTrackBar, g_hinstVolumeSlider, g_hinstVolumeLabel;
+HANDLE Timer, Thread;
+HICON hIcon1;
+HBRUSH g_BkgndBrush;
+
+WinUIClient::WinUIClientApp* app = NULL;
+
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+void LabelPrintf (HWND hwndEdit, TCHAR * szFormat, ...);
+HWND WINAPI CreateTrackbar(HWND parent, int x, int y, int w, int h,UINT iMin, UINT iMax, UINT iSelMin, UINT iSelMax);
+HWND WINAPI CreateLabel(HWND parent, LPCTSTR lpText, int x, int y, int w, int h);
+HWND WINAPI CreateButton(HWND parent, UINT_PTR id, LPCTSTR caption, int x, int y, int w, int h);
+
+FILE* client_open(const char* /*path*/, const char *mode)
+{
+    return fopen("./oic_svr_db_client.dat", mode);
+}
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
+            LPSTR lpCmdLine, int nCmdShow )
+{
+    MSG msg;
+    WNDCLASS wc = {sizeof(WNDCLASS)};
+    wc.lpszClassName = TEXT( "Static Control" );
+    wc.hInstance     = hInstance ;
+    wc.hbrBackground = GetSysColorBrush(COLOR_MENU);
+    wc.lpfnWndProc   = WndProc;
+    wc.hIcon         = LoadIcon (NULL, IDI_APPLICATION);
+    wc.hCursor = LoadCursor (NULL, IDC_ARROW);
+
+    RegisterClass(&wc);
+    hwnd = CreateWindow( wc.lpszClassName, TEXT("IoTivity Media Client - Windows UI"),
+                   WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
+                   100, 100, 275, 170, 0, 0, hInstance, 0);
+
+    InitCommonControls(); // loads common control's DLL
+
+    hwndVolumeSlider =
+             CreateTrackbar(hwnd,
+                            10,10,
+                            170,40,
+                            0,100,
+                            0,0);
+    hwndVolumeExpectedLabel =
+                CreateLabel(hwnd,
+                            "Expected Volume",
+                            10,50,
+                            240,30);
+
+    LabelPrintf(hwndVolumeExpectedLabel,
+                "Expected Volume: %i",
+                0);
+
+    hwndButtonPlayPause =
+                CreateButton(hwnd,
+                             ID_BUTTONPLAYPAUSE,
+                             "PlayPause",
+                             180,10,
+                             80,35);
+
+    hwndButtonFind =
+                CreateButton(hwnd,
+                             ID_BUTTONFIND,
+                             "Find",
+                             10,75,
+                             64,25);
+
+    hwndButtonGet =
+                CreateButton(hwnd,
+                             ID_BUTTONGET,
+                             "Get",
+                             10,105,
+                             64,25);
+
+    hwndButtonPut =
+                CreateButton(hwnd,
+                             ID_BUTTONPUT,
+                             "Put",
+                             80,75,
+                             64,25);
+
+    hwndButtonPost =
+                CreateButton(hwnd,
+                             ID_BUTTONPOST,
+                             "Post",
+                             80,105,
+                             64,25);
+    hwndButtonBeginObserve =
+                CreateButton(hwnd,
+                             ID_BUTTONBEGINOBSERVE,
+                             "Bgn Obs",
+                             150,75,
+                             64,25);
+    hwndButtonCancelObserve =
+                CreateButton(hwnd,
+                             ID_BUTTONCANCELOBSERVE,
+                             "Cncl Obs",
+                             150,105,
+                             64,25);
+
+
+    ShowWindow(hwnd, nCmdShow);
+    UpdateWindow(hwnd);
+
+    while (GetMessage(&msg, NULL, 0, 0))
+    {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+    }
+
+    return (int) msg.wParam;
+}
+
+LRESULT
+CALLBACK
+WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+    HDC hDC;
+    RECT rect;
+    WinUIClient::Media myMedia;
+
+    switch(msg){
+      case WM_HSCROLL:
+        switch (LOWORD(wParam)) {
+            case TB_ENDTRACK:
+                g_CurSliderVal = SendMessage(hwndVolumeSlider, TBM_GETPOS, 0, 0);
+                LabelPrintf(hwndVolumeExpectedLabel,"Volume: %i", g_CurSliderVal);
+
+                myMedia = app->GetMedia();
+                myMedia.m_volume = g_CurSliderVal;
+                app->SetMedia(myMedia.m_state, myMedia.m_volume);
+                app->PostMediaRepresentation();
+                break;
+        }
+        break;
+      case WM_CREATE:
+          hIcon1 = LoadIcon (NULL, IDI_WARNING);
+          SendMessage(icon_button,BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon1);
+          GetClientRect(hwnd, &rect);
+          g_BkgndBrush = GetSysColorBrush(COLOR_MENU);
+
+          app = new WinUIClient::WinUIClientApp({client_open, fread, fwrite, fclose, unlink });
+          app->Initialize();
+          app->Run();
+
+          break;
+      case WM_DESTROY:
+
+          delete app;
+
+          PostQuitMessage(0);
+          break;
+      case WM_ERASEBKGND:
+          GetClientRect(hwnd, &rect);
+          hDC = GetDC(hwnd);
+          SelectObject((HDC)wParam, g_BkgndBrush);
+          Rectangle((HDC)hDC, rect.left, rect.top, rect.right, rect.bottom);
+          ReleaseDC(hwnd, hDC);
+          break;
+      case WM_SIZE:
+          break;
+      case WM_RBUTTONDOWN:
+      case WM_LBUTTONDOWN:
+          break;
+      case WM_MOUSELEAVE:
+      case WM_RBUTTONUP:
+      case WM_LBUTTONUP:
+          break;
+      case WM_COMMAND:
+        if (HIWORD(wParam) == BN_CLICKED)
+        {
+
+            switch (LOWORD(wParam))
+            {
+                case ID_BUTTONPLAYPAUSE:
+                    myMedia = app->GetMedia();
+
+                    // HACK: We are using m_state in a stateless way.
+                    // True means "toggle".  The server does not have state
+                    // knowledge about whether or not media is playing on the
+                    // system.  It's dumb and hits the "PlayPause" key on the
+                    // keyboard.
+                    //
+                    myMedia.m_state = true;
+                    app->SetMedia(myMedia.m_state, myMedia.m_volume);
+                    myMedia.m_state = false;
+
+                    app->PutMediaRepresentation();
+                    break;
+                case ID_BUTTONFIND:
+                    app->FindResources();
+                    break;
+                case ID_BUTTONGET:
+                    app->GetMediaRepresentation();
+                    break;
+                case ID_BUTTONPUT:
+                    myMedia = app->GetMedia();
+                    myMedia.m_volume = g_CurSliderVal;
+                    app->SetMedia(myMedia.m_state, myMedia.m_volume);
+                    app->PutMediaRepresentation();
+                    break;
+                case ID_BUTTONPOST:
+                    myMedia = app->GetMedia();
+                    myMedia.m_volume = g_CurSliderVal;
+                    app->SetMedia(myMedia.m_state, myMedia.m_volume);
+                    app->PostMediaRepresentation();
+                    break;
+                case ID_BUTTONBEGINOBSERVE:
+                    app->BeginObserving();
+                    break;
+                case ID_BUTTONCANCELOBSERVE:
+                    app->CancelObserving();
+                    break;
+            }
+        }
+        break;
+      default:
+          return DefWindowProc(hwnd, msg, wParam, lParam);
+    }
+
+    return 0;
+}
+
+#define GWL_HINSTANCE -6
+HWND WINAPI CreateButton(HWND parent,
+                            UINT_PTR id,
+                            LPCTSTR caption    ,
+                            int x,
+                            int y,
+                            int w,
+                            int h
+                            )
+{
+    HWND hwndButton = CreateWindow(
+        "BUTTON",  // Predefined class; Unicode assumed
+        caption,      // Button text
+        WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles
+        x,         // x position
+        y,         // y position
+        w,        // Button width
+        h,        // Button height
+        parent,     // Parent window
+        (HMENU)id,       // No menu.
+        (HINSTANCE)GetWindowLongPtr(parent, GWL_HINSTANCE),
+        NULL);      // Pointer not needed.
+
+    return hwndButton;
+}
+
+HWND WINAPI CreateLabel(
+    HWND parent,  // handle of parent window
+    LPCTSTR lpText,
+    int x,
+    int y,
+    int w,
+    int h
+)
+{
+   HWND hwndPowerLabel  = CreateWindow("static", "ST_U",
+                                      WS_CHILD | WS_VISIBLE | WS_TABSTOP,
+                                      x, y, w, h,
+                                      parent, (HMENU)(501),
+                                      (HINSTANCE)GetWindowLongPtr(parent, GWL_HINSTANCE),
+                                      NULL);
+   SetWindowText(hwndPowerLabel, lpText);
+   return hwndPowerLabel;
+}
+
+// CreateTrackbar - creates and initializes a trackbar.
+//
+// Global variable
+//     g_hinstTrackBar - instance handle
+//
+HWND WINAPI CreateTrackbar(
+    HWND parent,  // handle of dialog box (parent window)
+    int x,
+    int y,
+    int w,
+    int h,
+    UINT iMin,     // minimum value in trackbar range
+    UINT iMax,     // maximum value in trackbar range
+    UINT iSelMin,  // minimum value in trackbar selection
+    UINT iSelMax)  // maximum value in trackbar selection
+{
+    HWND hwndVolumeSlider = CreateWindowEx(
+        0,                              // no extended styles
+        TRACKBAR_CLASS,                 // class name
+        "Trackbar Control",             // title (caption)
+        WS_CHILD |
+        WS_VISIBLE |
+        TBS_AUTOTICKS |
+        TBS_ENABLESELRANGE,             // style
+        x,y,w,h,                        // position ,size
+        parent,                        // parent window
+        (HMENU)ID_TRACKBAR,             // control identifier
+        (HINSTANCE)GetWindowLongPtr(parent, GWL_HINSTANCE),// instance
+        NULL                            // no WM_CREATE parameter
+        );
+
+    SendMessage(hwndVolumeSlider, TBM_SETRANGE,
+        (WPARAM) TRUE,                  // redraw flag
+        (LPARAM) MAKELONG(iMin, iMax)); // min. & max. positions
+
+    SendMessage(hwndVolumeSlider, TBM_SETPAGESIZE,
+        0, (LPARAM) 4);                 // new page size
+
+    SendMessage(hwndVolumeSlider, TBM_SETSEL,
+        (WPARAM) FALSE,                 // redraw flag
+        (LPARAM) MAKELONG(iSelMin, iSelMax));
+
+    SendMessage(hwndVolumeSlider, TBM_SETPOS,
+        (WPARAM) TRUE,                  // redraw flag
+        (LPARAM) iSelMin);
+
+    SetFocus(hwndVolumeSlider);
+
+    return hwndVolumeSlider;
+}
+
+void LabelPrintf (HWND hwndEdit, TCHAR * szFormat, ...)
+{
+     TCHAR   szBuffer [1024] ;
+     va_list pArgList ;
+
+     va_start (pArgList, szFormat) ;
+     wvsprintf (szBuffer, szFormat, pArgList) ;
+     va_end (pArgList) ;
+
+     SetWindowText(hwndEdit, szBuffer);
+}
+