⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chipcon remote control.cpp

📁 ti-Chipcon CCxx11 USB + MCU +RF 应用开发源码实例。包括2.0usb,rf,powermodes,clockmodes底层驱动源码。有了这些实例,包括误码率测试等。对你更
💻 CPP
字号:
#include "stdafx.h"
#include "Chipcon Remote Control.h"
#include "WinampGen.h"
#include "WinampIpc.h"

static const GUID WINAMP_REMOTE_GUID = { 0xEFA3F566, 0x6E8C, 0x4CC2, { 0x93, 0xFB, 0x31, 0x3B, 0x1B, 0xA3, 0x4D, 0x9E } };

// Global variables
HANDLE hRemoteControlThread;
HANDLE hRemoteDisplayThread;
HANDLE hDeviceMonitorThread;
CudalPipe *pControlPipe;
CudalPipe *pDisplayPipe;
CudalDongle *pDongle;
BOOL quitAsap;


// Function prototypes
int waInit(void);
void waConfig(void);
void waQuit(void);


winampGeneralPurposePlugin plugin = {
	GPPHDR_VER,
	"Chipcon Remote Control", // Description
	waInit,					  // Initialization function
	waConfig,					  // Configuration function
	waQuit					  // Deinitialization function
};




BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    return TRUE;
}




DWORD WINAPI RemoteDisplayThread(LPVOID lpParameter) {
    WINAMP_DISPLAY_DATA lastWaDispData;
    WINAMP_DISPLAY_DATA waDispData;
    int lastTime = -1;
    BOOL forceRefresh;
    memset(&lastWaDispData, 0x00, sizeof(WINAMP_DISPLAY_DATA));

    // Bail out when Winamp tells us to, or die in sympathy for the other thread
    while (!quitAsap && pControlPipe) {

        // Initialize displayData
        memset(&waDispData, 0x00, sizeof(WINAMP_DISPLAY_DATA));

        // Get output time
        int time = WA_GET_PLAY_TIME();
        if (time != -1) {
            waDispData.milliseconds = time % 1000;
            waDispData.seconds = (time / 1000) % 60;
            waDispData.minutes = time / (1000 * 60);

            // Check output time for changes
            if ((waDispData.milliseconds != lastWaDispData.milliseconds) ||
                (waDispData.seconds != lastWaDispData.seconds) ||
                (waDispData.minutes != lastWaDispData.minutes)) {
                waDispData.refresh |= WDD_REFRESH_TIME_BM;
            }
        }

        // Check the time for significant changes
        if (time < lastTime) {
            forceRefresh = TRUE;
        } else if (time > (lastTime + SIGNIFICANT_TIME_DELTA)) {
            forceRefresh = TRUE;
        } else {
            forceRefresh = FALSE;
        }
        lastTime = time;
        
        // Get play state
        waDispData.state = 0x00;
        if (WA_IS_PLAYING()) {
            waDispData.state |= WDD_STATE_PLAYING_BM;
        } else if (WA_IS_PAUSED()) {
            waDispData.state |= WDD_STATE_PAUSED_BM;
        }

        // Check player state for changes
        if ((waDispData.state & (WDD_STATE_PLAYING_BM | WDD_STATE_PAUSED_BM)) != 
            (lastWaDispData.state & (WDD_STATE_PLAYING_BM | WDD_STATE_PAUSED_BM))) {
            waDispData.refresh |= WDD_REFRESH_PLAY_STATE_BM;
        }

        // Get shuffle state
        if (WA_GET_SHUFFLE()) waDispData.state |= WDD_STATE_SHUFFLE_BM;

        // Check shuffle state for changes
        if ((waDispData.state & WDD_STATE_SHUFFLE_BM) != (lastWaDispData.state & WDD_STATE_SHUFFLE_BM)) {
            waDispData.refresh |= WDD_REFRESH_SHUFFLE_STATE_BM;
        }

        // Get track title
        int titleLength;
        if (WA_GET_LIST_LENGTH()) {
            char *pTitlePtr = WA_GET_LIST_TITLE(WA_GET_LIST_POS());
            memcpy(waDispData.pTitle, pTitlePtr, min(sizeof(waDispData.pTitle), strlen(pTitlePtr)));
            titleLength = strlen(pTitlePtr);
        } else {
            sprintf(waDispData.pTitle, "- No playlist -");
            titleLength = strlen(waDispData.pTitle);
        }

        // Calculate the total length of the display data 
        waDispData.totalLength = sizeof(waDispData) 
                               - sizeof(waDispData.pTitle)
                               + titleLength;

        // Check track title for changes
        if ((waDispData.totalLength != lastWaDispData.totalLength) ||
            (memcmp(waDispData.pTitle, lastWaDispData.pTitle, titleLength) != 0)) {
            waDispData.refresh |= WDD_REFRESH_TITLE_BM;
        }

        // Send it if there are any relevant changes
        if ((waDispData.refresh & (WDD_REFRESH_PLAY_STATE_BM | WDD_REFRESH_SHUFFLE_STATE_BM | WDD_REFRESH_TITLE_BM)) || 
            (forceRefresh)) {

            DWORD length = waDispData.totalLength;
            switch (pDisplayPipe->WriteSync(&waDispData, &length, 100)) {
            case USBIO_ERR_SUCCESS:
            case USBIO_ERR_TIMEOUT:
                // It's only a success if the transferred length is correct
                if (length == waDispData.totalLength) break;
            default:
                // Fatal error (possibly disconnection)
                goto error;
            }
        }

        memcpy(&lastWaDispData, &waDispData, sizeof(WINAMP_DISPLAY_DATA));

        Sleep(DISPLAY_INTERVAL);
    }
error:
    delete pDisplayPipe;
    pDisplayPipe = NULL;    

    return 0;
}




