int Trick::VariableServerThread::copy_data_scheduled(long long curr_tics) {

    int ret = 0 ;

    if ( enabled and copy_mode == VS_COPY_SCHEDULED) {
        if ( next_tics <= curr_tics ) {
            copy_sim_data() ;
            if ( !pause_cmd and write_mode == VS_WRITE_WHEN_COPIED and is_real_time()) {
                ret = write_data() ;
                if ( ret < 0 ) {
                    exit_cmd = true ;
                }
            }
            next_tics = curr_tics + cycle_tics ;
        }
    }
    return ret ;
}
示例#2
0
文件: portmidi.c 项目: RTcmix/RTcmix
 /* Algorithnm:
    if overflow or flush, return
    ATOMIC:
        enqueue data
        if buffer overflow, set overflow
        if buffer overflow and sysex_in_progress, set flush
  */
void pm_read_short(PmInternal *midi, PmEvent *event)
{ 
    long tail;
    int status;
    /* arg checking */
    assert(midi != NULL);
    assert(!Pm_HasHostError(midi));
    /* midi filtering is applied here */
    status = Pm_MessageStatus(event->message);
    if ((status == MIDI_ACTIVE) &&
        (midi->filters & PM_FILT_ACTIVE)) {
        /* MIDI active sensing filter: do nothing */
    } else if ((status == MIDI_CLOCK) && 
               (midi->filters & PM_FILT_CLOCK)) {
        /* MIDI clock filter: do nothing */
    } else {
        /* if sysex is in progress and we get a status byte, it had
           better be a realtime message or the starting SYSEX byte;
           otherwise, we exit the sysex_in_progress state
         */
        if (midi->sysex_in_progress && (status & MIDI_STATUS_MASK) && 
            !is_real_time(status) && status != MIDI_SYSEX ) {
            midi->sysex_in_progress = FALSE;
            midi->flush = FALSE;
        }

        /* don't try to do anything more in an overflow state */
        if (midi->overflow || midi->flush) return;

        /* insert the message */
        tail = midi->tail;
        midi->buffer[tail++] = *event;
        if (tail == midi->buffer_len) tail = 0;
        if (tail == midi->head || midi->overflow) {
             midi->overflow = TRUE;
            if (midi->sysex_in_progress) midi->flush = TRUE; 
            /* drop the rest of the message, this must be cleared 
               by caller when EOX is received */
               return;
        }
        midi->tail = tail; /* complete the write */
    }
}
int Trick::VariableServerThread::copy_data_freeze() {

    int ret = 0 ;
    long long curr_frame = exec_get_freeze_frame_count() ;
    long long temp_frame  ;

    if ( enabled and copy_mode == VS_COPY_TOP_OF_FRAME) {
        temp_frame = curr_frame % freeze_frame_multiple ;
        if ( temp_frame == freeze_frame_offset ) {
            copy_sim_data() ;
            if ( !pause_cmd and write_mode == VS_WRITE_WHEN_COPIED and is_real_time()) {
                ret = write_data() ;
                if ( ret < 0 ) {
                    exit_cmd = true ;
                }
            }
        }
    }
    return ret ;
}
示例#4
0
文件: portmidi.c 项目: RTcmix/RTcmix
PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, long length)
{
    PmInternal *midi = (PmInternal *) stream;
    PmError err;
    int i;
    int bits;
    
    /* arg checking */
    if(midi == NULL)
        err = pmBadPtr;
    else if(Pm_HasHostError(midi))
        err = pmHostError;
    else if(!descriptors[midi->device_id].pub.opened)
        err = pmBadPtr;
    else if(!descriptors[midi->device_id].pub.output)
        err = pmBadPtr;
    else
        err = pmNoError;
    
    if (err != pmNoError) goto pm_write_error;
    
    if (midi->latency == 0) {
        midi->now = 0;
    } else {
        midi->now = (*(midi->time_proc))(midi->time_info);
        if (midi->first_message || midi->sync_time + 100 /*ms*/ < midi->now) {
            /* time to resync */
            midi->now = (*midi->dictionary->synchronize)(midi);
            midi->first_message = FALSE;
        }
    }

    for (i = 0; i < length; i++) {
        unsigned long msg = buffer[i].message;
        bits = 0;
        /* is this a sysex message? */
        if (Pm_MessageStatus(msg) == MIDI_SYSEX) {
            if (midi->sysex_in_progress) {
                /* error: previous sysex was not terminated by EOX */
                midi->sysex_in_progress = FALSE;
                err = pmBadData;
                goto pm_write_error;
            }
            midi->sysex_in_progress = TRUE;
            if ((err = (*midi->dictionary->begin_sysex)(midi, 
                               buffer[i].timestamp)) != pmNoError)
                goto pm_write_error;
            if ((err = (*midi->dictionary->write_byte)(midi, MIDI_SYSEX,
                               buffer[i].timestamp)) != pmNoError) 
                goto pm_write_error;
            bits = 8;
            /* fall through to continue sysex processing */
        } else if ((msg & MIDI_STATUS_MASK) && 
                   (Pm_MessageStatus(msg) != MIDI_EOX)) {
            /* a non-sysex message */
            if (midi->sysex_in_progress) {
                /* this should be a non-realtime message */
                if (is_real_time(msg)) {
                    if ((err = (*midi->dictionary->write_realtime)(midi, 
                                       &(buffer[i]))) != pmNoError)
                        goto pm_write_error;
                } else {
                    midi->sysex_in_progress = FALSE;
                    err = pmBadData;
                    /* ignore any error from this, because we already have one */
                    /* pass 0 as timestamp -- it's ignored */
                    (*midi->dictionary->end_sysex)(midi, 0);
                    goto pm_write_error;
                }
            } else { /* regular short midi message */
                if ((err = (*midi->dictionary->write_short)(midi, 
                                   &(buffer[i]))) != pmNoError)
                    goto pm_write_error;
                continue;
            }
        }
        if (midi->sysex_in_progress) { /* send sysex bytes until EOX */
            while (bits < 32) {
                unsigned char midi_byte = (unsigned char) (msg >> bits);
                if ((err = (*midi->dictionary->write_byte)(midi, midi_byte, 
                                   buffer[i].timestamp)) != pmNoError)
                    goto pm_write_error;
                if (midi_byte == MIDI_EOX) {
                    midi->sysex_in_progress = FALSE;
                    if ((err = (*midi->dictionary->end_sysex)(midi, 
                                       buffer[i].timestamp)) != pmNoError)
                        goto pm_write_error;
                    break; /* from while loop */
                }
                bits += 8;
            }
        } else {
            /* not in sysex mode, but message did not start with status */
            err = pmBadData;
            goto pm_write_error;
        }
    }
示例#5
0
PMEXPORT PmError Pm_Write( PortMidiStream *stream, PmEvent *buffer, int32_t length)
{
    PmInternal *midi = (PmInternal *) stream;
    PmError err = pmNoError;
    int i;
    int bits;

    pm_hosterror = FALSE;
    /* arg checking */
    if(midi == NULL)
        err = pmBadPtr;
    else if(!descriptors[midi->device_id].pub.opened)
        err = pmBadPtr;
    else if(!descriptors[midi->device_id].pub.output)
        err = pmBadPtr;
    else
        err = pmNoError;

    if (err != pmNoError) goto pm_write_error;

    if (midi->latency == 0) {
        midi->now = 0;
    } else {
        midi->now = (*(midi->time_proc))(midi->time_info);
        if (midi->first_message || midi->sync_time + 100 /*ms*/ < midi->now) {
            /* time to resync */
            midi->now = (*midi->dictionary->synchronize)(midi);
            midi->first_message = FALSE;
        }
    }
    /* error recovery: when a sysex is detected, we call
     *   dictionary->begin_sysex() followed by calls to
     *   dictionary->write_byte() and dictionary->write_realtime()
     *   until an end-of-sysex is detected, when we call
     *   dictionary->end_sysex(). After an error occurs,
     *   Pm_Write() continues to call functions. For example,
     *   it will continue to call write_byte() even after
     *   an error sending a sysex message, and end_sysex() will be
     *   called when an EOX or non-real-time status is found.
     * When errors are detected, Pm_Write() returns immediately,
     *   so it is possible that this will drop data and leave
     *   sysex messages in a partially transmitted state.
     */
    for (i = 0; i < length; i++) {
        uint32_t msg = buffer[i].message;
        bits = 0;
        /* is this a sysex message? */
        if (Pm_MessageStatus(msg) == MIDI_SYSEX) {
            if (midi->sysex_in_progress) {
                /* error: previous sysex was not terminated by EOX */
                midi->sysex_in_progress = FALSE;
                err = pmBadData;
                goto pm_write_error;
            }
            midi->sysex_in_progress = TRUE;
            if ((err = (*midi->dictionary->begin_sysex)(midi,
                               buffer[i].timestamp)) != pmNoError)
                goto pm_write_error;
            if ((err = (*midi->dictionary->write_byte)(midi, MIDI_SYSEX,
                               buffer[i].timestamp)) != pmNoError)
                goto pm_write_error;
            bits = 8;
            /* fall through to continue sysex processing */
        } else if ((msg & MIDI_STATUS_MASK) &&
                   (Pm_MessageStatus(msg) != MIDI_EOX)) {
            /* a non-sysex message */
            if (midi->sysex_in_progress) {
                /* this should be a realtime message */
                if (is_real_time(msg)) {
                    if ((err = (*midi->dictionary->write_realtime)(midi,
                                       &(buffer[i]))) != pmNoError)
                        goto pm_write_error;
                } else {
                    midi->sysex_in_progress = FALSE;
                    err = pmBadData;
                    /* ignore any error from this, because we already have one */
                    /* pass 0 as timestamp -- it's ignored */
                    (*midi->dictionary->end_sysex)(midi, 0);
                    goto pm_write_error;
                }
            } else { /* regular short midi message */
                if ((err = (*midi->dictionary->write_short)(midi,
                                   &(buffer[i]))) != pmNoError)
                    goto pm_write_error;
                continue;
            }
        }
        if (midi->sysex_in_progress) { /* send sysex bytes until EOX */
            /* see if we can accelerate data transfer */
            if (bits == 0 && midi->fill_base && /* 4 bytes to copy */
                (*midi->fill_offset_ptr) + 4 <= midi->fill_length &&
                (msg & 0x80808080) == 0) { /* all data */
                    /* copy 4 bytes from msg to fill_base + fill_offset */
                    unsigned char *ptr = midi->fill_base +
                                         *(midi->fill_offset_ptr);
                    ptr[0] = msg; ptr[1] = msg >> 8;
                    ptr[2] = msg >> 16; ptr[3] = msg >> 24;
                    (*midi->fill_offset_ptr) += 4;
                     continue;
            }
            /* no acceleration, so do byte-by-byte copying */
            while (bits < 32) {
                unsigned char midi_byte = (unsigned char) (msg >> bits);
                if ((err = (*midi->dictionary->write_byte)(midi, midi_byte,
                                   buffer[i].timestamp)) != pmNoError)
                    goto pm_write_error;
                if (midi_byte == MIDI_EOX) {
                    err = pm_end_sysex(midi);
                    if (err != pmNoError) goto error_exit;
                    break; /* from while loop */
                }
                bits += 8;
            }
        } else {