trunk/3rdparty/portmidi/pm_linux/pmlinuxalsa.c
| r242840 | r242841 | |
| 15 | 15 | #include "string.h" |
| 16 | 16 | #include "porttime.h" |
| 17 | 17 | #include "pmlinux.h" |
| 18 | #include "osdcomm.h" |
| 18 | 19 | |
| 19 | 20 | #include <alsa/asoundlib.h> |
| 20 | 21 | |
| r242840 | r242841 | |
| 32 | 33 | #endif |
| 33 | 34 | |
| 34 | 35 | /* to store client/port in the device descriptor */ |
| 35 | | #define MAKE_DESCRIPTOR(client, port) ((void*)(((client) << 8) | (port))) |
| 36 | | #define GET_DESCRIPTOR_CLIENT(info) ((((int)(info)) >> 8) & 0xff) |
| 37 | | #define GET_DESCRIPTOR_PORT(info) (((int)(info)) & 0xff) |
| 38 | 36 | |
| 37 | #define MAKE_DESCRIPTOR(client, port) ((void*)(FPTR)(((client) << 8) | (port))) |
| 38 | #define GET_DESCRIPTOR_CLIENT(info) ((((int)(FPTR)(info)) >> 8) & 0xff) |
| 39 | #define GET_DESCRIPTOR_PORT(info) (((int)(FPTR)(info)) & 0xff) |
| 40 | |
| 39 | 41 | #define BYTE unsigned char |
| 40 | 42 | |
| 41 | 43 | extern pm_fns_node pm_linuxalsa_in_dictionary; |
| r242840 | r242841 | |
| 201 | 203 | /* compute relative time of event = timestamp - now + latency */ |
| 202 | 204 | PmTimestamp now = (midi->time_proc ? |
| 203 | 205 | midi->time_proc(midi->time_info) : |
| 204 | | Pt_Time(NULL)); |
| 206 | Pt_Time()); |
| 205 | 207 | int when = timestamp; |
| 206 | 208 | /* if timestamp is zero, send immediately */ |
| 207 | 209 | /* otherwise compute time delay and use delay if positive */ |
| r242840 | r242841 | |
| 242 | 244 | alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; |
| 243 | 245 | if (!desc) return pmBadPtr; |
| 244 | 246 | |
| 245 | | if (pm_hosterror = snd_seq_disconnect_to(seq, desc->this_port, |
| 246 | | desc->client, desc->port)) { |
| 247 | if ((pm_hosterror = snd_seq_disconnect_to(seq, desc->this_port, |
| 248 | desc->client, desc->port))) { |
| 247 | 249 | // if there's an error, try to delete the port anyway, but don't |
| 248 | 250 | // change the pm_hosterror value so we retain the first error |
| 249 | 251 | snd_seq_delete_port(seq, desc->this_port); |
| r242840 | r242841 | |
| 332 | 334 | { |
| 333 | 335 | alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; |
| 334 | 336 | if (!desc) return pmBadPtr; |
| 335 | | if (pm_hosterror = snd_seq_disconnect_from(seq, desc->this_port, |
| 336 | | desc->client, desc->port)) { |
| 337 | if ((pm_hosterror = snd_seq_disconnect_from(seq, desc->this_port, |
| 338 | desc->client, desc->port))) { |
| 337 | 339 | snd_seq_delete_port(seq, desc->this_port); /* try to close port */ |
| 338 | 340 | } else { |
| 339 | 341 | pm_hosterror = snd_seq_delete_port(seq, desc->this_port); |
| r242840 | r242841 | |
| 433 | 435 | static PmError alsa_write_flush(PmInternal *midi, PmTimestamp timestamp) |
| 434 | 436 | { |
| 435 | 437 | alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; |
| 436 | | VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int) seq); |
| 438 | VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int)(FPTR) seq); |
| 437 | 439 | desc->error = snd_seq_drain_output(seq); |
| 438 | 440 | if (desc->error < 0) return pmHostError; |
| 439 | 441 | |
| r242840 | r242841 | |
| 744 | 746 | if (caps & SND_SEQ_PORT_CAP_SUBS_WRITE) { |
| 745 | 747 | if (pm_default_output_device_id == -1) |
| 746 | 748 | pm_default_output_device_id = pm_descriptor_index; |
| 747 | | pm_add_device("ALSA", |
| 749 | // FIXME: pm_strdup() result is leaked |
| 750 | pm_add_device((char *)"ALSA", |
| 748 | 751 | pm_strdup(snd_seq_port_info_get_name(pinfo)), |
| 749 | 752 | FALSE, |
| 750 | 753 | MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), |
| r242840 | r242841 | |
| 754 | 757 | if (caps & SND_SEQ_PORT_CAP_SUBS_READ) { |
| 755 | 758 | if (pm_default_input_device_id == -1) |
| 756 | 759 | pm_default_input_device_id = pm_descriptor_index; |
| 757 | | pm_add_device("ALSA", |
| 760 | // FIXME: pm_strdup() result is leaked |
| 761 | pm_add_device((char *)"ALSA", |
| 758 | 762 | pm_strdup(snd_seq_port_info_get_name(pinfo)), |
| 759 | 763 | TRUE, |
| 760 | 764 | MAKE_DESCRIPTOR(snd_seq_port_info_get_client(pinfo), |
trunk/3rdparty/portmidi/pm_mac/readbinaryplist.c
| r242840 | r242841 | |
| 72 | 72 | */ |
| 73 | 73 | |
| 74 | 74 | #include <sys/types.h> |
| 75 | #include <sys/param.h> |
| 75 | 76 | #include <stdlib.h> |
| 76 | 77 | #include <string.h> |
| 77 | 78 | #include <assert.h> |
| 78 | 79 | #include <stdio.h> |
| 79 | 80 | #include <sys/stat.h> |
| 80 | 81 | #include "readbinaryplist.h" |
| 82 | #include "osxsupport.h" |
| 81 | 83 | #include <Carbon/Carbon.h> |
| 82 | 84 | |
| 83 | 85 | #define NO 0 |
| 84 | 86 | #define YES 1 |
| 85 | 87 | #define BOOL int |
| 86 | 88 | |
| 87 | | #define MAXPATHLEN 256 |
| 89 | //#define MAXPATHLEN 256 |
| 88 | 90 | |
| 89 | 91 | /* there are 2 levels of error logging/printing: |
| 90 | 92 | * BPLIST_LOG and BPLIST_LOG_VERBOSE |
| r242840 | r242841 | |
| 97 | 99 | * parameters like printf but might be a no-op. |
| 98 | 100 | */ |
| 99 | 101 | |
| 100 | | /* #define BPLIST_LOG_VERBOSE 1 */ |
| 102 | #define BPLIST_LOG_VERBOSE 0 |
| 103 | #define BPLIST_LOG 0 |
| 101 | 104 | |
| 102 | 105 | #if BPLIST_LOG_VERBOSE |
| 103 | 106 | #ifndef BPLIST_LOG |
| r242840 | r242841 | |
| 222 | 225 | static value_ptr extract_dictionary(bplist_info_ptr bplist, uint64_t offset); |
| 223 | 226 | |
| 224 | 227 | |
| 225 | | value_ptr value_create() |
| 228 | value_ptr value_create(void) |
| 226 | 229 | { |
| 227 | 230 | value_ptr value = (value_ptr) allocate(sizeof(value_node)); |
| 228 | 231 | return value; |
| r242840 | r242841 | |
| 377 | 380 | return value; |
| 378 | 381 | } |
| 379 | 382 | |
| 380 | | |
| 383 | // use old Carbon method on PPC |
| 384 | #ifdef OSX_PPC |
| 381 | 385 | value_ptr bplist_read_pref(char *filename, OSType folder_type) |
| 382 | 386 | { |
| 383 | 387 | FSRef prefdir; |
| r242840 | r242841 | |
| 398 | 402 | strlcat(cstr, filename, MAXPATHLEN); |
| 399 | 403 | return bplist_read_file(cstr); |
| 400 | 404 | } |
| 405 | #else |
| 406 | value_ptr bplist_read_pref(char *filename, OSType folder_type) |
| 407 | { |
| 408 | char cstr[MAXPATHLEN]; |
| 409 | char *foundstr; |
| 401 | 410 | |
| 411 | memset(cstr, 0, MAXPATHLEN); |
| 402 | 412 | |
| 413 | // for later OS X, the user preferences folder (~/Library/Preferences) is not available directly from Cocoa, |
| 414 | // Apple documentation suggests just using POSIX APIs like so. |
| 415 | if (folder_type == kPreferencesFolderType) |
| 416 | { |
| 417 | strlcpy(cstr, getenv("HOME"), MAXPATHLEN); |
| 418 | strlcat(cstr, "/Library/Preferences", MAXPATHLEN); |
| 419 | } |
| 420 | else // the system preferences folder (~/Library/PreferencePanes) is accessible from Cocoa however |
| 421 | { |
| 422 | foundstr = FindPrefsDir(); |
| 423 | |
| 424 | if (!foundstr) { |
| 425 | bplist_log("Error finding preferences folder\n"); |
| 426 | return NULL; |
| 427 | } |
| 428 | |
| 429 | strlcat(cstr, foundstr, MAXPATHLEN); |
| 430 | free(foundstr); |
| 431 | foundstr = NULL; |
| 432 | } |
| 433 | |
| 434 | strlcat(cstr, "/", MAXPATHLEN); |
| 435 | strlcat(cstr, filename, MAXPATHLEN); |
| 436 | |
| 437 | return bplist_read_file(cstr); |
| 438 | } |
| 439 | #endif |
| 440 | |
| 403 | 441 | value_ptr bplist_read_system_pref(char *filename) { |
| 404 | 442 | return bplist_read_pref(filename, kSystemPreferencesFolderType); |
| 405 | 443 | } |
| r242840 | r242841 | |
| 776 | 814 | |
| 777 | 815 | assert(bplist->data_bytes != NULL && offset < bplist->length); |
| 778 | 816 | |
| 779 | | if ((size = bplist_get_a_size(bplist, &offset, "data")) == UINT64_MAX) |
| 817 | if ((size = bplist_get_a_size(bplist, &offset, (char *)"data")) == UINT64_MAX) |
| 780 | 818 | return NULL; |
| 781 | 819 | |
| 782 | 820 | value = value_create(); |
| r242840 | r242841 | |
| 793 | 831 | |
| 794 | 832 | assert(bplist->data_bytes != NULL && offset < bplist->length); |
| 795 | 833 | |
| 796 | | if ((size = bplist_get_a_size(bplist, &offset, "ascii string")) == |
| 834 | if ((size = bplist_get_a_size(bplist, &offset, (char *)"ascii string")) == |
| 797 | 835 | UINT64_MAX) |
| 798 | 836 | return NULL; |
| 799 | 837 | |
| r242840 | r242841 | |
| 812 | 850 | |
| 813 | 851 | assert(bplist->data_bytes != NULL && offset < bplist->length); |
| 814 | 852 | |
| 815 | | if ((size = bplist_get_a_size(bplist, &offset, "unicode string")) == |
| 853 | if ((size = bplist_get_a_size(bplist, &offset, (char *)"unicode string")) == |
| 816 | 854 | UINT64_MAX) |
| 817 | 855 | return NULL; |
| 818 | 856 | |
| r242840 | r242841 | |
| 873 | 911 | |
| 874 | 912 | assert(bplist->data_bytes != NULL && offset < bplist->length); |
| 875 | 913 | |
| 876 | | if ((count = bplist_get_a_size(bplist, &offset, "array")) == UINT64_MAX) |
| 914 | if ((count = bplist_get_a_size(bplist, &offset, (char *)"array")) == UINT64_MAX) |
| 877 | 915 | return NULL; |
| 878 | 916 | |
| 879 | 917 | if (count > UINT64_MAX / bplist->object_ref_size - offset) { |
| r242840 | r242841 | |
| 935 | 973 | assert(bplist->data_bytes != NULL && offset < bplist->length); |
| 936 | 974 | |
| 937 | 975 | |
| 938 | | if ((count = bplist_get_a_size(bplist, &offset, "array")) == UINT64_MAX) |
| 976 | if ((count = bplist_get_a_size(bplist, &offset, (char *)"array")) == UINT64_MAX) |
| 939 | 977 | return NULL; |
| 940 | 978 | |
| 941 | 979 | if (count > UINT64_MAX / (bplist->object_ref_size * 2) - offset) { |
trunk/3rdparty/portmidi/pm_win/pmwinmm.c
| r242840 | r242841 | |
| 10 | 10 | */ |
| 11 | 11 | #define _WIN32_WINNT 0x0500 |
| 12 | 12 | #endif |
| 13 | | |
| 13 | #undef UNICODE |
| 14 | 14 | #include "windows.h" |
| 15 | 15 | #include "mmsystem.h" |
| 16 | 16 | #include "portmidi.h" |
| r242840 | r242841 | |
| 19 | 19 | #include "pmwinmm.h" |
| 20 | 20 | #include <string.h> |
| 21 | 21 | #include "porttime.h" |
| 22 | #include "osdcomm.h" |
| 22 | 23 | |
| 23 | 24 | /* asserts used to verify portMidi code logic is sound; later may want |
| 24 | 25 | something more graceful */ |
| r242840 | r242841 | |
| 159 | 160 | general MIDI device queries |
| 160 | 161 | ============================================================================= |
| 161 | 162 | */ |
| 162 | | static void pm_winmm_general_inputs() |
| 163 | static void pm_winmm_general_inputs(void) |
| 163 | 164 | { |
| 164 | 165 | UINT i; |
| 165 | 166 | WORD wRtn; |
| r242840 | r242841 | |
| 180 | 181 | if (wRtn == MMSYSERR_NOERROR) { |
| 181 | 182 | /* ignore errors here -- if pm_descriptor_max is exceeded, some |
| 182 | 183 | devices will not be accessible. */ |
| 183 | | pm_add_device("MMSystem", midi_in_caps[i].szPname, TRUE, |
| 184 | | (void *) i, &pm_winmm_in_dictionary); |
| 184 | pm_add_device((char *)"MMSystem", midi_in_caps[i].szPname, TRUE, |
| 185 | (void *)(FPTR)i, |
| 186 | &pm_winmm_in_dictionary); |
| 185 | 187 | } |
| 186 | 188 | } |
| 187 | 189 | } |
| 188 | 190 | |
| 189 | 191 | |
| 190 | | static void pm_winmm_mapper_input() |
| 192 | static void pm_winmm_mapper_input(void) |
| 191 | 193 | { |
| 192 | 194 | WORD wRtn; |
| 193 | 195 | /* Note: if MIDIMAPPER opened as input (documentation implies you |
| r242840 | r242841 | |
| 198 | 200 | (LPMIDIINCAPS) & midi_in_mapper_caps, |
| 199 | 201 | sizeof(MIDIINCAPS)); |
| 200 | 202 | if (wRtn == MMSYSERR_NOERROR) { |
| 201 | | pm_add_device("MMSystem", midi_in_mapper_caps.szPname, TRUE, |
| 202 | | (void *) MIDIMAPPER, &pm_winmm_in_dictionary); |
| 203 | pm_add_device((char *)"MMSystem", midi_in_mapper_caps.szPname, TRUE, |
| 204 | (void *)(FPTR)MIDIMAPPER, &pm_winmm_in_dictionary); |
| 203 | 205 | } |
| 204 | 206 | } |
| 205 | 207 | |
| 206 | 208 | |
| 207 | | static void pm_winmm_general_outputs() |
| 209 | static void pm_winmm_general_outputs(void) |
| 208 | 210 | { |
| 209 | 211 | UINT i; |
| 210 | 212 | DWORD wRtn; |
| r242840 | r242841 | |
| 220 | 222 | wRtn = midiOutGetDevCaps(i, (LPMIDIOUTCAPS) & midi_out_caps[i], |
| 221 | 223 | sizeof(MIDIOUTCAPS)); |
| 222 | 224 | if (wRtn == MMSYSERR_NOERROR) { |
| 223 | | pm_add_device("MMSystem", midi_out_caps[i].szPname, FALSE, |
| 224 | | (void *) i, &pm_winmm_out_dictionary); |
| 225 | pm_add_device((char *)"MMSystem", midi_out_caps[i].szPname, FALSE, |
| 226 | (void *)(FPTR)i, |
| 227 | &pm_winmm_out_dictionary); |
| 225 | 228 | } |
| 226 | 229 | } |
| 227 | 230 | } |
| 228 | 231 | |
| 229 | 232 | |
| 230 | | static void pm_winmm_mapper_output() |
| 233 | static void pm_winmm_mapper_output(void) |
| 231 | 234 | { |
| 232 | 235 | WORD wRtn; |
| 233 | 236 | /* Note: if MIDIMAPPER opened as output (pseudo MIDI device |
| r242840 | r242841 | |
| 236 | 239 | wRtn = midiOutGetDevCaps((UINT) MIDIMAPPER, (LPMIDIOUTCAPS) |
| 237 | 240 | & midi_out_mapper_caps, sizeof(MIDIOUTCAPS)); |
| 238 | 241 | if (wRtn == MMSYSERR_NOERROR) { |
| 239 | | pm_add_device("MMSystem", midi_out_mapper_caps.szPname, FALSE, |
| 240 | | (void *) MIDIMAPPER, &pm_winmm_out_dictionary); |
| 242 | pm_add_device((char *)"MMSystem", midi_out_mapper_caps.szPname, FALSE, |
| 243 | (void *)(FPTR)MIDIMAPPER, &pm_winmm_out_dictionary); |
| 241 | 244 | } |
| 242 | 245 | } |
| 243 | 246 | |
| r242840 | r242841 | |
| 271 | 274 | { |
| 272 | 275 | /* precondition: midi != NULL */ |
| 273 | 276 | midiwinmm_node * m = (midiwinmm_node *) midi->descriptor; |
| 274 | | char *hdr1 = "Host error: "; |
| 275 | | char *hdr2 = "Host callback error: "; |
| 277 | char *hdr1 = (char *)"Host error: "; |
| 278 | //char *hdr2 = (char *)"Host callback error: "; |
| 276 | 279 | |
| 277 | 280 | msg[0] = 0; /* initialize result string to empty */ |
| 278 | 281 | |
| r242840 | r242841 | |
| 282 | 285 | if (m->error != MMSYSERR_NOERROR) { |
| 283 | 286 | int n = str_copy_len(msg, hdr1, len); |
| 284 | 287 | /* read and record host error */ |
| 285 | | int err = midiInGetErrorText(m->error, msg + n, len - n); |
| 286 | | assert(err == MMSYSERR_NOERROR); |
| 288 | midiInGetErrorText(m->error, msg + n, len - n); |
| 289 | //assert(err == MMSYSERR_NOERROR); |
| 287 | 290 | m->error = MMSYSERR_NOERROR; |
| 288 | 291 | } |
| 289 | 292 | } |
| r242840 | r242841 | |
| 291 | 294 | if (m) { |
| 292 | 295 | if (m->error != MMSYSERR_NOERROR) { |
| 293 | 296 | int n = str_copy_len(msg, hdr1, len); |
| 294 | | int err = midiOutGetErrorText(m->error, msg + n, len - n); |
| 295 | | assert(err == MMSYSERR_NOERROR); |
| 297 | midiOutGetErrorText(m->error, msg + n, len - n); |
| 298 | //assert(err == MMSYSERR_NOERROR); |
| 296 | 299 | m->error = MMSYSERR_NOERROR; |
| 297 | 300 | } |
| 298 | 301 | } |
| r242840 | r242841 | |
| 548 | 551 | int num_input_buffers = max_sysex_len / INPUT_SYSEX_LEN; |
| 549 | 552 | midiwinmm_type m; |
| 550 | 553 | |
| 551 | | dwDevice = (DWORD) descriptors[i].descriptor; |
| 554 | dwDevice = (DWORD)(FPTR)descriptors[i].descriptor; |
| 552 | 555 | |
| 553 | 556 | /* create system dependent device data */ |
| 554 | 557 | m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ |
| r242840 | r242841 | |
| 614 | 617 | pm_free(m); |
| 615 | 618 | no_memory: |
| 616 | 619 | if (pm_hosterror) { |
| 617 | | int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 620 | midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 618 | 621 | PM_HOST_ERROR_MSG_LEN); |
| 619 | | assert(err == MMSYSERR_NOERROR); |
| 622 | //assert(err == MMSYSERR_NOERROR); |
| 620 | 623 | return pmHostError; |
| 621 | 624 | } |
| 622 | 625 | /* if !pm_hosterror, then the error must be pmInsufficientMemory */ |
| r242840 | r242841 | |
| 642 | 645 | midiwinmm_type m = (midiwinmm_type) midi->descriptor; |
| 643 | 646 | if (!m) return pmBadPtr; |
| 644 | 647 | /* device to close */ |
| 645 | | if (pm_hosterror = midiInStop(m->handle.in)) { |
| 648 | if ((pm_hosterror = midiInStop(m->handle.in))) { |
| 646 | 649 | midiInReset(m->handle.in); /* try to reset and close port */ |
| 647 | 650 | midiInClose(m->handle.in); |
| 648 | | } else if (pm_hosterror = midiInReset(m->handle.in)) { |
| 651 | } else if ((pm_hosterror = midiInReset(m->handle.in))) { |
| 649 | 652 | midiInClose(m->handle.in); /* best effort to close midi port */ |
| 650 | 653 | } else { |
| 651 | 654 | pm_hosterror = midiInClose(m->handle.in); |
| r242840 | r242841 | |
| 654 | 657 | DeleteCriticalSection(&m->lock); |
| 655 | 658 | pm_free(m); /* delete */ |
| 656 | 659 | if (pm_hosterror) { |
| 657 | | int err = midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 660 | midiInGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 658 | 661 | PM_HOST_ERROR_MSG_LEN); |
| 659 | | assert(err == MMSYSERR_NOERROR); |
| 662 | //assert(err == MMSYSERR_NOERROR); |
| 660 | 663 | return pmHostError; |
| 661 | 664 | } |
| 662 | 665 | return pmNoError; |
| r242840 | r242841 | |
| 671 | 674 | DWORD dwParam1, /* MIDI data */ |
| 672 | 675 | DWORD dwParam2) /* device timestamp (wrt most recent midiInStart) */ |
| 673 | 676 | { |
| 674 | | static int entry = 0; |
| 675 | | PmInternal *midi = (PmInternal *) dwInstance; |
| 677 | //static int entry = 0; |
| 678 | PmInternal *midi = (PmInternal *)(FPTR) dwInstance; |
| 676 | 679 | midiwinmm_type m = (midiwinmm_type) midi->descriptor; |
| 677 | 680 | |
| 678 | 681 | /* NOTE: we do not just EnterCriticalSection() here because an |
| r242840 | r242841 | |
| 688 | 691 | * hardware interrupt? -- but I've seen reentrant behavior |
| 689 | 692 | * using a debugger, so it happens. |
| 690 | 693 | */ |
| 691 | | long new_driver_time; |
| 694 | //long new_driver_time; |
| 692 | 695 | EnterCriticalSection(&m->lock); |
| 693 | 696 | |
| 694 | 697 | /* dwParam1 is MIDI data received, packed into DWORD w/ 1st byte of |
| r242840 | r242841 | |
| 697 | 700 | in [ms] from when midiInStart called. |
| 698 | 701 | each message is expanded to include the status byte */ |
| 699 | 702 | |
| 700 | | new_driver_time = dwParam2; |
| 703 | //new_driver_time = dwParam2; |
| 701 | 704 | |
| 702 | 705 | if ((dwParam1 & 0x80) == 0) { |
| 703 | 706 | /* not a status byte -- ignore it. This happened running the |
| r242840 | r242841 | |
| 717 | 720 | break; |
| 718 | 721 | } |
| 719 | 722 | case MIM_LONGDATA: { |
| 720 | | MIDIHDR *lpMidiHdr = (MIDIHDR *) dwParam1; |
| 723 | MIDIHDR *lpMidiHdr = (MIDIHDR *)(FPTR)dwParam1; |
| 721 | 724 | unsigned char *data = (unsigned char *) lpMidiHdr->lpData; |
| 722 | 725 | unsigned int processed = 0; |
| 723 | 726 | int remaining = lpMidiHdr->dwBytesRecorded; |
| r242840 | r242841 | |
| 741 | 744 | case, we do not want to send them back to the interface (if |
| 742 | 745 | we do, the interface will not close, and Windows OS may hang). */ |
| 743 | 746 | if (lpMidiHdr->dwBytesRecorded > 0) { |
| 744 | | MMRESULT rslt; |
| 747 | //MMRESULT rslt; |
| 745 | 748 | lpMidiHdr->dwBytesRecorded = 0; |
| 746 | 749 | lpMidiHdr->dwFlags = 0; |
| 747 | 750 | |
| 748 | 751 | /* note: no error checking -- can this actually fail? */ |
| 749 | | rslt = midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); |
| 750 | | assert(rslt == MMSYSERR_NOERROR); |
| 752 | midiInPrepareHeader(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); |
| 753 | //assert(rslt == MMSYSERR_NOERROR); |
| 751 | 754 | /* note: I don't think this can fail except possibly for |
| 752 | 755 | * MMSYSERR_NOMEM, but the pain of reporting this |
| 753 | 756 | * unlikely but probably catastrophic error does not seem |
| 754 | 757 | * worth it. |
| 755 | 758 | */ |
| 756 | | rslt = midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); |
| 757 | | assert(rslt == MMSYSERR_NOERROR); |
| 759 | midiInAddBuffer(hMidiIn, lpMidiHdr, sizeof(MIDIHDR)); |
| 760 | //assert(rslt == MMSYSERR_NOERROR); |
| 758 | 761 | LeaveCriticalSection(&m->lock); |
| 759 | 762 | } else { |
| 760 | 763 | midiInUnprepareHeader(hMidiIn,lpMidiHdr,sizeof(MIDIHDR)); |
| r242840 | r242841 | |
| 806 | 809 | static PmTimestamp pm_time_get(midiwinmm_type m) |
| 807 | 810 | { |
| 808 | 811 | MMTIME mmtime; |
| 809 | | MMRESULT wRtn; |
| 812 | //MMRESULT wRtn; |
| 810 | 813 | mmtime.wType = TIME_TICKS; |
| 811 | 814 | mmtime.u.ticks = 0; |
| 812 | | wRtn = midiStreamPosition(m->handle.stream, &mmtime, sizeof(mmtime)); |
| 813 | | assert(wRtn == MMSYSERR_NOERROR); |
| 815 | midiStreamPosition(m->handle.stream, &mmtime, sizeof(mmtime)); |
| 816 | //assert(wRtn == MMSYSERR_NOERROR); |
| 814 | 817 | return mmtime.u.ticks; |
| 815 | 818 | } |
| 816 | 819 | |
| r242840 | r242841 | |
| 828 | 831 | int max_sysex_len = midi->buffer_len * 4; |
| 829 | 832 | int output_buffer_len; |
| 830 | 833 | int num_buffers; |
| 831 | | dwDevice = (DWORD) descriptors[i].descriptor; |
| 832 | | |
| 834 | dwDevice = (DWORD)(FPTR) descriptors[i].descriptor; |
| 833 | 835 | /* create system dependent device data */ |
| 834 | 836 | m = (midiwinmm_type) pm_alloc(sizeof(midiwinmm_node)); /* create */ |
| 835 | 837 | midi->descriptor = m; |
| r242840 | r242841 | |
| 891 | 893 | if (output_buffer_len < MIN_SIMPLE_SYSEX_LEN) |
| 892 | 894 | output_buffer_len = MIN_SIMPLE_SYSEX_LEN; |
| 893 | 895 | } else { |
| 894 | | long dur = 0; |
| 895 | | num_buffers = max(midi->buffer_len, midi->latency / 2); |
| 896 | //long dur = 0; |
| 897 | //num_buffers = (int)(double)max((double)midi->buffer_len, (double)midi->latency / 2); |
| 898 | if (midi->buffer_len > (midi->latency / 2)) |
| 899 | { |
| 900 | num_buffers = midi->buffer_len; |
| 901 | } |
| 902 | else |
| 903 | { |
| 904 | num_buffers = (midi->latency / 2); |
| 905 | } |
| 906 | |
| 896 | 907 | if (num_buffers < MIN_STREAM_BUFFERS) |
| 897 | 908 | num_buffers = MIN_STREAM_BUFFERS; |
| 898 | 909 | output_buffer_len = STREAM_BUFFER_LEN; |
| r242840 | r242841 | |
| 930 | 941 | winmm_out_delete(midi); /* frees buffers and m */ |
| 931 | 942 | no_memory: |
| 932 | 943 | if (pm_hosterror) { |
| 933 | | int err = midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 944 | midiOutGetErrorText(pm_hosterror, (char *) pm_hosterror_text, |
| 934 | 945 | PM_HOST_ERROR_MSG_LEN); |
| 935 | | assert(err == MMSYSERR_NOERROR); |
| 946 | //assert(err == MMSYSERR_NOERROR); |
| 936 | 947 | return pmHostError; |
| 937 | 948 | } |
| 938 | 949 | return pmInsufficientMemory; |
| r242840 | r242841 | |
| 985 | 996 | winmm_out_delete(midi); |
| 986 | 997 | } |
| 987 | 998 | if (pm_hosterror) { |
| 988 | | int err = midiOutGetErrorText(pm_hosterror, |
| 999 | midiOutGetErrorText(pm_hosterror, |
| 989 | 1000 | (char *) pm_hosterror_text, |
| 990 | 1001 | PM_HOST_ERROR_MSG_LEN); |
| 991 | | assert(err == MMSYSERR_NOERROR); |
| 1002 | //assert(err == MMSYSERR_NOERROR); |
| 992 | 1003 | return pmHostError; |
| 993 | 1004 | } |
| 994 | 1005 | return pmNoError; |
| r242840 | r242841 | |
| 1207 | 1218 | if (!hdr) { |
| 1208 | 1219 | m->hdr = hdr = get_free_output_buffer(midi); |
| 1209 | 1220 | assert(hdr); |
| 1210 | | midi->fill_base = (unsigned char *) m->hdr->lpData; |
| 1211 | | midi->fill_offset_ptr = &(hdr->dwBytesRecorded); |
| 1221 | midi->fill_base = (unsigned char *)(FPTR) m->hdr->lpData; |
| 1222 | midi->fill_offset_ptr = (uint32_t *)&(hdr->dwBytesRecorded); |
| 1223 | |
| 1212 | 1224 | /* when buffer fills, Pm_WriteSysEx will revert to calling |
| 1213 | 1225 | * pmwin_write_byte, which expect to have space, so leave |
| 1214 | 1226 | * one byte free for pmwin_write_byte. Leave another byte |
| r242840 | r242841 | |
| 1330 | 1342 | static void CALLBACK winmm_streamout_callback(HMIDIOUT hmo, UINT wMsg, |
| 1331 | 1343 | DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) |
| 1332 | 1344 | { |
| 1333 | | PmInternal *midi = (PmInternal *) dwInstance; |
| 1345 | PmInternal *midi = (PmInternal *)(FPTR) dwInstance; |
| 1346 | LPMIDIHDR hdr = (LPMIDIHDR)(FPTR) dwParam1; |
| 1334 | 1347 | midiwinmm_type m = (midiwinmm_type) midi->descriptor; |
| 1335 | | LPMIDIHDR hdr = (LPMIDIHDR) dwParam1; |
| 1336 | | int err; |
| 1348 | //int err; |
| 1337 | 1349 | |
| 1338 | 1350 | /* Even if an error is pending, I think we should unprepare msgs and |
| 1339 | 1351 | signal their arrival |
| r242840 | r242841 | |
| 1341 | 1353 | /* printf("streamout_callback: hdr %x, wMsg %x, MOM_DONE %x\n", |
| 1342 | 1354 | hdr, wMsg, MOM_DONE); */ |
| 1343 | 1355 | if (wMsg == MOM_DONE) { |
| 1344 | | MMRESULT ret = midiOutUnprepareHeader(m->handle.out, hdr, |
| 1356 | midiOutUnprepareHeader(m->handle.out, hdr, |
| 1345 | 1357 | sizeof(MIDIHDR)); |
| 1346 | | assert(ret == MMSYSERR_NOERROR); |
| 1358 | //assert(ret == MMSYSERR_NOERROR); |
| 1347 | 1359 | } |
| 1348 | 1360 | /* signal client in case it is blocked waiting for buffer */ |
| 1349 | | err = SetEvent(m->buffer_signal); |
| 1350 | | assert(err); /* false -> error */ |
| 1361 | SetEvent(m->buffer_signal); |
| 1362 | //assert(err); /* false -> error */ |
| 1351 | 1363 | } |
| 1352 | 1364 | |
| 1353 | 1365 | |
| r242840 | r242841 | |
| 1418 | 1430 | int i; |
| 1419 | 1431 | #ifdef DEBUG |
| 1420 | 1432 | char msg[PM_HOST_ERROR_MSG_LEN]; |
| 1421 | | #endif |
| 1422 | 1433 | int doneAny = 0; |
| 1423 | | #ifdef DEBUG |
| 1424 | 1434 | printf("pm_winmm_term called\n"); |
| 1425 | 1435 | #endif |
| 1426 | 1436 | for (i = 0; i < pm_descriptor_index; i++) { |