Example #1
0
static PaError BoostPriority( PaUnixThread* self )
{
    PaError result = paNoError;
    struct sched_param spm = { 0 };
    /* Priority should only matter between contending FIFO threads? */
    spm.sched_priority = 1;

    assert( self );

    if( pthread_setschedparam( self->thread, SCHED_FIFO, &spm ) != 0 )
    {
        PA_UNLESS( errno == EPERM, paInternalError );  /* Lack permission to raise priority */
        PA_DEBUG(( "Failed bumping priority\n" ));
        result = 0;
    }
    else
    {
        result = 1; /* Success */
    }
error:
    return result;
}
Example #2
0
static PaError BlockingWriteStream(PaStream* stream, const void *data, unsigned long numFrames)
{
    PaSndioStream *s = (PaSndioStream *)stream;
    unsigned n, res;

    while (numFrames > 0) {
        n = s->par.round;
        if (n > numFrames)
            n = numFrames;
        PaUtil_SetOutputFrameCount(&s->bufferProcessor, n);
        PaUtil_SetInterleavedOutputChannels(&s->bufferProcessor, 0, s->writeBuffer, s->par.pchan);
        res = PaUtil_CopyOutput(&s->bufferProcessor, &data, n);
        if (res != n) {
            PA_DEBUG(("BlockingWriteStream: copyOutput: %u != %u\n"));
            return paUnanticipatedHostError;
        }
        res = sio_write(s->hdl, s->writeBuffer, n * s->par.pchan * s->par.bps);
        if (res == 0)
            return paUnanticipatedHostError;        
        s->bytesWritten += n;
        numFrames -= n;
    }
    return paNoError;
}
Example #3
0
static void *WatchdogFunc( void *userData )
{
    PaError result = paNoError, *pres = NULL;
    int err;
    PaAlsaThreading *th = (PaAlsaThreading *) userData;
    unsigned intervalMsec = 500;
    const PaTime maxSeconds = 3.;   /* Max seconds between callbacks */
    PaTime timeThen = PaUtil_GetTime(), timeNow, timeElapsed, cpuTimeThen, cpuTimeNow, cpuTimeElapsed;
    double cpuLoad, avgCpuLoad = 0.;
    int throttled = 0;

    assert( th );

    /* Execute OnWatchdogExit when exiting */
    pthread_cleanup_push( &OnWatchdogExit, th );

    /* Boost priority of callback thread */
    PA_ENSURE( result = BoostPriority( th ) );
    if( !result )
    {
        /* Boost failed, might as well exit */
        pthread_exit( NULL );
    }

    cpuTimeThen = th->callbackCpuTime;
    {
        int policy;
        struct sched_param spm = { 0 };
        pthread_getschedparam( pthread_self(), &policy, &spm );
        PA_DEBUG(( "%s: Watchdog priority is %d\n", __FUNCTION__, spm.sched_priority ));
    }

    while( 1 )
    {
        double lowpassCoeff = 0.9, lowpassCoeff1 = 0.99999 - lowpassCoeff;
        
        /* Test before and after in case whatever underlying sleep call isn't interrupted by pthread_cancel */
        pthread_testcancel();
        Pa_Sleep( intervalMsec );
        pthread_testcancel();

        if( PaUtil_GetTime() - th->callbackTime > maxSeconds )
        {
            PA_DEBUG(( "Watchdog: Terminating callback thread\n" ));
            /* Tell thread to terminate */
            err = pthread_kill( th->callbackThread, SIGKILL );
            pthread_exit( NULL );
        }

        PA_DEBUG(( "%s: PortAudio reports CPU load: %g\n", __FUNCTION__, PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) ));

        /* Check if we should throttle, or unthrottle :P */
        cpuTimeNow = th->callbackCpuTime;
        cpuTimeElapsed = cpuTimeNow - cpuTimeThen;
        cpuTimeThen = cpuTimeNow;

        timeNow = PaUtil_GetTime();
        timeElapsed = timeNow - timeThen;
        timeThen = timeNow;
        cpuLoad = cpuTimeElapsed / timeElapsed;
        avgCpuLoad = avgCpuLoad * lowpassCoeff + cpuLoad * lowpassCoeff1;
        /*
        if( throttled )
            PA_DEBUG(( "Watchdog: CPU load: %g, %g\n", avgCpuLoad, cpuTimeElapsed ));
            */
        if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) > .925 )
        {
            static int policy;
            static struct sched_param spm = { 0 };
            static const struct sched_param defaultSpm = { 0 };
            PA_DEBUG(( "%s: Throttling audio thread, priority %d\n", __FUNCTION__, spm.sched_priority ));

            pthread_getschedparam( th->callbackThread, &policy, &spm );
            if( !pthread_setschedparam( th->callbackThread, SCHED_OTHER, &defaultSpm ) )
            {
                throttled = 1;
            }
            else
                PA_DEBUG(( "Watchdog: Couldn't lower priority of audio thread: %s\n", strerror( errno ) ));

            /* Give other processes a go, before raising priority again */
            PA_DEBUG(( "%s: Watchdog sleeping for %lu msecs before unthrottling\n", __FUNCTION__, th->throttledSleepTime ));
            Pa_Sleep( th->throttledSleepTime );

            /* Reset callback priority */
            if( pthread_setschedparam( th->callbackThread, SCHED_FIFO, &spm ) != 0 )
            {
                PA_DEBUG(( "%s: Couldn't raise priority of audio thread: %s\n", __FUNCTION__, strerror( errno ) ));
            }

            if( PaUtil_GetCpuLoad( th->cpuLoadMeasurer ) >= .99 )
                intervalMsec = 50;
            else
                intervalMsec = 100;

            /*
            lowpassCoeff = .97;
            lowpassCoeff1 = .99999 - lowpassCoeff;
            */
        }
        else if( throttled && avgCpuLoad < .8 )
        {
            intervalMsec = 500;
            throttled = 0;

            /*
            lowpassCoeff = .9;
            lowpassCoeff1 = .99999 - lowpassCoeff;
            */
        }
    }

    pthread_cleanup_pop( 1 );   /* Execute cleanup on exit */