DWORD WINAPI RemoteControlThread(LPVOID lpParameter) {
    WINAMP_CONTROL_DATA controlData;
    CudalAsyncInfo asyncInfo;
    DWORD length;

    // Start polling
    if (!pControlPipe->ReadAsync(&asyncInfo, &controlData, sizeof(WINAMP_CONTROL_DATA))) {
        goto error;
    }

    // Bail out when Winamp tells us to, or die in sympathy for the other thread
    while (!quitAsap && pDisplayPipe) {

        // Did we get anything?
        switch (pControlPipe->WaitAsync(&asyncInfo, &length, 100)) {
        case USBIO_ERR_SUCCESS:

            // Make sure that we got it all...
            if (length == 2) {

                // When a command is received, perform the corresponding action
                switch (controlData.command) {
                case DONGLE_CMD_PREVIOUS_TRACK: WA_CMD_PREVIOUS_TRACK();             break;
                case DONGLE_CMD_PLAY:           WA_CMD_PLAY();                       break;
                case DONGLE_CMD_PAUSE:          WA_CMD_PAUSE();                      break;
                case DONGLE_CMD_STOP:           WA_CMD_STOP();                       break;
                case DONGLE_CMD_NEXT_TRACK:     WA_CMD_NEXT_TRACK();                 break;
                case DONGLE_CMD_VOLUMEUP:       WA_CMD_VOLUMEUP();                   break;
                case DONGLE_CMD_VOLUMEDOWN:     WA_CMD_VOLUMEDOWN();                 break;
                case DONGLE_CMD_FFWD5S:         WA_CMD_FFWD5S();                     break;
                case DONGLE_CMD_REW5S:          WA_CMD_REW5S();                      break;
                case DONGLE_SET_REPEAT:         WA_SET_REPEAT(controlData.value);    break;
                case DONGLE_SET_SHUFFLE:        WA_SET_SHUFFLE(controlData.value);   break;
                case DONGLE_SET_VOLUME:         WA_SET_VOLUME(controlData.value);    break;
                }
            }

            // Continue polling
            if (!pControlPipe->ReadAsync(&asyncInfo, &controlData, sizeof(WINAMP_CONTROL_DATA))) {
                goto error;
            }
            break;

        case USBIO_ERR_TIMEOUT:
            // A timeout does not have any effect
            break;

        default:
            // Fatal error (possibly disconnection)
            goto error;
        }
    }

error:

    // Terminate the transfer
    pControlPipe->AbortAll();
    pControlPipe->WaitAsyncTermination(&asyncInfo);

    // Delete the control pipe to tell the other threads that we're done
    delete pControlPipe;
    pControlPipe = NULL;
    
    return 0;
}




