Ejemplo n.º 1
0
PmError Pm_Close( PortMidiStream *stream ) {
    PmInternal *midi = (PmInternal *) stream;
    PmError err = pmNoError;

    /* arg checking */
    if (midi == NULL) /* midi must point to something */
        err = pmBadPtr;
    /* if it is an open device, the device_id will be valid */
    else if (midi->device_id < 0 || midi->device_id >= pm_descriptor_index)
        err = pmBadPtr;
    /* and the device should be in the opened state */
    else if (!descriptors[midi->device_id].pub.opened)
        err = pmBadPtr;
    
    if (err != pmNoError) 
        goto error_return;

    /* close the device */
    err = (*midi->dictionary->close)(midi);
    /* even if an error occurred, continue with cleanup */
    descriptors[midi->device_id].internalDescriptor = NULL;
    descriptors[midi->device_id].pub.opened = FALSE;
    pm_free(midi->buffer);       
    pm_free(midi); 
error_return:
    return pm_errmsg(err);
}
Ejemplo n.º 2
0
Archivo: pmap.c Proyecto: Darge/mimiker
int main() { /* Simple test */
  pmap_t pmap;
  pmap_init(&pmap);
  pmap.asid = 10;

  set_active_pmap(&pmap);
  vm_page_t *pg1 = pm_alloc(4);

  vaddr_t ex_addr = PAGESIZE * 10;
  pmap_map(&pmap, ex_addr, pg1->paddr, pg1->size, PMAP_VALID | PMAP_DIRTY);

  int *x = (int *) ex_addr;
  for (int i = 0; i < 1024 * pg1->size; i++)
    *(x + i) = i;
  for (int i = 0; i < 1024 * pg1->size; i++)
    assert(*(x + i) == i);

  vm_page_t *pg2 = pm_alloc(1);

  ex_addr = PAGESIZE * 2000;
  pmap_map(&pmap, ex_addr, pg2->paddr, pg2->size, PMAP_VALID | PMAP_DIRTY);

  x = (int *) ex_addr;
  for (int i = 0; i < 1024 * pg2->size; i++)
    *(x + i) = i;
  for (int i = 0; i < 1024 * pg2->size; i++)
    assert(*(x + i) == i);

  pm_free(pg1);
  pm_free(pg2);

  pmap_delete(&pmap);
  kprintf("Tests passed\n");
  return 0;
}
Ejemplo n.º 3
0
PMEXPORT PmQueue *Pm_QueueCreate(long num_msgs, int32_t bytes_per_msg)
{
    int32_t int32s_per_msg = 
            (int32_t) (((bytes_per_msg + sizeof(int32_t) - 1) &
                       ~(sizeof(int32_t) - 1)) / sizeof(int32_t));
    PmQueueRep *queue = (PmQueueRep *) pm_alloc(sizeof(PmQueueRep));
    if (!queue) /* memory allocation failed */
        return NULL;

    /* need extra word per message for non-zero encoding */
    queue->len = num_msgs * (int32s_per_msg + 1);
    queue->buffer = (int32_t *) pm_alloc(queue->len * sizeof(int32_t));
    bzero(queue->buffer, queue->len * sizeof(int32_t));
    if (!queue->buffer) {
        pm_free(queue);
        return NULL;
    } else { /* allocate the "peek" buffer */
        queue->peek = (int32_t *) pm_alloc(int32s_per_msg * sizeof(int32_t));
        if (!queue->peek) {
            /* free everything allocated so far and return */
            pm_free(queue->buffer);
            pm_free(queue);
            return NULL;
        }
    }
    bzero(queue->buffer, queue->len * sizeof(int32_t));
    queue->head = 0;
    queue->tail = 0;
    /* msg_size is in words */
    queue->msg_size = int32s_per_msg + 1; /* note extra word is counted */
    queue->overflow = FALSE;
    queue->peek_overflow = FALSE;
    queue->peek_flag = FALSE;
    return queue;
}
Ejemplo n.º 4
0
static void winmm_out_delete(PmInternal *midi)
{
	int i;
	/* delete system dependent device data */
	midiwinmm_type m = (midiwinmm_type) midi->descriptor;
	if (m) {
		if (m->buffer_signal) {
			/* don't report errors -- better not to stop cleanup */
			CloseHandle(m->buffer_signal);
		}
		/* if using stream output, free buffers */
		for (i = 0; i < m->num_buffers; i++) {
			if (m->buffers[i]) pm_free(m->buffers[i]);
		}
		m->num_buffers = 0;
		pm_free(m->buffers);
		m->max_buffers = 0;
#ifdef USE_SYSEX_BUFFERS
		/* free sysex buffers */
		for (i = 0; i < NUM_SYSEX_BUFFERS; i++) {
			if (m->sysex_buffers[i]) pm_free(m->sysex_buffers[i]);
		}
#endif
	}
	midi->descriptor = NULL;
	pm_free(m); /* delete */
}
Ejemplo n.º 5
0
Archivo: pmap.c Proyecto: Darge/mimiker
void pmap_delete(pmap_t *pmap) {
  while (!TAILQ_EMPTY(&pmap->pte_pages)) {
    vm_page_t *pg = TAILQ_FIRST(&pmap->pte_pages);
    TAILQ_REMOVE(&pmap->pte_pages, pg, pt.list);
    pm_free(pg);
  }
  pm_free(pmap->pde_page);
}
Ejemplo n.º 6
0
PmError Pm_QueueDestroy(PmQueue *q)
{
    PmQueueRep *queue = (PmQueueRep *) q;
	
	/* arg checking */
    if (!queue || !queue->buffer) 
		return pmBadPtr;
    
	pm_free(queue->buffer);
    pm_free(queue);
    return pmNoError;
}
Ejemplo n.º 7
0
/* no error codes are returned, even if errors are encountered, because
   there is probably nothing the user could do (e.g. it would be an error
   to retry.
 */
void pm_winmm_term( void )
{
    int i;
#ifdef DEBUG
    char msg[PM_HOST_ERROR_MSG_LEN];
#endif
    int doneAny = 0;
#ifdef DEBUG
    printf("pm_winmm_term called\n");
#endif
    for (i = 0; i < pm_descriptor_index; i++) {
        PmInternal * midi = descriptors[i].internalDescriptor;
        if (midi) {
            midiwinmm_type m = (midiwinmm_type) midi->descriptor;
            if (m->handle.out) {
                /* close next open device*/
#ifdef DEBUG
                if (doneAny == 0) {
                    printf("begin closing open devices...\n");
                    doneAny = 1;
                }
                /* report any host errors; this EXTEREMELY useful when
                   trying to debug client app */
                if (winmm_has_host_error(midi)) {
                    winmm_get_host_error(midi, msg, PM_HOST_ERROR_MSG_LEN);
                    printf("%s\n", msg);
                }
#endif
                /* close all open ports */
                (*midi->dictionary->close)(midi);
            }
        }
    }
    if (midi_in_caps) {
        pm_free(midi_in_caps);
        midi_in_caps = NULL;
    }
    if (midi_out_caps) {
        pm_free(midi_out_caps);
        midi_out_caps = NULL;
    }
#ifdef DEBUG
    if (doneAny) {
        printf("warning: devices were left open. They have been closed.\n");
    }
    printf("pm_winmm_term exiting\n");
#endif
    pm_descriptor_index = 0;
}
Ejemplo n.º 8
0
static Header ldhdr_bynevr(const struct pkg *pkg, void *foo) 
{
    struct pm_ctx    *pmctx;
    struct pkgdb     *db;
    struct pm_dbrec  dbrec;
    Header           h = NULL;
    
    DBGF("%s\n", pkg_snprintf_s(pkg));
    foo = foo;
    pmctx = pm_new("rpm");
    
    db = pkgdb_open(pmctx, "/", NULL, O_RDONLY, NULL);
    if (db == NULL) 
        goto l_end;
    
    if (pkgdb_get_package_hdr(db, pkg, &dbrec)) {
        n_assert(dbrec.hdr);
        h = pm_rpmhdr_link(dbrec.hdr);
    }
    
    pkgdb_free(db);
    
 l_end:
    pm_free(pmctx);
    return h;
}
Ejemplo n.º 9
0
static Header ldhdr_byrecno(const struct pkg *pkg, void *foo) 
{
    struct pm_ctx    *pmctx;
    struct pkgdb     *db;
    struct pkgdb_it  it;
    const struct pm_dbrec *dbrec;
    Header           h = NULL;

    foo = foo;
    n_assert(pkg->recno > 0);

    pmctx = pm_new("rpm");
    db = pkgdb_open(pmctx, "/", NULL, O_RDONLY, NULL);
    if (db == NULL) 
        goto l_end;
    
    pkgdb_it_init(db, &it, PMTAG_RECNO, (const char*)&pkg->recno);
    
    if ((dbrec = pkgdb_it_get(&it)) == NULL)
        goto l_end;

    // rpm's error: rpmdb_it_get_count(&it) with RECNO is always 0 
    if (dbrec->hdr)
        h = pm_rpmhdr_link(dbrec->hdr);
        
    pkgdb_it_destroy(&it);
    pkgdb_free(db);
    
 l_end:
    pm_free(pmctx);
    return h;
}
Ejemplo n.º 10
0
void io_libraryRelease(io_library_t *library)
{
	spinlock_lock(&library->lock);

	if((-- library->refCount) == 0)
	{
		struct io_dependency_s *dependency = list_first(library->dependencies);
		while(dependency)
		{
			io_libraryRelease(dependency->library);
			dependency = dependency->next;
		}

		io_storeRemoveLibrary(library);

		if(library->vmemory)
			vm_free(vm_getKernelDirectory(), library->vmemory, library->pages);

		if(library->pmemory)
			pm_free(library->pmemory, library->pages);

		hfree(NULL, library->path);
		list_destroy(library->dependencies);
		return;
	}

	spinlock_unlock(&library->lock);
}
Ejemplo n.º 11
0
void dma_free(dma_t *dma)
{
	for(size_t i=0; i<dma->pfragmentCount; i++)
	{
		pm_free(dma->pfragments[i], dma->pfragmentPages[i]);
	}

	if(dma->vaddress)
		vm_free(vm_getKernelDirectory(), dma->vaddress, dma->pages);

	hfree(NULL, dma);
}
Ejemplo n.º 12
0
static PmError allocate_input_buffer(HMIDIIN h, long buffer_len)
{
    LPMIDIHDR hdr = allocate_buffer(buffer_len);
    if (!hdr) return pmInsufficientMemory;
    pm_hosterror = midiInPrepareHeader(h, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        return pm_hosterror;
    }
    pm_hosterror = midiInAddBuffer(h, hdr, sizeof(MIDIHDR));
    return pm_hosterror;
}
Ejemplo n.º 13
0
static PmError allocate_buffers(midiwinmm_type m, long data_size, long count)
{
    int i;
    /* buffers is an array of count pointers to MIDIHDR/MIDIEVENT struct */
    m->num_buffers = 0; /* in case no memory can be allocated */
    m->buffers = (LPMIDIHDR *) pm_alloc(sizeof(LPMIDIHDR) * count);
    if (!m->buffers) return pmInsufficientMemory;
    m->max_buffers = count;
    for (i = 0; i < count; i++) {
        LPMIDIHDR hdr = allocate_buffer(data_size);
        if (!hdr) { /* free everything allocated so far and return */
            for (i = i - 1; i >= 0; i--) pm_free(m->buffers[i]);
            pm_free(m->buffers);
            m->max_buffers = 0;
            return pmInsufficientMemory;
        }
        m->buffers[i] = hdr; /* this may be NULL if allocation fails */
    }
    m->num_buffers = count;
    return pmNoError;
}
Ejemplo n.º 14
0
void
fastpm_png_induce_correlation(FastPMPNGaussian * png, PM * pm, FastPMFloat * delta_k)
{
    FastPMFloat * g_x = pm_alloc(pm);
    png->Volume = pm->Volume;

    fastpm_ic_induce_correlation(pm, delta_k, (fastpm_fkfunc) fastpm_png_potential, png);

    pm_assign(pm, delta_k, g_x);
    pm_c2r(pm, g_x);

    fastpm_png_transform_potential(pm, g_x, png);

    pm_r2c(pm, g_x, delta_k);
    pm_free(pm, g_x);

    fastpm_apply_any_transfer(pm, delta_k, delta_k, (fastpm_fkfunc) fastpm_png_transfer_function, png);
}
Ejemplo n.º 15
0
void ld_executableRelease(ld_exectuable_t *executable)
{
	executable->useCount --;

	if(executable->useCount == 0)
	{
		if(executable->source)
			ld_executableRelease(executable->source);

		if(executable->pimage)
			pm_free(executable->pimage, executable->imagePages);

		if(executable->vimage)
			vm_free(executable->pdirectory, executable->vimage, executable->imagePages);

		hfree(NULL, executable);
	}
}
Ejemplo n.º 16
0
PmQueue *Pm_QueueCreate(long num_msgs, long bytes_per_msg)
{
    PmQueueRep *queue = (PmQueueRep *) pm_alloc(sizeof(PmQueueRep));

	/* arg checking */
    if (!queue) 
		return NULL;
    
	queue->len = num_msgs * bytes_per_msg;
    queue->buffer = pm_alloc(queue->len);
    if (!queue->buffer) {
        pm_free(queue);
        return NULL;
    }
    queue->head = 0;
    queue->tail = 0;
    queue->msg_size = bytes_per_msg;
    queue->overflow = FALSE;
    return queue;
}
Ejemplo n.º 17
0
/*
 * assume midi is non-null (checked by caller)
 */
static PmError winmm_in_close(PmInternal *midi)
{
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;
    if (!m) return pmBadPtr;
    /* device to close */
    if (pm_hosterror = midiInStop(m->handle.in)) {
        midiInReset(m->handle.in); /* try to reset and close port */
        midiInClose(m->handle.in);
    } else if (pm_hosterror = midiInReset(m->handle.in)) {
        midiInClose(m->handle.in); /* best effort to close midi port */
    } else {
        pm_hosterror = midiInClose(m->handle.in);
    }
    midi->descriptor = NULL;
    pm_free(m); /* delete */
    if (pm_hosterror) {
        int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, 
                                     PM_HOST_ERROR_MSG_LEN);
        assert(err == MMSYSERR_NOERROR);
        return pmHostError;
    }
    return pmNoError;
}
Ejemplo n.º 18
0
int main() {
  vm_page_t *page = pm_alloc(1);

  MALLOC_DEFINE(mp, "testing memory pool");

  kmalloc_init(mp);
  kmalloc_add_arena(mp, page->vaddr, PAGESIZE);

  void *ptr1 = kmalloc(mp, 15, 0);
  assert(ptr1 != NULL);

  void *ptr2 = kmalloc(mp, 23, 0);
  assert(ptr2 != NULL && ptr2 > ptr1);

  void *ptr3 = kmalloc(mp, 7, 0);
  assert(ptr3 != NULL && ptr3 > ptr2);

  void *ptr4 = kmalloc(mp, 2000, 0);
  assert(ptr4 != NULL && ptr4 > ptr3);

  void *ptr5 = kmalloc(mp, 1000, 0);
  assert(ptr5 != NULL);

  kfree(mp, ptr1);
  kfree(mp, ptr2);
  kmalloc_dump(mp);
  kfree(mp, ptr3);
  kfree(mp, ptr5);

  void *ptr6 = kmalloc(mp, 2000, M_NOWAIT);
  assert(ptr6 == NULL);

  pm_free(page);

  return 0;
}
Ejemplo n.º 19
0
static Header ldhdr(const struct pkg *pkg, void *foo) 
{
    struct pm_ctx    *pmctx;
    struct pkgdb     *db;
    struct pkgdb_it  it;
    const struct pm_dbrec *dbrec;
    Header              h = NULL;

    foo = foo;
    n_assert(pkg->recno > 0);
    
    if (pkg->pkgdir == NULL)
        return NULL;

    pmctx = pkg->pkgdir->mod_data;
    if (pkg->pkgdir->mod_data == NULL) /* pkgdir are saved now  */
        pmctx = pm_new("rpm");
    
    db = pkgdb_open(pmctx, "/", pkg->pkgdir->idxpath,
                    O_RDONLY, NULL);
    if (db == NULL)
        return NULL;
    
    pkgdb_it_init(db, &it, PMTAG_RECNO, (const char*)&pkg->recno);
    dbrec = pkgdb_it_get(&it);
    
    // rpm's error: rpmdb_it_get_count(&it) with RECNO is always 0 
    if (dbrec && dbrec->hdr)
        h = pm_rpmhdr_link(dbrec->hdr);

    pkgdb_it_destroy(&it);
    pkgdb_free(db);
    if (pkg->pkgdir->mod_data == NULL)
        pm_free(pmctx);
    return h;
}
Ejemplo n.º 20
0
static void do_free(struct pkgdir *pkgdir)
{
    if (pkgdir->mod_data)
        pm_free(pkgdir->mod_data);
}
Ejemplo n.º 21
0
static PmError winmm_in_open(PmInternal *midi, void *driverInfo)
{
    DWORD dwDevice;
    int i = midi->device_id;
    int max_sysex_len = midi->buffer_len * 4;
    int num_input_buffers = max_sysex_len / INPUT_SYSEX_LEN;
    midiwinmm_type m;

    dwDevice = (DWORD) descriptors[i].descriptor;

    /* create system dependent device data */
    m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */
    midi->descriptor = m;
    if (!m) goto no_memory;
    m->handle.in = NULL;
    m->buffers = NULL; /* not used for input */
    m->num_buffers = 0; /* not used for input */
    m->max_buffers = FALSE; /* not used for input */
    m->buffers_expanded = 0; /* not used for input */
    m->next_buffer = 0; /* not used for input */
    m->buffer_signal = 0; /* not used for input */
    m->last_time = 0;
    m->first_message = TRUE; /* not used for input */
    m->sysex_mode = FALSE;
    m->sysex_word = 0;
    m->sysex_byte_count = 0;
    m->hdr = NULL; /* not used for input */
    m->sync_time = 0;
    m->delta = 0;
    m->error = MMSYSERR_NOERROR;
    /* 4000 is based on Windows documentation -- that's the value used in the
       memory manager. It's small enough that it should not hurt performance even
       if it's not optimal.
     */
    InitializeCriticalSectionAndSpinCount(&m->lock, 4000);
    /* open device */
    pm_hosterror = midiInOpen(
	    &(m->handle.in),  /* input device handle */
	    dwDevice,  /* device ID */
	    (DWORD_PTR) winmm_in_callback,  /* callback address */
	    (DWORD_PTR) midi,  /* callback instance data */
	    CALLBACK_FUNCTION); /* callback is a procedure */
    if (pm_hosterror) goto free_descriptor;

    if (num_input_buffers < MIN_INPUT_BUFFERS)
        num_input_buffers = MIN_INPUT_BUFFERS;
    for (i = 0; i < num_input_buffers; i++) {
        if (allocate_input_buffer(m->handle.in, INPUT_SYSEX_LEN)) {
            /* either pm_hosterror was set, or the proper return code
               is pmInsufficientMemory */
            goto close_device;
        }
    }
    /* start device */
    pm_hosterror = midiInStart(m->handle.in);
    if (pm_hosterror) goto reset_device;
    return pmNoError;

    /* undo steps leading up to the detected error */
reset_device:
    /* ignore return code (we already have an error to report) */
    midiInReset(m->handle.in);
close_device:
    midiInClose(m->handle.in); /* ignore return code */
free_descriptor:
    midi->descriptor = NULL;
    pm_free(m);
no_memory:
    if (pm_hosterror) {
        int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text,
                                     PM_HOST_ERROR_MSG_LEN);
        assert(err == MMSYSERR_NOERROR);
        return pmHostError;
    }
    /* if !pm_hosterror, then the error must be pmInsufficientMemory */
    return pmInsufficientMemory;
    /* note: if we return an error code, the device will be
       closed and memory will be freed. It's up to the caller
       to free the parameter midi */
}
Ejemplo n.º 22
0
PmError Pm_OpenOutput(PortMidiStream** stream,
                      PmDeviceID outputDevice,
                      void *outputDriverInfo,
                      long bufferSize,
                      PmTimeProcPtr time_proc,
                      void *time_info,
                      long latency ) {
    PmInternal *midi;
    PmError err = pmNoError;
    pm_hosterror = FALSE;
    *stream =  NULL;
    
    /* arg checking */
    if (outputDevice < 0 || outputDevice >= pm_descriptor_index)
        err = pmInvalidDeviceId;
    else if (!descriptors[outputDevice].pub.output) 
        err = pmBadPtr;
    else if (descriptors[outputDevice].pub.opened)
        err = pmBadPtr;
    if (err != pmNoError) 
        goto error_return;

    /* create portMidi internal data */
    midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); 
    *stream = midi;                 
    if (!midi) {
        err = pmInsufficientMemory;
        goto error_return;
    }
    midi->device_id = outputDevice;
    midi->write_flag = TRUE;
    midi->time_proc = time_proc;
    /* if latency > 0, we need a time reference. If none is provided,
       use PortTime library */
    if (time_proc == NULL && latency != 0) {
        if (!Pt_Started()) 
            Pt_Start(1, 0, 0);
        /* time_get does not take a parameter, so coerce */
        midi->time_proc = (PmTimeProcPtr) Pt_Time;
    }
    midi->time_info = time_info;
    /* when stream used, this buffer allocated and used by 
        winmm_out_open; deleted by winmm_out_close */
    midi->buffer_len = bufferSize;
    midi->buffer = NULL;
    midi->head = 0; /* unused by output */
    midi->tail = 0; /* unused by output */
    /* if latency zero, output immediate (timestamps ignored) */
    /* if latency < 0, use 0 but don't return an error */
    if (latency < 0) latency = 0;
    midi->latency = latency;
    midi->overflow = FALSE; /* not used */
    midi->flush = FALSE; /* not used */
    midi->sysex_in_progress = FALSE;
    midi->sysex_message = 0; /* unused by output */
    midi->sysex_message_count = 0; /* unused by output */
    midi->filters = 0; /* not used for output */
    midi->sync_time = 0;
    midi->first_message = TRUE;
    midi->dictionary = descriptors[outputDevice].dictionary;
    descriptors[outputDevice].internalDescriptor = midi;
    /* open system dependent output device */
    err = (*midi->dictionary->open)(midi, outputDriverInfo);
    if (err) {
        *stream = NULL;
        descriptors[outputDevice].internalDescriptor = NULL;
        /* free portMidi data */
        pm_free(midi); 
    } else {
        /* portMidi input open successful */
        descriptors[outputDevice].pub.opened = TRUE;
    }
error_return:
    return pm_errmsg(err);
}
Ejemplo n.º 23
0
/* Callback function executed via midiInput SW interrupt (via midiInOpen). */
static void FAR PASCAL winmm_in_callback(
     HMIDIIN hMidiIn,   /* midiInput device Handle */
     WORD wMsg,         /* midi msg */
     DWORD dwInstance,  /* application data */
     DWORD dwParam1,    /* MIDI data */
     DWORD dwParam2)    /* device timestamp (wrt most recent midiInStart) */
{
    static int entry = 0;   
    PmInternal *midi = (PmInternal *) dwInstance;
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;

    if (++entry > 1) {
        assert(FALSE);
    } 

    /* for simplicity, this logic perhaps overly conservative */
    /* note also that this might leak memory if buffers are being
       returned as a result of midiInReset */
    if (m->callback_error) {
        entry--;
        return;
    }

    switch (wMsg) {
      case MIM_DATA: {
        /* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of 
                message LOB;
           dwParam2 is time message received by input device driver, specified
            in [ms] from when midiInStart called.
           each message is expanded to include the status byte */

        long new_driver_time = dwParam2;

        if ((dwParam1 & 0x80) == 0) {
            /* not a status byte -- ignore it. This happens running the 
               sysex.c test under Win2K with MidiMan USB 1x1 interface.
               Is it a driver bug or a Win32 bug? If not, there's a bug
               here somewhere. -RBD
             */
        } else { /* data to process */
            PmEvent event;
            if (midi->time_proc) 
                dwParam2 = (*midi->time_proc)(midi->time_info);
            event.timestamp = dwParam2;
            event.message = dwParam1;
            pm_read_short(midi, &event);
        }
        break;  
      }
      case MIM_LONGDATA: {
        MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1;
        unsigned char *data = lpMidiHdr->lpData;
        unsigned int i = 0;
        long size = sizeof(MIDIHDR) + lpMidiHdr->dwBufferLength;
        /* ignore sysex data, but free returned buffers */
        if (lpMidiHdr->dwBytesRecorded > 0 &&
            midi->filters & PM_FILT_SYSEX) {
                m->callback_error = midiInAddBuffer(hMidiIn, lpMidiHdr, 
                                                    sizeof(MIDIHDR));
                break; 
        }
        if (midi->time_proc)
            dwParam2 = (*midi->time_proc)(midi->time_info);

        while (i < lpMidiHdr->dwBytesRecorded) {
            /* collect bytes from *data into a word */
            pm_read_byte(midi, *data, dwParam2);
            data++;
            i++;
        }
        /* when a device is closed, the pending MIM_LONGDATA buffers are 
           returned to this callback with dwBytesRecorded == 0. In this 
           case, we do not want to send them back to the interface (if 
           we do, the interface will not close, and Windows OS may hang). */
        if (lpMidiHdr->dwBytesRecorded > 0) {
            m->callback_error = midiInAddBuffer(hMidiIn, lpMidiHdr, 
                                                sizeof(MIDIHDR));
        } else {
            pm_free(lpMidiHdr);
        }
        break;
      }
      case MIM_OPEN: /* fall thru */
      case MIM_CLOSE:
      case MIM_ERROR: 
      case MIM_LONGERROR: 
      default:
        break;
    }
    entry--;
}
Ejemplo n.º 24
0
int main(int argc, char *argv[]) {
    // Get path
    char *ip = NULL;
    unsigned short connect_port = 0;
    unsigned short listen_port = 0;
    int net_mode = NET_MODE_NONE;
    int ret = 0;

    // Path manager
    if(pm_init() != 0) {
        err_msgbox(pm_get_errormsg());
        return 1;
    }

    // Check arguments
    if(argc >= 2) {
        if(strcmp(argv[1], "-v") == 0) {
            printf("OpenOMF v%d.%d.%d\n", V_MAJOR, V_MINOR, V_PATCH);
            printf("Source available at https://github.com/omf2097/ under MIT License\n");
            printf("(C) 2097 Tuomas Virtanen, Andrew Thompson, Hunter and others\n");
            goto exit_0;
        } else if(strcmp(argv[1], "-h") == 0) {
            printf("Arguments:\n");
            printf("-h              Prints this help\n");
            printf("-c [ip] [port]  Connect to server\n");
            printf("-l [port]       Start server\n");
            goto exit_0;
        } else if(strcmp(argv[1], "-c") == 0) {
            if(argc >= 3) {
                ip = strcpy(malloc(strlen(argv[2])+1), argv[2]);
            }
            if(argc >= 4) {
                connect_port = atoi(argv[3]);
            }
            net_mode = NET_MODE_CLIENT;
        } else if(strcmp(argv[1], "-l") == 0) {
            if(argc >= 3) {
                listen_port = atoi(argv[2]);
            }
            net_mode = NET_MODE_SERVER;
        }
    }

    // Init log
#if defined(DEBUGMODE) || defined(STANDALONE_SERVER)
    if(log_init(0)) {
        err_msgbox("Error while initializing log!");
        goto exit_0;
    }
#else
    if(log_init(pm_get_local_path(LOG_PATH))) {
        err_msgbox("Error while initializing log '%s'!", pm_get_local_path(LOG_PATH));
        goto exit_0;
    }
#endif

    // Simple header
    INFO("Starting OpenOMF v%d.%d.%d", V_MAJOR, V_MINOR, V_PATCH);

    // Dump pathmanager log
    pm_log();

    // Random seed
    rand_seed(time(NULL));

    // Init stringparser
    sd_stringparser_lib_init();

    // Init config
    if(settings_init(pm_get_local_path(CONFIG_PATH))) {
        err_msgbox("Failed to initialize settings file");
        goto exit_1;
    }
    settings_load();

    // Find plugins and make sure they are valid
    plugins_init();

    // Network game override stuff
    if(ip) {
        DEBUG("Connect IP overridden to %s", ip);
        settings_get()->net.net_connect_ip = ip;
    }
    if(connect_port > 0 && connect_port < 0xFFFF) {
        DEBUG("Connect Port overridden to %u", connect_port&0xFFFF);
        settings_get()->net.net_connect_port = connect_port;
    }
    if(listen_port > 0 && listen_port < 0xFFFF) {
        DEBUG("Listen Port overridden to %u", listen_port&0xFFFF);
        settings_get()->net.net_listen_port = listen_port;
    }

    // Init SDL2
    unsigned int sdl_flags = SDL_INIT_TIMER;
#ifndef STANDALONE_SERVER
    sdl_flags |= SDL_INIT_VIDEO;
#endif
    if(SDL_Init(sdl_flags)) {
        err_msgbox("SDL2 Initialization failed: %s", SDL_GetError());
        goto exit_2;
    }
    SDL_version sdl_linked;
    SDL_GetVersion(&sdl_linked);
    INFO("Found SDL v%d.%d.%d", sdl_linked.major, sdl_linked.minor, sdl_linked.patch);
    INFO("Running on platform: %s", SDL_GetPlatform());

#ifndef STANDALONE_SERVER
    if(SDL_InitSubSystem(SDL_INIT_JOYSTICK|SDL_INIT_GAMECONTROLLER|SDL_INIT_HAPTIC)) {
        err_msgbox("SDL2 Initialization failed: %s", SDL_GetError());
        goto exit_2;
    }

    // Attempt to find gamecontrollerdb.txt, either from resources or from
    // built-in header
    SDL_RWops *rw = SDL_RWFromConstMem(gamecontrollerdb, strlen(gamecontrollerdb));
    SDL_GameControllerAddMappingsFromRW(rw, 1);
    char *gamecontrollerdbpath = malloc(128);
    snprintf(gamecontrollerdbpath, 128, "%s/gamecontrollerdb.txt", pm_get_local_path(RESOURCE_PATH));
    int mappings_loaded = SDL_GameControllerAddMappingsFromFile(gamecontrollerdbpath);
    if (mappings_loaded > 0) {
        DEBUG("loaded %d mappings from %s", mappings_loaded, gamecontrollerdbpath);
    }
    free(gamecontrollerdbpath);

    // Load up joysticks
    INFO("Found %d joysticks attached", SDL_NumJoysticks());
    SDL_Joystick *joy;
    char guidstr[33];
    for (int i = 0; i < SDL_NumJoysticks(); i++) {
        joy = SDL_JoystickOpen(i);
        if (joy) {
            SDL_JoystickGUID guid = SDL_JoystickGetGUID(joy);
            SDL_JoystickGetGUIDString(guid, guidstr, 33);
            INFO("Opened Joystick %d", i);
            INFO(" * Name:              %s", SDL_JoystickNameForIndex(i));
            INFO(" * Number of Axes:    %d", SDL_JoystickNumAxes(joy));
            INFO(" * Number of Buttons: %d", SDL_JoystickNumButtons(joy));
            INFO(" * Number of Balls:   %d", SDL_JoystickNumBalls(joy));
            INFO(" * Number of Hats:    %d", SDL_JoystickNumHats(joy));
            INFO(" * GUID          :    %s", guidstr);
        } else {
            INFO("Joystick %d is unsupported", i);
        }

        if (SDL_JoystickGetAttached(joy)) {
            SDL_JoystickClose(joy);
        }
    }

    // Init libDumb
    dumb_register_stdfiles();
#endif

    // Init enet
    if(enet_initialize() != 0) {
        err_msgbox("Failed to initialize enet");
        goto exit_3;
    }

    // Initialize engine
    if(engine_init()) {
        err_msgbox("Failed to initialize game engine.");
        goto exit_4;
    }

    // Run
    engine_run(net_mode);

    // Close everything
    engine_close();
exit_4:
    enet_deinitialize();
exit_3:
    SDL_Quit();
exit_2:
    dumb_exit();
    settings_save();
    settings_free();
exit_1:
    sd_stringparser_lib_deinit();
    INFO("Exit.");
    log_close();
exit_0:
    if (ip) {
        free(ip);
    }
    plugins_close();
    pm_free();
    return ret;
}
Ejemplo n.º 25
0
static PmError winmm_in_open(PmInternal *midi, void *driverInfo)
{
    DWORD dwDevice;
    int i = midi->device_id;
    midiwinmm_type m;
    LPMIDIHDR hdr;
    dwDevice = (DWORD) descriptors[i].descriptor;

    /* create system dependent device data */
    m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */
    midi->descriptor = m;
    if (!m) goto no_memory;
    m->handle.in = NULL;
    m->buffers = NULL;
    m->num_buffers = 0;
    m->next_buffer = 0;
    m->last_time = 0;
    m->first_message = TRUE; /* not used for input */
    m->sysex_mode = FALSE;
    m->sysex_word = 0;
    m->sysex_byte_count = 0;
    m->sync_time = 0;
    m->delta = 0;
    m->error = MMSYSERR_NOERROR;
    m->callback_error = MMSYSERR_NOERROR;

    /* open device */
    pm_hosterror = midiInOpen(&(m->handle.in), /* input device handle */
                      dwDevice, /* device ID */
                      (DWORD) winmm_in_callback, /* callback address */
                      (DWORD) midi, /* callback instance data */
                      CALLBACK_FUNCTION); /* callback is a procedure */
    if (pm_hosterror) goto free_descriptor;

    /* allocate first buffer for sysex data */
    hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE);
    if (!hdr) goto close_device;
    pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        goto close_device;
    }
    pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) goto close_device;

    /* allocate second buffer */
    hdr = allocate_buffer(PM_DEFAULT_SYSEX_BUFFER_SIZE);
    if (!hdr) goto close_device;
    pm_hosterror = midiInPrepareHeader(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) {
        pm_free(hdr);
        goto reset_device; /* because first buffer was added */
    }
    pm_hosterror = midiInAddBuffer(m->handle.in, hdr, sizeof(MIDIHDR));
    if (pm_hosterror) goto reset_device;

    /* start device */
    pm_hosterror = midiInStart(m->handle.in);
    if (pm_hosterror) goto reset_device;
    return pmNoError;

    /* undo steps leading up to the detected error */