error:
    /* Shouldn't get here in the normal case */

    /* Pass on error code */
    pres = malloc( sizeof (PaError) );
    *pres = result;
    
    pthread_exit( pres );
}
Example #4
0
PaError PaUnixThread_Terminate( PaUnixThread* self, int wait, PaError* exitResult )
{
    PaError result = paNoError;
    void* pret;

    if( exitResult )
    {
        *exitResult = paNoError;
    }
#if 0
    if( watchdogExitResult )
        *watchdogExitResult = paNoError;

    if( th->watchdogRunning )
    {
        pthread_cancel( th->watchdogThread );
        PA_ENSURE_SYSTEM( pthread_join( th->watchdogThread, &pret ), 0 );

        if( pret && pret != PTHREAD_CANCELED )
        {
            if( watchdogExitResult )
                *watchdogExitResult = *(PaError *) pret;
            free( pret );
        }
    }
#endif

    /* Only kill the thread if it isn't in the process of stopping (flushing adaptation buffers) */
    /* TODO: Make join time out */
    self->stopRequested = wait;
    if( !wait )
    {
        PA_DEBUG(( "%s: Canceling thread %d\n", __FUNCTION__, self->thread ));
        /* XXX: Safe to call this if the thread has exited on its own? */
#ifdef PTHREAD_CANCELED
        pthread_cancel( self->thread );
#endif
    }
    PA_DEBUG(( "%s: Joining thread %d\n", __FUNCTION__, self->thread ));
    PA_ENSURE_SYSTEM( pthread_join( self->thread, &pret ), 0 );

#ifdef PTHREAD_CANCELED
    if( pret && PTHREAD_CANCELED != pret )
#else
    /* !wait means the thread may have been canceled */
    if( pret && wait )
#endif
    {
        if( exitResult )
        {
            *exitResult = *(PaError*)pret;
        }
        free( pret );
    }

error:
    PA_ASSERT_CALL( PaUnixMutex_Terminate( &self->mtx ), paNoError );
    PA_ASSERT_CALL( pthread_cond_destroy( &self->cond ), 0 );

    return result;
}
Example #5
0
PaError PaUnixThread_New( PaUnixThread* self, void* (*threadFunc)( void* ), void* threadArg, PaTime waitForChild,
        int rtSched )
{
    PaError result = paNoError;
    pthread_attr_t attr;
    int started = 0;

    memset( self, 0, sizeof (PaUnixThread) );
    PaUnixMutex_Initialize( &self->mtx );
    PA_ASSERT_CALL( pthread_cond_init( &self->cond, NULL ), 0 );

    self->parentWaiting = 0 != waitForChild;

    /* Spawn thread */

/* Temporarily disabled since we should test during configuration for presence of required mman.h header */
#if 0
#if defined _POSIX_MEMLOCK && (_POSIX_MEMLOCK != -1)
    if( rtSched )
    {
        if( mlockall( MCL_CURRENT | MCL_FUTURE ) < 0 )
        {
            int savedErrno = errno;             /* In case errno gets overwritten */
            assert( savedErrno != EINVAL );     /* Most likely a programmer error */
            PA_UNLESS( (savedErrno == EPERM), paInternalError );
            PA_DEBUG(( "%s: Failed locking memory\n", __FUNCTION__ ));
        }
        else
            PA_DEBUG(( "%s: Successfully locked memory\n", __FUNCTION__ ));
    }
#endif
#endif

    PA_UNLESS( !pthread_attr_init( &attr ), paInternalError );
    /* Priority relative to other processes */
    PA_UNLESS( !pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ), paInternalError );   

    PA_UNLESS( !pthread_create( &self->thread, &attr, threadFunc, threadArg ), paInternalError );
    started = 1;

    if( rtSched )
    {
#if 0
        if( self->useWatchdog )
        {
            int err;
            struct sched_param wdSpm = { 0 };
            /* Launch watchdog, watchdog sets callback thread priority */
            int prio = PA_MIN( self->rtPrio + 4, sched_get_priority_max( SCHED_FIFO ) );
            wdSpm.sched_priority = prio;

            PA_UNLESS( !pthread_attr_init( &attr ), paInternalError );
            PA_UNLESS( !pthread_attr_setinheritsched( &attr, PTHREAD_EXPLICIT_SCHED ), paInternalError );
            PA_UNLESS( !pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ), paInternalError );
            PA_UNLESS( !pthread_attr_setschedpolicy( &attr, SCHED_FIFO ), paInternalError );
            PA_UNLESS( !pthread_attr_setschedparam( &attr, &wdSpm ), paInternalError );
            if( (err = pthread_create( &self->watchdogThread, &attr, &WatchdogFunc, self )) )
            {
                PA_UNLESS( err == EPERM, paInternalError );
                /* Permission error, go on without realtime privileges */
                PA_DEBUG(( "Failed bumping priority\n" ));
            }
            else
            {
                int policy;
                self->watchdogRunning = 1;
                PA_ENSURE_SYSTEM( pthread_getschedparam( self->watchdogThread, &policy, &wdSpm ), 0 );
                /* Check if priority is right, policy could potentially differ from SCHED_FIFO (but that's alright) */
                if( wdSpm.sched_priority != prio )
                {
                    PA_DEBUG(( "Watchdog priority not set correctly (%d)\n", wdSpm.sched_priority ));
                    PA_ENSURE( paInternalError );
                }
            }
        }
        else
#endif
            PA_ENSURE( BoostPriority( self ) );

        {
            int policy;
            struct sched_param spm;
            pthread_getschedparam(self->thread, &policy, &spm);
        }
    }
    
    if( self->parentWaiting )
    {
        PaTime till;
        struct timespec ts;
        int res = 0;
        PaTime now;

        PA_ENSURE( PaUnixMutex_Lock( &self->mtx ) );

        /* Wait for stream to be started */
        now = PaUtil_GetTime();
        till = now + waitForChild;

        while( self->parentWaiting && !res )
        {
            if( waitForChild > 0 )
            {
                ts.tv_sec = (time_t) floor( till );
                ts.tv_nsec = (long) ((till - floor( till )) * 1e9);
                res = pthread_cond_timedwait( &self->cond, &self->mtx.mtx, &ts );
            }
            else
            {
                res = pthread_cond_wait( &self->cond, &self->mtx.mtx );
            }
        }

        PA_ENSURE( PaUnixMutex_Unlock( &self->mtx ) );

        PA_UNLESS( !res || ETIMEDOUT == res, paInternalError );
        PA_DEBUG(( "%s: Waited for %g seconds for stream to start\n", __FUNCTION__, PaUtil_GetTime() - now ));
        if( ETIMEDOUT == res )
        {
            PA_ENSURE( paTimedOut );
        }
    }

end:
    return result;