DWORD WINAPI DongleMonitorThread(LPVOID lpParameter) {
    DWORD dummy;
	
    
    // This is sort of the main loop. Leave when the quit signal is given
    while (!quitAsap) {

        // If the pipes don't exist, then try to find a dongle to connect to
        if (!pControlPipe && !pDisplayPipe) {

            // Close the old thread handles
            if (hRemoteControlThread) { 
                CloseHandle(hRemoteControlThread); 
                hRemoteControlThread = NULL; 
            }
            if (hRemoteDisplayThread) { 
                CloseHandle(hRemoteDisplayThread); 
                hRemoteDisplayThread = NULL; 
            }
            
            // Clean up after last rounds
            if (pDongle) { 
                delete pDongle; 
                pDongle = NULL;
            }

            // Find the correct dongle type
            CUDAL_DONGLE_INFO pDongleInfo[MAX_DONGLE_ENUM_COUNT];
            int dongleCount = CudalDongle::EnumDongles(pDongleInfo, MAX_DONGLE_ENUM_COUNT, &WINAMP_REMOTE_GUID);
            for (int n = 0; n < dongleCount; n++) {
                if ((pDongleInfo[n].vendorId == CHIPCON_VID) &&
                    (pDongleInfo[n].productId == WINAMP_REMOTE_CONTROL_PID)) {

                    // If the dongle object could be created, then create the control and display pipes
                    if (pDongle = CudalDongle::CreateDongle(&pDongleInfo[n], 0, &WINAMP_REMOTE_GUID)) {
                        pDisplayPipe = pDongle->CreatePipe(REMOTE_DISPLAY_ENDPOINT, FALSE);
                        pControlPipe = pDongle->CreatePipe(REMOTE_CONTROL_ENDPOINT, TRUE);

                        // When both pipes have been created, the two data transfer threads can be started
                        if (pDisplayPipe && pControlPipe) {
                            hRemoteControlThread = CreateThread(NULL, 0, RemoteControlThread, NULL, 0, &dummy);
                            hRemoteDisplayThread = CreateThread(NULL, 0, RemoteDisplayThread, NULL, 0, &dummy);
							n = dongleCount;//stop searching
                        
                        // If not, then destroy everything
                        } else {
                            if (pDisplayPipe) { delete pDisplayPipe; pDisplayPipe = NULL; }
                            if (pControlPipe) { delete pControlPipe; pControlPipe = NULL; }
                            if (pDongle) { delete pDongle; pDongle = NULL; }
                        }
                    }
                }
            }
        }

        // Reduce activity
        for (int s = 0; s < 10; s++) {
            if (!quitAsap) {
                Sleep(MONITOR_INTERVAL / 10);
            }
        }
    }

    // Wait for the other threads to quit before destroying the dongle object
    if (hRemoteControlThread) {
        WaitForSingleObject(hRemoteControlThread, 5000);
        CloseHandle(hRemoteControlThread);
    }
    if (hRemoteDisplayThread) {
        WaitForSingleObject(hRemoteDisplayThread, 5000);
        CloseHandle(hRemoteDisplayThread);
    }
    if (pDongle) delete pDongle;

    return 0;
}




int waInit(void) {
    DWORD dummy;
    
    // Reset relevant globals
    hRemoteControlThread = 0;
    hRemoteDisplayThread = 0;
    pControlPipe = NULL;
    pDisplayPipe = NULL;
    pDongle = NULL;
    quitAsap = FALSE;

    // Start the monitoring thread, which discovers a dongle and initializes it
    hDeviceMonitorThread = CreateThread(NULL, 0, DongleMonitorThread, NULL, 0, &dummy);
    return 0;
}




void waConfig(void) { 
    MessageBox(plugin.hwndParent, 
               "This plug-in demonstrates the Chipcon USB Dongle Access Library\n"
               "(CUDAL). Download \"winamp_remote.hex\" into a CC2510 on a\n"
               "SmartRF04EB, and \"winamp_dongle.hex\" into the CC2511 dongle.\n"
               "The plug-in will detect and attach to the first unused remote\n"
               "control that it finds. The dongle safely be removed at any time\n"
               "and re-connected later on.", 
               "Chipcon Remote Control",
               MB_OK | MB_ICONINFORMATION);
}




void waQuit(void) {   
    quitAsap = TRUE;
    WaitForSingleObject(hDeviceMonitorThread, INFINITE);
    CloseHandle(hDeviceMonitorThread);
}



extern "C" {
    __declspec(dllexport) winampGeneralPurposePlugin *winampGetGeneralPurposePlugin(void) { 
	    return &plugin;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -