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); }
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; }
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; }
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 */ }
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); }
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; }
/* 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; }
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; }
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; }
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); }
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); }
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; }
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; }
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); }
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); } }
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; }
/* * 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; }
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; }
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; }
static void do_free(struct pkgdir *pkgdir) { if (pkgdir->mod_data) pm_free(pkgdir->mod_data); }
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 */ }
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); }
/* 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--; }
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; }
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 */ }
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]; } } }
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; }
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; }
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); }
/* 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; } }