error:
    if( started )
    {
        PaUnixThread_Terminate( self, 0, NULL );
    }

    goto end;
}
Example #6
0
void PaWinDs_InitializeDSoundEntryPoints(void)
{
    paWinDsDSoundEntryPoints.hInstance_ = LoadLibraryA("dsound.dll");
    if( paWinDsDSoundEntryPoints.hInstance_ != NULL )
    {
        paWinDsDSoundEntryPoints.DllGetClassObject =
                (HRESULT (WINAPI *)(REFCLSID, REFIID , LPVOID *))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DllGetClassObject" );
        if( paWinDsDSoundEntryPoints.DllGetClassObject == NULL )
            paWinDsDSoundEntryPoints.DllGetClassObject = DummyDllGetClassObject;

        paWinDsDSoundEntryPoints.DirectSoundCreate =
                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCreate" );
        if( paWinDsDSoundEntryPoints.DirectSoundCreate == NULL )
            paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;

        paWinDsDSoundEntryPoints.DirectSoundEnumerateW =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateW" );
        if( paWinDsDSoundEntryPoints.DirectSoundEnumerateW == NULL )
            paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;

        paWinDsDSoundEntryPoints.DirectSoundEnumerateA =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateA" );
        if( paWinDsDSoundEntryPoints.DirectSoundEnumerateA == NULL )
            paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;

        paWinDsDSoundEntryPoints.DirectSoundCaptureCreate =
                (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureCreate" );
        if( paWinDsDSoundEntryPoints.DirectSoundCaptureCreate == NULL )
            paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;

        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateW" );
        if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW == NULL )
            paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;

        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA =
                (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateA" );
        if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA == NULL )
            paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;

#ifdef PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE
        paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 =
                (HRESULT (WINAPI *)(LPCGUID, LPCGUID, LPCDSCBUFFERDESC, LPCDSBUFFERDESC,
                                    HWND, DWORD, LPDIRECTSOUNDFULLDUPLEX *, LPDIRECTSOUNDCAPTUREBUFFER8 *,
                                    LPDIRECTSOUNDBUFFER8 *, LPUNKNOWN))
                GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundFullDuplexCreate" );
        if( paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 == NULL )
            paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 = DummyDirectSoundFullDuplexCreate8;
#endif
    }
    else
    {
        DWORD errorCode = GetLastError(); // 126 (0x7E) == ERROR_MOD_NOT_FOUND
        PA_DEBUG(("Couldn't load dsound.dll error code: %d \n",errorCode));

        /* initialize with dummy entry points to make live easy when ds isn't present */
        paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
        paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
        paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
        paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
        paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
#ifdef PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE
        paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 = DummyDirectSoundFullDuplexCreate8;
#endif
    }
}
DEFINE_THREAD_ROUTINE(academy_upload, data)
{
	char *directoryList = NULL;
	char *fileList = NULL;
	char dirname[ACADEMY_MAX_FILENAME];
	_ftp_t *academy_ftp = NULL;
	_ftp_status academy_status;
	char *ptr = NULL;
	academy_upload_t *academy = (academy_upload_t *)data;

	printf("Start thread %s\n", __FUNCTION__);

	while( academy_upload_started && !ardrone_tool_exit() )
	{
		vp_os_mutex_lock(&academy->mutex);
		vp_os_memset(&academy->user, 0, sizeof(academy_user_t));
		academy->callback = &academy_upload_private_callback;
		academy->connected = FALSE;
		academy_upload_resetState(academy);
		vp_os_cond_wait(&academy->cond);
		vp_os_mutex_unlock(&academy->mutex);

		while(academy_upload_started && academy->connected)
		{
			academy_status = FTP_FAIL;
			academy_upload_nextState(academy);

			switch(academy->state.state)
			{
				case ACADEMY_STATE_CONNECTION:
					{
						struct dirent *dirent = NULL;
						DIR *dir = NULL;
						academy_status = FTP_FAIL;

						// Check if flight_* directory exist in local dir
						if((dir = opendir(flight_dir)) != NULL)
						{
							struct stat statbuf;
							while(FTP_FAILED(academy_status) && (dirent = readdir(dir)) != NULL)
							{
								if((strncmp(dirent->d_name, "flight_", strlen("flight_")) == 0))
								{
									char local_dir[ACADEMY_MAX_FILENAME];
									sprintf(dirname, "%s", dirent->d_name);
									sprintf(local_dir, "%s/%s", flight_dir, dirname);
									if((stat(local_dir, &statbuf) == 0) && S_ISDIR(statbuf.st_mode))
										academy_status = FTP_SUCCESS;
								}
							}
                            closedir(dir);
						}

						if(FTP_SUCCEDED(academy_status))
						{
							if(academy_ftp == NULL)
								academy_ftp = ftpConnectFromName(ACADEMY_SERVERNAME, ACADEMY_PORT, academy->user.username, academy->user.password, &academy_status);
						}
					}
					break;

				case ACADEMY_STATE_PREPARE_PROCESS:
					academy_status = ftpCd(academy_ftp, "/Uploaded");
					if(FTP_FAILED(academy_status))
					{
						ftpMkdir(academy_ftp, "/Uploaded");
						academy_status = ftpCd(academy_ftp, "/Uploaded");
					}

					if(FTP_SUCCEDED(academy_status))
					{
						academy_status = ftpList(academy_ftp, &directoryList, NULL);
						if(FTP_SUCCEDED(academy_status))
						{
							bool_t found = FALSE;
							char *next_dir = NULL;

							while(!found && (ptr = academy_get_next_item_with_prefix(directoryList, &next_dir, "flight_", TRUE)))
							{
								if(strcmp(ptr, dirname) == 0)
								{
									found = TRUE;
									academy_upload_setState(academy, ACADEMY_STATE_FINISH_PROCESS);
								}
							}

							if(directoryList != NULL)
							{
								vp_os_free(directoryList);
								directoryList = NULL;
							}
						}
					}
					break;

				case ACADEMY_STATE_PROCESS:
					academy_status = ftpCd(academy_ftp, "/Uploading");
					if(FTP_FAILED(academy_status))
					{
						ftpMkdir(academy_ftp, "/Uploading");
						academy_status = ftpCd(academy_ftp, "/Uploading");
					}

					if(FTP_SUCCEDED(academy_status))
					{
						ftpMkdir(academy_ftp, dirname);
						academy_status = ftpCd(academy_ftp, dirname);
						if(FTP_SUCCEDED(academy_status))
						{
							char local_dir[ACADEMY_MAX_FILENAME];
							struct dirent *dirent = NULL;
							DIR *dir = NULL;

							sprintf(local_dir, "%s/%s", flight_dir, dirname);
							if((dir = opendir(local_dir)) != NULL)
							{
								char local_filename[ACADEMY_MAX_FILENAME];
								struct stat statbuf;
								while(FTP_SUCCEDED(academy_status) && ((dirent = readdir(dir)) != NULL))
								{
									if((strncmp(dirent->d_name, "picture_", strlen("picture_")) == 0) || (strncmp(dirent->d_name, "userbox_", strlen("userbox_")) == 0))
									{
										sprintf(local_filename, "%s/%s", local_dir, dirent->d_name);
										if((stat(local_filename, &statbuf) == 0) && !S_ISDIR(statbuf.st_mode))
										{
											PA_DEBUG("Put %s from local directory to server...", dirent->d_name);
											academy_status = ftpPut(academy_ftp, local_filename, dirent->d_name, 1, NULL);
											if(FTP_SUCCEDED(academy_status))
												PA_DEBUG("OK\n");
											else
												PA_DEBUG("ERROR\n");
										}
									}
								}
                                
                                closedir(dir);
							}
						}
					}
					break;

				case ACADEMY_STATE_FINISH_PROCESS:
					{
						char local_dir[ACADEMY_MAX_FILENAME];
						char src[ACADEMY_MAX_FILENAME];
						char dest[ACADEMY_MAX_FILENAME];
						sprintf(src, "/Uploading/%s", dirname);
						sprintf(dest, "/Uploaded/%s", dirname);
						academy_status = ftpRename(academy_ftp, src, dest);

						// Penser à supprimer le fichier local
						academy_status = FTP_FAIL;
						sprintf(local_dir, "%s/%s", flight_dir, dirname);
						if(!ftw(local_dir, &academy_remove, 1))
						{
							rmdir(local_dir);
							academy_status = FTP_SUCCESS;
						}
					}
					break;

				case ACADEMY_STATE_DISCONNECTION:
					if(academy_ftp != NULL)
						ftpClose(&academy_ftp);
					academy_status = FTP_SUCCESS;
					break;

				default:
					// Nothing to do
					break;
			}

			if(FTP_SUCCEDED(academy_status))
			{
				PA_DEBUG("continue state from %d to %d\n", academy->state.state, (academy->state.state + 1) % ACADEMY_STATE_MAX);
				academy_upload_stateOK(academy);
			}
			else
			{
				PA_DEBUG("stop\n");
				academy_upload_stateERROR(academy);

				if(fileList != NULL)
				{
					vp_os_free(fileList);
					fileList = NULL;
				}

				if(academy_ftp)
					ftpClose(&academy_ftp);

				vp_os_delay(1000);
			}
		}

		if(fileList != NULL)
		{
			vp_os_free(fileList);
			fileList = NULL;
		}

		if(academy_ftp)
			ftpClose(&academy_ftp);
	} // while

	THREAD_RETURN(C_OK);
}
Example #8
0
void *CallbackThread( void *userData )
{
    PaAlsaStream *stream = (PaAlsaStream*)userData;
    pthread_cleanup_push( &Stop, stream );   // Execute Stop on exit

    if( stream->pcm_playback )
        snd_pcm_start( stream->pcm_playback );
    else if( stream->pcm_capture )
        snd_pcm_start( stream->pcm_capture );

    while(1)
    {
        int frames_avail;
        int frames_got;

        PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
        int callbackResult;
        int framesProcessed;

        pthread_testcancel();
        {
            /* calculate time info */
            snd_timestamp_t capture_timestamp;
            snd_timestamp_t playback_timestamp;
            snd_pcm_status_t *capture_status;
            snd_pcm_status_t *playback_status;
            snd_pcm_status_alloca( &capture_status );
            snd_pcm_status_alloca( &playback_status );

            if( stream->pcm_capture )
            {
                snd_pcm_status( stream->pcm_capture, capture_status );
                snd_pcm_status_get_tstamp( capture_status, &capture_timestamp );
            }
            if( stream->pcm_playback )
            {
                snd_pcm_status( stream->pcm_playback, playback_status );
                snd_pcm_status_get_tstamp( playback_status, &playback_timestamp );
            }

            /* Hmm, we potentially have both a playback and a capture timestamp.
             * Hopefully they are the same... */
            if( stream->pcm_capture && stream->pcm_playback )
            {
                float capture_time = capture_timestamp.tv_sec +
                                     ((float)capture_timestamp.tv_usec/1000000);
                float playback_time= playback_timestamp.tv_sec +
                                     ((float)playback_timestamp.tv_usec/1000000);
                if( fabsf(capture_time-playback_time) > 0.01 )
                    PA_DEBUG(("Capture time and playback time differ by %f\n", fabsf(capture_time-playback_time)));
                timeInfo.currentTime = capture_time;
            }
            else if( stream->pcm_playback )
            {
                timeInfo.currentTime = playback_timestamp.tv_sec +
                                       ((float)playback_timestamp.tv_usec/1000000);
            }
            else
            {
                timeInfo.currentTime = capture_timestamp.tv_sec +
                                       ((float)capture_timestamp.tv_usec/1000000);
            }

            if( stream->pcm_capture )
            {
                snd_pcm_sframes_t capture_delay = snd_pcm_status_get_delay( capture_status );
                timeInfo.inputBufferAdcTime = timeInfo.currentTime -
                    (float)capture_delay / stream->streamRepresentation.streamInfo.sampleRate;
            }

            if( stream->pcm_playback )
            {
                snd_pcm_sframes_t playback_delay = snd_pcm_status_get_delay( playback_status );
                timeInfo.outputBufferDacTime = timeInfo.currentTime +
                    (float)playback_delay / stream->streamRepresentation.streamInfo.sampleRate;
            }
        }


        /*
            IMPLEMENT ME:
                - handle buffer slips
        */

        /*
            depending on whether the host buffers are interleaved, non-interleaved
            or a mixture, you will want to call PaUtil_ProcessInterleavedBuffers(),
            PaUtil_ProcessNonInterleavedBuffers() or PaUtil_ProcessBuffers() here.
        */

        framesProcessed = frames_avail = wait( stream );

        while( frames_avail > 0 )
        {
            //PA_DEBUG(( "%d frames available\n", frames_avail ));

            /* Now we know the soundcard is ready to produce/receive at least
             * one period.  We just need to get the buffers for the client
             * to read/write. */
            PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo,
                    0 /* @todo pass underflow/overflow flags when necessary */ );

            frames_got = setup_buffers( stream, frames_avail );


            PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );

            callbackResult = paContinue;

            /* this calls the callback */

            framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor,
                                                          &callbackResult );

            PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );

            /* inform ALSA how many frames we wrote */

            if( stream->pcm_capture )
                snd_pcm_mmap_commit( stream->pcm_capture, stream->capture_offset, frames_got );

            if( stream->pcm_playback )
                snd_pcm_mmap_commit( stream->pcm_playback, stream->playback_offset, frames_got );

            if( callbackResult != paContinue )
                break;

            frames_avail -= frames_got;
        }


        /*
            If you need to byte swap outputBuffer, you can do it here using
            routines in pa_byteswappers.h
        */

        if( callbackResult != paContinue )
        {
            stream->callback_finished = 1;
            stream->callbackAbort = (callbackResult == paAbort);

            pthread_exit( NULL );
        }
    }

    /* This code is unreachable, but important to include regardless because it
     * is possibly a macro with a closing brace to match the opening brace in
     * pthread_cleanup_push() above.  The documentation states that they must
     * always occur in pairs. */

    pthread_cleanup_pop( 1 );
}
Example #9
0
PaError PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex)
{
    PaSndioHostApiRepresentation *sndioHostApi;
    PaDeviceInfo *info;
    struct sio_hdl *hdl;
    
    PA_DEBUG(("PaSndio_Initialize: initializing...\n"));

    /* unusable APIs should return paNoError and a NULL hostApi */
    *hostApi = NULL;

    sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation));
    if (sndioHostApi == NULL)
        return paNoError;

    info = &sndioHostApi->default_info;
    info->structVersion = 2;
    info->name = "default";
    info->hostApi = hostApiIndex;
    info->maxInputChannels = 128;
    info->maxOutputChannels = 128;
    info->defaultLowInputLatency = 0.01;
    info->defaultLowOutputLatency = 0.01;
    info->defaultHighInputLatency = 0.5;
    info->defaultHighOutputLatency = 0.5;
    info->defaultSampleRate = 48000;
    sndioHostApi->infos[0] = info;
    
    *hostApi = &sndioHostApi->base;
    (*hostApi)->info.structVersion = 1;
    (*hostApi)->info.type = paSndio;
    (*hostApi)->info.name = "sndio";
    (*hostApi)->info.deviceCount = 1;
    (*hostApi)->info.defaultInputDevice = 0;
    (*hostApi)->info.defaultOutputDevice = 0;
    (*hostApi)->deviceInfos = sndioHostApi->infos;
    (*hostApi)->Terminate = Terminate;
    (*hostApi)->OpenStream = OpenStream;
    (*hostApi)->IsFormatSupported = IsFormatSupported;
    
    PaUtil_InitializeStreamInterface(&sndioHostApi->blocking,
        CloseStream,
        StartStream,
        StopStream,
        AbortStream,
        IsStreamStopped,
        IsStreamActive,
        GetStreamTime,
        PaUtil_DummyGetCpuLoad,
        BlockingReadStream,
        BlockingWriteStream,
        BlockingGetStreamReadAvailable,
        BlockingGetStreamWriteAvailable);

    PaUtil_InitializeStreamInterface(&sndioHostApi->callback,
        CloseStream,
        StartStream,
        StopStream,
        AbortStream,
        IsStreamStopped,
        IsStreamActive,
        GetStreamTime,
        PaUtil_DummyGetCpuLoad,
        PaUtil_DummyRead,
        PaUtil_DummyWrite,
        PaUtil_DummyGetReadAvailable,
        PaUtil_DummyGetWriteAvailable);

    PA_DEBUG(("PaSndio_Initialize: done\n"));
    return paNoError;
}
Example #10
0
static PaError AbortStream(PaStream *stream)
{
    PA_DEBUG(("AbortStream:\n"));

    return StopStream(stream);
}
Example #11
0
static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi,
    PaStream **stream,
    const PaStreamParameters *inputPar,
    const PaStreamParameters *outputPar,
    double sampleRate,
    unsigned long framesPerBuffer,
    PaStreamFlags streamFlags,
    PaStreamCallback *streamCallback,
    void *userData)
{
    PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi;
    PaSndioStream *s;
    PaError err;
    struct sio_hdl *hdl;
    struct sio_par par;
    unsigned mode;
    int readChannels, writeChannels;
    PaSampleFormat readFormat, writeFormat, deviceFormat;

    PA_DEBUG(("OpenStream:\n"));

    mode = 0;
    readChannels = writeChannels = 0;
    readFormat = writeFormat = 0;
    sio_initpar(&par);

    if (outputPar && outputPar->channelCount > 0) {
        if (outputPar->device != 0) {
            PA_DEBUG(("OpenStream: %d: bad output device\n", outputPar->device));
            return paInvalidDevice;
        }
        if (outputPar->hostApiSpecificStreamInfo) {
            PA_DEBUG(("OpenStream: output specific info\n"));
            return paIncompatibleHostApiSpecificStreamInfo;
        }
        if (!SampleFormatToSndioParameters(&par, outputPar->sampleFormat)) {
            return paSampleFormatNotSupported;
        }
        writeFormat = outputPar->sampleFormat;
        writeChannels = par.pchan = outputPar->channelCount;
        mode |= SIO_PLAY;
    }
    if (inputPar && inputPar->channelCount > 0) {
        if (inputPar->device != 0) {
            PA_DEBUG(("OpenStream: %d: bad input device\n", inputPar->device));
            return paInvalidDevice;
        }
        if (inputPar->hostApiSpecificStreamInfo) {
            PA_DEBUG(("OpenStream: input specific info\n"));
            return paIncompatibleHostApiSpecificStreamInfo;
        }
        if (!SampleFormatToSndioParameters(&par, inputPar->sampleFormat)) {
            return paSampleFormatNotSupported;
        }
        readFormat = inputPar->sampleFormat;
        readChannels = par.rchan = inputPar->channelCount;
        mode |= SIO_REC;
    }
    par.rate = sampleRate;
    if (framesPerBuffer != paFramesPerBufferUnspecified)
        par.round = framesPerBuffer;

    PA_DEBUG(("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate));

    hdl = sio_open(SIO_DEVANY, mode, 0);
    if (hdl == NULL)
        return paUnanticipatedHostError;
    if (!sio_setpar(hdl, &par)) {
        sio_close(hdl);
        return paUnanticipatedHostError;
    }
    if (!sio_getpar(hdl, &par)) {
        sio_close(hdl);
        return paUnanticipatedHostError;
    }
    if (!SndioParametersToSampleFormat(&par, &deviceFormat)) {
        sio_close(hdl);
        return paSampleFormatNotSupported;
    }
    if ((mode & SIO_REC) && par.rchan != inputPar->channelCount) {
        PA_DEBUG(("OpenStream: rchan(%u) != %d\n", par.rchan, inputPar->channelCount));
        sio_close(hdl);
        return paInvalidChannelCount;
    }
    if ((mode & SIO_PLAY) && par.pchan != outputPar->channelCount) {
        PA_DEBUG(("OpenStream: pchan(%u) != %d\n", par.pchan, outputPar->channelCount));
        sio_close(hdl);
        return paInvalidChannelCount;
    }
    if ((double)par.rate < sampleRate * 0.995 ||
        (double)par.rate > sampleRate * 1.005) {
        PA_DEBUG(("OpenStream: rate(%u) != %g\n", par.rate, sampleRate));
        sio_close(hdl);
        return paInvalidSampleRate;
    }
    
    s = (PaSndioStream *)PaUtil_AllocateMemory(sizeof(PaSndioStream));
    if (s == NULL) {
        sio_close(hdl);
        return paInsufficientMemory;
    }
    PaUtil_InitializeStreamRepresentation(&s->base, 
        streamCallback ? &sndioHostApi->callback : &sndioHostApi->blocking,
        streamCallback, userData);
    PA_DEBUG(("readChannels = %d, writeChannels = %d, readFormat = %x, writeFormat = %x\n", 
        readChannels, writeChannels, readFormat, writeFormat));
    err = PaUtil_InitializeBufferProcessor(&s->bufferProcessor,
        readChannels, readFormat, deviceFormat,
        writeChannels, writeFormat, deviceFormat,
        sampleRate,
        streamFlags,
        framesPerBuffer,
        par.round,
        paUtilFixedHostBufferSize, 
        streamCallback, userData);
    if (err) {
        PA_DEBUG(("OpenStream: PaUtil_InitializeBufferProcessor failed\n"));
        PaUtil_FreeMemory(s);
        sio_close(hdl);
        return err;
    }
    if (mode & SIO_REC) {
        s->readBuffer = malloc(par.round * par.rchan * par.bps);
        if (s->readBuffer == NULL) {
            PA_DEBUG(("OpenStream: failed to allocate readBuffer\n"));
            PaUtil_FreeMemory(s);
            sio_close(hdl);
            return paInsufficientMemory;
        }
    }
    if (mode & SIO_PLAY) {
        s->writeBuffer = malloc(par.round * par.pchan * par.bps);
        if (s->writeBuffer == NULL) {
            PA_DEBUG(("OpenStream: failed to allocate writeBuffer\n"));
            free(s->readBuffer);
            PaUtil_FreeMemory(s);
            sio_close(hdl);
            return paInsufficientMemory;
        }
    }
    s->nfds = sio_nfds(hdl);
    s->pfds = malloc(sizeof(struct pollfd) * s->nfds);
    s->base.streamInfo.inputLatency = 0;
    s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ?
        (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatencyFrames(&s->bufferProcessor)) / (double)par.rate : 0;
    s->base.streamInfo.sampleRate = par.rate;
    s->active = 0;
    s->stopped = 1;
    s->mode = mode;
    s->hdl = hdl;
    s->par = par;
    *stream = s;    
    PA_DEBUG(("OpenStream: done\n"));
    return paNoError;
}
Example #12
0
/*
 * I/O loop for callback interface
 */
static void *sndioThread(void *arg)
{
    PaSndioStream *s = (PaSndioStream *)arg;
    PaStreamCallbackTimeInfo ti;
    unsigned char *data;
    unsigned todo, rblksz, wblksz;
    int n, result;
    
    rblksz = s->par.round * s->par.rchan * s->par.bps;
    wblksz = s->par.round * s->par.pchan * s->par.bps;
    
    PA_DEBUG(("sndioThread: mode = %x, round = %u, rblksz = %u, wblksz = %u\n",
	s->mode, s->par.round, rblksz, wblksz));
    
    while (!s->stopped) {
        if (s->mode & SIO_REC) {
            todo = rblksz;
            data = s->readBuffer;
            while (todo > 0) {
                n = sio_read(s->hdl, data, todo);
                if (n == 0) {
                    PA_DEBUG(("sndioThread: sio_read failed\n"));
                    goto failed;
                }
                todo -= n;
                data += n;
            }
            s->bytesRead += s->par.round;
            ti.inputBufferAdcTime = 
                (double)s->framesProcessed / s->par.rate;
        }
        if (s->mode & SIO_PLAY) {
            ti.outputBufferDacTime =
                (double)(s->framesProcessed + s->par.bufsz) / s->par.rate;
        }
        ti.currentTime = s->framesProcessed / (double)s->par.rate;
        PaUtil_BeginBufferProcessing(&s->bufferProcessor, &ti, 0);
        if (s->mode & SIO_PLAY) {
            PaUtil_SetOutputFrameCount(&s->bufferProcessor, s->par.round);
            PaUtil_SetInterleavedOutputChannels(&s->bufferProcessor,
                0, s->writeBuffer, s->par.pchan);
        }
        if (s->mode & SIO_REC) {
            PaUtil_SetInputFrameCount(&s->bufferProcessor, s->par.round);
            PaUtil_SetInterleavedInputChannels(&s->bufferProcessor,
                0, s->readBuffer, s->par.rchan);
        }
        result = paContinue;
        n = PaUtil_EndBufferProcessing(&s->bufferProcessor, &result);
        if (n != s->par.round) {
            PA_DEBUG(("sndioThread: %d < %u frames, result = %d\n",
		      n, s->par.round, result));
        }
        if (result != paContinue) {
            break;
        }
        if (s->mode & SIO_PLAY) {
            n = sio_write(s->hdl, s->writeBuffer, wblksz);
            if (n < wblksz) {
                PA_DEBUG(("sndioThread: sio_write failed\n"));
                goto failed;
            }
            s->bytesWritten += s->par.round;
        }
    }
 failed:
    s->active = 0;
    PA_DEBUG(("sndioThread: done\n"));
}