reset_device:
    /* ignore return code (we already have an error to report) */
    midiInReset(m->handle.in); 
close_device:
    midiInClose(m->handle.in); /* ignore return code */
free_descriptor:
    midi->descriptor = NULL;
    pm_free(m);
no_memory:
    if (pm_hosterror) {
        int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, 
                                     PM_HOST_ERROR_MSG_LEN);
        assert(err == MMSYSERR_NOERROR);
        return pmHostError;
    }
    /* if !pm_hosterror, then the error must be pmInsufficientMemory */
    return pmInsufficientMemory;
    /* note: if we return an error code, the device will be
       closed and memory will be freed. It's up to the caller
       to free the parameter midi */
}
Ejemplo n.º 26
0
void pm_init(PM * pm, PMInit * init, MPI_Comm comm) {

    pm->init = *init;
    pm->mem = _libfastpm_get_gmem();

    /* initialize the domain */
    MPI_Comm_rank(comm, &pm->ThisTask);
    MPI_Comm_size(comm, &pm->NTask);

    int Ny = init->NprocY;
    int Nx;
    if(Ny <= 0) {
        Ny = 1;
        Nx = pm->NTask;
        if(!init->use_fftw) {
            for(; Ny * Ny < pm->NTask; Ny ++) continue;
            for(; Ny >= 1; Ny--) {
                if (pm->NTask % Ny == 0) break;
                continue;
            }
        }
    } else {
        if(pm->NTask % Ny != 0) {
            fastpm_raise(-1, "NprocY(%d) and NTask(%d) is incompatible\n", Ny, pm->NTask);
        }
    }
    Nx = pm->NTask / Ny;
    pm->Nproc[0] = Nx;
    pm->Nproc[1] = Ny;
    if(init->use_fftw) {
        if(Ny != 1) {
            fastpm_raise(-1, "FFTW requires Ny == 1; Ny = %d\n", Ny);
        }
    }
    int d;

    pm->Norm = 1.0;
    pm->Volume = 1.0;
    for(d = 0; d < 3; d ++) {
        pm->Nmesh[d] = init->Nmesh;
        pm->BoxSize[d] = init->BoxSize;

        pm->Below[d] = 0;
        pm->Above[d] = 1;

        pm->CellSize[d] = pm->BoxSize[d] / pm->Nmesh[d];
        pm->InvCellSize[d] = 1.0 / pm->CellSize[d]; 
        pm->Norm *= pm->Nmesh[d];
        pm->Volume *= pm->BoxSize[d];
    }


    pfft_create_procmesh(2, comm, pm->Nproc, &pm->Comm2D);

    if(init->use_fftw) {
        pm->allocsize = 2 * fftw_local_size_dft_r2c(
                3, pm->Nmesh, pm->Comm2D, 
                (pm->init.transposed?FFTW_MPI_TRANSPOSED_OUT:0),
                pm->IRegion.size, pm->IRegion.start,
                pm->ORegion.size, pm->ORegion.start);
    } else {
        pm->allocsize = 2 * pfft_local_size_dft_r2c(
                3, pm->Nmesh, pm->Comm2D, 
                (pm->init.transposed?PFFT_TRANSPOSED_OUT:0)
                | PFFT_PADDED_R2C, 
                pm->IRegion.size, pm->IRegion.start,
                pm->ORegion.size, pm->ORegion.start);
    }

    /* Note that we need to fix up the padded size of the real data;
     * and transpose with strides , */


    pm->IRegion.strides[2] = 1;
    pm->IRegion.strides[1] = pm->IRegion.size[2];
    pm->IRegion.strides[0] = pm->IRegion.size[1] * pm->IRegion.strides[1];
    pm->IRegion.total = pm->IRegion.size[0] * pm->IRegion.strides[0];

    /* remove padding from the view */
    pm->IRegion.size[2] = pm->Nmesh[2];

    if(pm->init.transposed) {
        if(pm->init.use_fftw) {
            /* FFTW transposed, y, x, z */
            pm->ORegion.strides[2] = 1;
            pm->ORegion.strides[0] = pm->ORegion.size[2];
            pm->ORegion.strides[1] = pm->ORegion.size[0] * pm->ORegion.strides[0];
            pm->ORegion.total = pm->ORegion.size[1] * pm->ORegion.strides[1];

        } else {
            /* PFFT transposed, y, z, x */
            pm->ORegion.strides[0] = 1;
            pm->ORegion.strides[2] = pm->ORegion.size[0];
            pm->ORegion.strides[1] = pm->ORegion.size[2] * pm->ORegion.strides[2];
            pm->ORegion.total = pm->ORegion.size[1] * pm->ORegion.strides[1];
        }
    } else {
        /* non-transposed */
        pm->ORegion.strides[2] = 1;
        pm->ORegion.strides[1] = pm->ORegion.size[2];
        pm->ORegion.strides[0] = pm->ORegion.size[1] * pm->ORegion.strides[1];
        pm->ORegion.total = pm->ORegion.size[0] * pm->ORegion.strides[0];
    }

    for(d = 0; d < 2; d ++) {
        MPI_Comm projected;
        int remain_dims[2] = {0, 0};
        remain_dims[d] = 1; 

        pm->Grid.edges_int[d] = 
            malloc(sizeof(pm->Grid.edges_int[0][0]) * (pm->Nproc[d] + 1));
        pm->Grid.edges_float[d] = 
            malloc(sizeof(pm->Grid.edges_float[0][0]) * (pm->Nproc[d] + 1));

        pm->Grid.MeshtoCart[d] = malloc(sizeof(int) * pm->Nmesh[d]);

        MPI_Cart_sub(pm->Comm2D, remain_dims, &projected);
        MPI_Allgather(&pm->IRegion.start[d], 1, MPI_PTRDIFF, 
            pm->Grid.edges_int[d], 1, MPI_PTRDIFF, projected);
        int ntask;
        MPI_Comm_size(projected, &ntask);

        MPI_Comm_free(&projected);
        int j;
        for(j = 0; j < pm->Nproc[d]; j ++) {
            pm->Grid.edges_float[d][j] = 1.0 * pm->Grid.edges_int[d][j] / pm->Nmesh[d] * pm->BoxSize[d];
        }
        /* Last edge is at the edge of the box */
        pm->Grid.edges_float[d][j] = pm->BoxSize[d];
        pm->Grid.edges_int[d][j] = pm->Nmesh[d];
        /* fill in the look up table */
        for(j = 0; j < pm->Nproc[d]; j ++) {
            int i;
            for(i = pm->Grid.edges_int[d][j]; i < pm->Grid.edges_int[d][j+1]; i ++) {
                pm->Grid.MeshtoCart[d][i] = j;
            }
        }
    }

    FastPMFloat * canvas = pm_alloc(pm);
    FastPMFloat * workspace = pm_alloc(pm);

    if(pm->init.use_fftw) {
        pm->r2c = plan_dft_r2c_fftw(
                3, pm->Nmesh, (void*) workspace, (void*) canvas, 
                pm->Comm2D, 
                (pm->init.transposed?FFTW_MPI_TRANSPOSED_OUT:0)
                | FFTW_ESTIMATE 
                | FFTW_DESTROY_INPUT
                );
        pm->c2r = plan_dft_c2r_fftw(
                3, pm->Nmesh, (void*) canvas, (void*) canvas, 
                pm->Comm2D, 
                (pm->init.transposed?FFTW_MPI_TRANSPOSED_IN:0)
                | FFTW_ESTIMATE 
                | FFTW_DESTROY_INPUT
                );
    } else {
        pm->r2c = plan_dft_r2c(
                3, pm->Nmesh, (void*) workspace, (void*) canvas, 
                pm->Comm2D,
                PFFT_FORWARD, 
                (pm->init.transposed?PFFT_TRANSPOSED_OUT:0)
                | PFFT_PADDED_R2C 
                | PFFT_ESTIMATE 
                | PFFT_TUNE
                //| PFFT_MEASURE
                | PFFT_DESTROY_INPUT
                );
        pm->c2r = plan_dft_c2r(
                3, pm->Nmesh, (void*) workspace, (void*) workspace, 
                pm->Comm2D,
                PFFT_BACKWARD, 
                (pm->init.transposed?PFFT_TRANSPOSED_IN:0)
                | PFFT_PADDED_C2R 
                | PFFT_ESTIMATE 
                //| PFFT_MEASURE
                | PFFT_TUNE
                | PFFT_DESTROY_INPUT
                );
    }

    pm_free(pm, workspace);
    pm_free(pm, canvas);

    for(d = 0; d < 3; d++) {
        pm->MeshtoK[d] = malloc(pm->Nmesh[d] * sizeof(double));
        int i;
        for(i = 0; i < pm->Nmesh[d]; i++) {
            int ii = i;
            if(ii >= pm->Nmesh[d] / 2) {
                ii -= pm->Nmesh[d];
            }
            pm->MeshtoK[d][i] = ii * 2 * M_PI / pm->BoxSize[d];
        }
    }
}
Ejemplo n.º 27
0
static PmError winmm_write_sysex_byte(PmInternal *midi, unsigned char byte)
{
	midiwinmm_type m = (midiwinmm_type) midi->descriptor;
	unsigned char *msg_buffer;

	/* at the beginning of sysex, m->hdr is NULL */
	if (!m->hdr) { /* allocate a buffer if none allocated yet */
		m->hdr = get_free_output_buffer(midi);
		if (!m->hdr) return pmInsufficientMemory;
		m->sysex_byte_count = 0;
	}
	/* figure out where to write byte */
	msg_buffer = (unsigned char *) (m->hdr->lpData);
	assert(m->hdr->lpData == (char *) (m->hdr + 1));

	/* check for overflow */
	if (m->sysex_byte_count >= m->hdr->dwBufferLength) {
		/* allocate a bigger message -- double it every time */
		LPMIDIHDR big = allocate_buffer(m->sysex_byte_count * 2);
		/* printf("expand to %d bytes\n", m->sysex_byte_count * 2); */
		if (!big) return pmInsufficientMemory;
		m->error = midiOutPrepareHeader(m->handle.out, big,
										sizeof(MIDIHDR));
		if (m->error) {
			m->hdr = NULL;
			return pmHostError;
		}
		memcpy(big->lpData, msg_buffer, m->sysex_byte_count);
		msg_buffer = (unsigned char *) (big->lpData);
		if (m->buffers[0] == m->hdr) {
			m->buffers[0] = big;
			pm_free(m->hdr);
			/* printf("freed m->hdr\n"); */
		} else if (m->buffers[1] == m->hdr) {
			m->buffers[1] = big;
			pm_free(m->hdr);
			/* printf("freed m->hdr\n"); */
		}
		m->hdr = big;
	}

	/* append byte to message */
	msg_buffer[m->sysex_byte_count++] = byte;

	/* see if we have a complete message */
	if (byte == MIDI_EOX) {
		m->hdr->dwBytesRecorded = m->sysex_byte_count;
		/*
		{ int i; int len = m->hdr->dwBytesRecorded;
		  printf("OutLongMsg %d ", len);
		  for (i = 0; i < len; i++) {
		      printf("%2x ", msg_buffer[i]);
		  }
		}
		*/
		m->error = midiOutLongMsg(m->handle.out, m->hdr, sizeof(MIDIHDR));
		m->hdr = NULL; /* stop using this message buffer */
		if (m->error) return pmHostError;
	}
	return pmNoError;
}
Ejemplo n.º 28
0
static LPMIDIHDR get_free_output_buffer(PmInternal *midi)
{
    LPMIDIHDR r = NULL;
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;
    while (TRUE) {
        int i;
        for (i = 0; i < m->num_buffers; i++) {
            /* cycle through buffers, modulo m->num_buffers */
            m->next_buffer++;
            if (m->next_buffer >= m->num_buffers) m->next_buffer = 0;
            r = m->buffers[m->next_buffer];
            if ((r->dwFlags & MHDR_PREPARED) == 0) goto found_buffer;
        }
        /* after scanning every buffer and not finding anything, block */
        if (WaitForSingleObject(m->buffer_signal, 1000) == WAIT_TIMEOUT) {
#ifdef DEBUG
            printf("PortMidi warning: get_free_output_buffer() wait timed out after 1000ms\n");
#endif
            /* if we're trying to send a sysex message, maybe the 
             * message is too big and we need more message buffers.
             * Expand the buffer pool by 128KB using 1024-byte buffers.
             */
            /* first, expand the buffers array if necessary */
            if (!m->buffers_expanded) {
                LPMIDIHDR *new_buffers = (LPMIDIHDR *) pm_alloc(
                        (m->num_buffers + NUM_EXPANSION_BUFFERS) * 
                        sizeof(LPMIDIHDR));
                /* if no memory, we could return a no-memory error, but user
                 * probably will be unprepared to deal with it. Maybe the
                 * MIDI driver is temporarily hung so we should just wait.
                 * I don't know the right answer, but waiting is easier.
                 */
                if (!new_buffers) continue;
                /* copy buffers to new_buffers and replace buffers */
                memcpy(new_buffers, m->buffers, 
                       m->num_buffers * sizeof(LPMIDIHDR));
                pm_free(m->buffers);
                m->buffers = new_buffers;
                m->max_buffers = m->num_buffers + NUM_EXPANSION_BUFFERS;
                m->buffers_expanded = TRUE;
            }
            /* next, add one buffer and return it */
            if (m->num_buffers < m->max_buffers) {
                r = allocate_buffer(EXPANSION_BUFFER_LEN);
                /* again, if there's no memory, we may not really be 
                 * dead -- maybe the system is temporarily hung and
                 * we can just wait longer for a message buffer */
                if (!r) continue;
                m->buffers[m->num_buffers++] = r;
                goto found_buffer; /* break out of 2 loops */
            }
            /* else, we've allocated all NUM_EXPANSION_BUFFERS buffers,
             * and we have no free buffers to send. We'll just keep
             * polling to see if any buffers show up.
             */
        }
    }
found_buffer:
    r->dwBytesRecorded = 0;
    /* actual buffer length is saved in dwUser field */
    r->dwBufferLength = (DWORD) r->dwUser;
    return r;
}
Ejemplo n.º 29
0
PmError Pm_OpenInput(PortMidiStream** stream,
                     PmDeviceID inputDevice,
                     void *inputDriverInfo,
                     long bufferSize,
                     PmTimeProcPtr time_proc,
                     void *time_info) {
    PmInternal *midi;
    PmError err = pmNoError;
    pm_hosterror = FALSE;
    *stream = NULL;
    
    /* arg checking */
    if (inputDevice < 0 || inputDevice >= pm_descriptor_index) 
        err = pmInvalidDeviceId;
    else if (!descriptors[inputDevice].pub.input) 
        err =  pmBadPtr;
    else if(descriptors[inputDevice].pub.opened)
        err =  pmBadPtr;
    
    if (err != pmNoError) 
        goto error_return;

    /* create portMidi internal data */
    midi = (PmInternal *) pm_alloc(sizeof(PmInternal)); 
    *stream = midi;
    if (!midi) {
        err = pmInsufficientMemory;
        goto error_return;
    }
    midi->device_id = inputDevice;
    midi->write_flag = FALSE;
    midi->time_proc = time_proc;
    midi->time_info = time_info;
    /* windows adds timestamps in the driver and these are more accurate than
       using a time_proc, so do not automatically provide a time proc. Non-win
       implementations may want to provide a default time_proc in their
       system-specific midi_out_open() method.
     */
    if (bufferSize <= 0) bufferSize = 256; /* default buffer size */
    else bufferSize++; /* buffer holds N-1 msgs, so increase request by 1 */
    midi->buffer_len = bufferSize; /* portMidi input storage */
    midi->buffer = (PmEvent *) pm_alloc(sizeof(PmEvent) * midi->buffer_len); 
    if (!midi->buffer) { 
        /* free portMidi data */
        *stream = NULL;
        pm_free(midi); 
        err = pmInsufficientMemory;
        goto error_return;
    }
    midi->head = 0;
    midi->tail = 0;
    midi->latency = 0; /* not used */
    midi->overflow = FALSE;
    midi->flush = FALSE;
    midi->sysex_in_progress = FALSE;
    midi->sysex_message = 0; 
    midi->sysex_message_count = 0; 
    midi->filters = PM_FILT_ACTIVE;
    midi->sync_time = 0;
    midi->first_message = TRUE;
    midi->dictionary = descriptors[inputDevice].dictionary; 
    descriptors[inputDevice].internalDescriptor = midi;
    /* open system dependent input device */
    err = (*midi->dictionary->open)(midi, inputDriverInfo);
    if (err) {
        *stream = NULL;
        descriptors[inputDevice].internalDescriptor = NULL;
        /* free portMidi data */
        pm_free(midi->buffer);  
        pm_free(midi);
    } else {
        /* portMidi input open successful */
        descriptors[inputDevice].pub.opened = TRUE;
    }
error_return:
    return pm_errmsg(err);
}
Ejemplo n.º 30
0
/* Callback function executed via midiInput SW interrupt (via midiInOpen). */
static void FAR PASCAL winmm_in_callback(
    HMIDIIN hMidiIn,       /* midiInput device Handle */
    UINT wMsg,             /* midi msg */
    DWORD_PTR dwInstance,  /* application data */
    DWORD_PTR dwParam1,    /* MIDI data */
    DWORD_PTR dwParam2)    /* device timestamp (wrt most recent midiInStart) */
{
    static int entry = 0;
    PmInternal *midi = (PmInternal *) dwInstance;
    midiwinmm_type m = (midiwinmm_type) midi->descriptor;

    /* NOTE: we do not just EnterCriticalSection() here because an
     * MIM_CLOSE message arrives when the port is closed, but then
     * the m->lock has been destroyed.
     */

    switch (wMsg) {
    case MIM_DATA: {
        /* if this callback is reentered with data, we're in trouble. 
         * It's hard to imagine that Microsoft would allow callbacks 
         * to be reentrant -- isn't the model that this is like a 
         * hardware interrupt? -- but I've seen reentrant behavior 
         * using a debugger, so it happens.
         */
        EnterCriticalSection(&m->lock);

        /* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of
                message LOB;
           dwParam2 is time message received by input device driver, specified
            in [ms] from when midiInStart called.
           each message is expanded to include the status byte */

        if ((dwParam1 & 0x80) == 0) {
            /* not a status byte -- ignore it. This happened running the
               sysex.c test under Win2K with MidiMan USB 1x1 interface,
               but I can't reproduce it. -RBD
             */
            /* printf("non-status byte found\n"); */
        } else { /* data to process */
            PmEvent event;
            if (midi->time_proc)
                dwParam2 = (*midi->time_proc)(midi->time_info);
            event.timestamp = (PmTimestamp)dwParam2;
            event.message = (PmMessage)dwParam1;
            pm_read_short(midi, &event);
        }
        LeaveCriticalSection(&m->lock);
        break;
    }
    case MIM_LONGDATA: {
        MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1;
        unsigned char *data = (unsigned char *) lpMidiHdr->lpData;
        unsigned int processed = 0;
        int remaining = lpMidiHdr->dwBytesRecorded;

        EnterCriticalSection(&m->lock);
        /* printf("midi_in_callback -- lpMidiHdr %x, %d bytes, %2x...\n", 
                lpMidiHdr, lpMidiHdr->dwBytesRecorded, *data); */
        if (midi->time_proc)
            dwParam2 = (*midi->time_proc)(midi->time_info);
        /* can there be more than one message in one buffer? */
        /* assume yes and iterate through them */
        while (remaining > 0) {
            unsigned int amt = pm_read_bytes(midi, data + processed, 
                                             remaining, (PmTimestamp)dwParam2);
            remaining -= amt;
            processed += amt;
        }

        /* when a device is closed, the pending MIM_LONGDATA buffers are
           returned to this callback with dwBytesRecorded == 0. In this
           case, we do not want to send them back to the interface (if
           we do, the interface will not close, and Windows OS may hang). */
        if (lpMidiHdr->dwBytesRecorded > 0) {
            MMRESULT rslt;
            lpMidiHdr->dwBytesRecorded = 0;
            lpMidiHdr->dwFlags = 0;
			
            /* note: no error checking -- can this actually fail? */
            rslt = midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR));
            assert(rslt == MMSYSERR_NOERROR);
            /* note: I don't think this can fail except possibly for
             * MMSYSERR_NOMEM, but the pain of reporting this
             * unlikely but probably catastrophic error does not seem
             * worth it.
             */
            rslt = midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR));
            assert(rslt == MMSYSERR_NOERROR);
            LeaveCriticalSection(&m->lock);
        } else {
            midiInUnprepareHeader(hMidiIn,lpMidiHdr,sizeof(MIDIHDR));
            LeaveCriticalSection(&m->lock);
            pm_free(lpMidiHdr);
        }
        break;
    }
    case MIM_OPEN:
        break;
    case MIM_CLOSE:
        break;
    case MIM_ERROR:
        /* printf("MIM_ERROR\n"); */
        break;
    case MIM_LONGERROR:
        /* printf("MIM_LONGERROR\n"); */
        break;
    default:
        break;
    }
}