Example #1
0
/**************************************************************************
 * 				wodPlayer_Reset			[internal]
 *
 * wodPlayer helper. Resets current output stream.
 */
static	void	wodPlayer_Reset(WINE_WAVEOUT* wwo, BOOL reset)
{
    wodUpdatePlayedTotal(wwo);
    wodPlayer_NotifyCompletions(wwo, FALSE); /* updates current notify list */

    /* we aren't able to flush any data that has already been written */
    /* to nas, otherwise we would do the flushing here */

    nas_free(wwo);

    if (reset) {
        enum win_wm_message     msg;
        DWORD_PTR               param;
        HANDLE                  ev;

	/* remove any buffer */
	wodPlayer_NotifyCompletions(wwo, TRUE);

	wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
	wwo->state = WINE_WS_STOPPED;
	wwo->PlayedTotal = wwo->WrittenTotal = 0;

        /* remove any existing message in the ring */
        EnterCriticalSection(&wwo->msgRing.msg_crst);

        /* return all pending headers in queue */
        while (NAS_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev))
        {
	    TRACE("flushing msg\n");
            if (msg != WINE_WM_HEADER)
            {
                FIXME("shouldn't have headers left\n");
                SetEvent(ev);
                continue;
            }
            ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
            ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;

            wodNotifyClient(wwo, WOM_DONE, param, 0);
        }
        ResetEvent(wwo->msgRing.msg_event);
        LeaveCriticalSection(&wwo->msgRing.msg_crst);
    } else {
        if (wwo->lpLoopPtr) {
            /* complicated case, not handled yet (could imply modifying the loop counter */
            FIXME("Pausing while in loop isn't correctly handled yet, expec strange results\n");
            wwo->lpPlayPtr = wwo->lpLoopPtr;
            wwo->WrittenTotal = wwo->PlayedTotal; /* this is wrong !!! */
        } else {
	    /* the data already written is going to be played, so take */
	    /* this fact into account here */
	    wwo->PlayedTotal = wwo->WrittenTotal;
        }
	wwo->state = WINE_WS_PAUSED;
    }
}
Example #2
0
/**************************************************************************
 * 				wodPlayer			[internal]
 */
static	DWORD	CALLBACK	wodPlayer(LPVOID pmt)
{
    WORD       uDevID = (DWORD_PTR)pmt;
    WINE_WAVEOUT* wwo = &WOutDev[uDevID];

    wwo->state = WINE_WS_STOPPED;
    SetEvent(wwo->hStartUpEvent);

    for (;;) {

        if (wwo->FlowStarted) {
           AuHandleEvents(wwo->AuServ);

           if (wwo->state == WINE_WS_PLAYING && wwo->freeBytes && wwo->BufferUsed)
              nas_send_buffer(wwo);
        }

        if (wwo->BufferUsed <= FRAG_SIZE && wwo->writeBytes > 0)
           wodPlayer_NotifyCompletions(wwo, FALSE);

        WaitForSingleObject(wwo->msgRing.msg_event, 20);
        wodPlayer_ProcessMessages(wwo);

        while(wwo->lpPlayPtr) {
           wwo->lpPlayPtr->reserved = wwo->WrittenTotal + wwo->lpPlayPtr->dwBufferLength;
           nas_add_buffer(wwo);
           wodPlayer_PlayPtrNext(wwo);
        }
    return 0;
    }
}
Example #3
0
/**************************************************************************
 * 				wodPlayer			[internal]
 */
static	DWORD	CALLBACK	wodPlayer(LPVOID pmt)
{
    WORD	  uDevID = (DWORD_PTR)pmt;
    WINE_WAVEDEV* wwo = &WOutDev[uDevID];
    DWORD         dwNextFeedTime = INFINITE;   /* Time before DSP needs feeding */
    DWORD         dwNextNotifyTime = INFINITE; /* Time before next wave completion */
    DWORD         dwSleepTime;

    wwo->state = WINE_WS_STOPPED;
    SetEvent(wwo->hStartUpEvent);

    for (;;) {
        /** Wait for the shortest time before an action is required.  If there
         *  are no pending actions, wait forever for a command.
         */
        dwSleepTime = min(dwNextFeedTime, dwNextNotifyTime);
        TRACE("waiting %ums (%u,%u)\n", dwSleepTime, dwNextFeedTime, dwNextNotifyTime);
        ALSA_WaitRingMessage(&wwo->msgRing, dwSleepTime);
	wodPlayer_ProcessMessages(wwo);
	if (wwo->state == WINE_WS_PLAYING) {
	    dwNextFeedTime = wodPlayer_FeedDSP(wwo);
	    dwNextNotifyTime = wodPlayer_NotifyCompletions(wwo, FALSE);
	    if (dwNextFeedTime == INFINITE) {
		/* FeedDSP ran out of data, but before giving up, */
		/* check that a notification didn't give us more */
		wodPlayer_ProcessMessages(wwo);
		if (wwo->lpPlayPtr) {
		    TRACE("recovering\n");
		    dwNextFeedTime = wodPlayer_FeedDSP(wwo);
		}
	    }
	} else {
	    dwNextFeedTime = dwNextNotifyTime = INFINITE;
	}
    }
    return 0;
}
Example #4
0
/**************************************************************************
 * 				wodPlayer_Reset			[internal]
 *
 * wodPlayer helper. Resets current output stream.
 */
static	void	wodPlayer_Reset(WINE_WAVEDEV* wwo, BOOL reset)
{
    int                         err;
    TRACE("(%p)\n", wwo);

    wodUpdatePlayedTotal(wwo, NULL);
    /* updates current notify list */
    wodPlayer_NotifyCompletions(wwo, FALSE);

    if ( (err = snd_pcm_drop(wwo->pcm)) < 0) {
	FIXME("flush: %s\n", snd_strerror(err));
	wwo->hThread = 0;
	wwo->state = WINE_WS_STOPPED;
	ExitThread(-1);
    }
    if ( (err = snd_pcm_prepare(wwo->pcm)) < 0 )
        ERR("pcm prepare failed: %s\n", snd_strerror(err));

    if (reset) {
        enum win_wm_message	msg;
        DWORD_PTR	        param;
        HANDLE		        ev;

        /* remove any buffer */
        wodPlayer_NotifyCompletions(wwo, TRUE);

        wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
        wwo->state = WINE_WS_STOPPED;
        wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
        /* Clear partial wavehdr */
        wwo->dwPartialOffset = 0;

        /* remove any existing message in the ring */
        EnterCriticalSection(&wwo->msgRing.msg_crst);
        /* return all pending headers in queue */
        while (ALSA_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev))
        {
            if (msg != WINE_WM_HEADER)
            {
                FIXME("shouldn't have headers left\n");
                SetEvent(ev);
                continue;
            }
            ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
            ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;

                wodNotifyClient(wwo, WOM_DONE, param, 0);
        }
        ALSA_ResetRingMessage(&wwo->msgRing);
        LeaveCriticalSection(&wwo->msgRing.msg_crst);
    } else {
        if (wwo->lpLoopPtr) {
            /* complicated case, not handled yet (could imply modifying the loop counter */
            FIXME("Pausing while in loop isn't correctly handled yet, expect strange results\n");
            wwo->lpPlayPtr = wwo->lpLoopPtr;
            wwo->dwPartialOffset = 0;
            wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
        } else {
            LPWAVEHDR   ptr;
            DWORD       sz = wwo->dwPartialOffset;

            /* reset all the data as if we had written only up to lpPlayedTotal bytes */
            /* compute the max size playable from lpQueuePtr */
            for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext) {
                sz += ptr->dwBufferLength;
            }
            /* because the reset lpPlayPtr will be lpQueuePtr */
            if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("grin\n");
            wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
            wwo->dwWrittenTotal = wwo->dwPlayedTotal;
            wwo->lpPlayPtr = wwo->lpQueuePtr;
        }
        wwo->state = WINE_WS_PAUSED;
    }
}