/* * This function has been borrowed from the tiny player found on * wavpack.com. Modifications were required because mpd only handles * max 24-bit samples. */ static void format_samples_int(int bytes_per_sample, void *buffer, uint32_t count) { int32_t *src = buffer; switch (bytes_per_sample) { case 1: { uchar *dst = buffer; /* * The asserts like the following one are because we do the * formatting of samples within a single buffer. The size * of the output samples never can be greater than the size * of the input ones. Otherwise we would have an overflow. */ assert_static(sizeof(*dst) <= sizeof(*src)); /* pass through and align 8-bit samples */ while (count--) { *dst++ = *src++; } break; } case 2: { uint16_t *dst = buffer; assert_static(sizeof(*dst) <= sizeof(*src)); /* pass through and align 16-bit samples */ while (count--) { *dst++ = *src++; } break; } case 3: /* do nothing */ break; case 4: { uint32_t *dst = buffer; assert_static(sizeof(*dst) <= sizeof(*src)); /* downsample to 24-bit */ while (count--) { *dst++ = *src++ >> 8; } break; } } }
/* * This function converts floating point sample data to 24-bit integer. */ static void format_samples_float(G_GNUC_UNUSED int bytes_per_sample, void *buffer, uint32_t count) { int32_t *dst = buffer; float *src = buffer; assert_static(sizeof(*dst) <= sizeof(*src)); while (count--) { *dst++ = (int32_t)(*src++ + 0.5f); } }
kern_return_t mach_port_names( ipc_space_t space, mach_port_name_t **namesp, mach_msg_type_number_t *namesCnt, mach_port_type_t **typesp, mach_msg_type_number_t *typesCnt) { ipc_entry_bits_t *capability; ipc_tree_entry_t tentry; ipc_entry_t table; ipc_entry_num_t tsize; mach_port_index_t index; ipc_entry_num_t actual; /* this many names */ ipc_port_timestamp_t timestamp; /* logical time of this operation */ mach_port_name_t *names; mach_port_type_t *types; kern_return_t kr; vm_size_t size; /* size of allocated memory */ vm_offset_t addr1; /* allocated memory, for names */ vm_offset_t addr2; /* allocated memory, for types */ vm_map_copy_t memory1; /* copied-in memory, for names */ vm_map_copy_t memory2; /* copied-in memory, for types */ /* safe simplifying assumption */ assert_static(sizeof(mach_port_name_t) == sizeof(mach_port_type_t)); if (space == IS_NULL) return KERN_INVALID_TASK; size = 0; for (;;) { ipc_entry_num_t bound; vm_size_t size_needed; is_read_lock(space); if (!space->is_active) { is_read_unlock(space); if (size != 0) { kmem_free(ipc_kernel_map, addr1, size); kmem_free(ipc_kernel_map, addr2, size); } return KERN_INVALID_TASK; } /* upper bound on number of names in the space */ bound = space->is_table_size + space->is_tree_total; size_needed = round_page_32(bound * sizeof(mach_port_name_t)); if (size_needed <= size) break; is_read_unlock(space); if (size != 0) { kmem_free(ipc_kernel_map, addr1, size); kmem_free(ipc_kernel_map, addr2, size); } size = size_needed; kr = vm_allocate(ipc_kernel_map, &addr1, size, TRUE); if (kr != KERN_SUCCESS) return KERN_RESOURCE_SHORTAGE; kr = vm_allocate(ipc_kernel_map, &addr2, size, TRUE); if (kr != KERN_SUCCESS) { kmem_free(ipc_kernel_map, addr1, size); return KERN_RESOURCE_SHORTAGE; } /* can't fault while we hold locks */ kr = vm_map_wire(ipc_kernel_map, addr1, addr1 + size, VM_PROT_READ|VM_PROT_WRITE, FALSE); if (kr != KERN_SUCCESS) { kmem_free(ipc_kernel_map, addr1, size); kmem_free(ipc_kernel_map, addr2, size); return KERN_RESOURCE_SHORTAGE; } kr = vm_map_wire(ipc_kernel_map, addr2, addr2 + size, VM_PROT_READ|VM_PROT_WRITE, FALSE); if (kr != KERN_SUCCESS) { kmem_free(ipc_kernel_map, addr1, size); kmem_free(ipc_kernel_map, addr2, size); return KERN_RESOURCE_SHORTAGE; } } /* space is read-locked and active */ names = (mach_port_name_t *) addr1; types = (mach_port_type_t *) addr2; actual = 0; timestamp = ipc_port_timestamp(); table = space->is_table; tsize = space->is_table_size; for (index = 0; index < tsize; index++) { ipc_entry_t entry = &table[index]; ipc_entry_bits_t bits = entry->ie_bits; if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) { mach_port_name_t name; name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits)); mach_port_names_helper(timestamp, entry, name, names, types, &actual, space); } } for (tentry = ipc_splay_traverse_start(&space->is_tree); tentry != ITE_NULL; tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) { ipc_entry_t entry = &tentry->ite_entry; mach_port_name_t name = tentry->ite_name; assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE); mach_port_names_helper(timestamp, entry, name, names, types, &actual, space); } ipc_splay_traverse_finish(&space->is_tree); is_read_unlock(space); if (actual == 0) { memory1 = VM_MAP_COPY_NULL; memory2 = VM_MAP_COPY_NULL; if (size != 0) { kmem_free(ipc_kernel_map, addr1, size); kmem_free(ipc_kernel_map, addr2, size); } } else { vm_size_t size_used; vm_size_t vm_size_used; size_used = actual * sizeof(mach_port_name_t); vm_size_used = round_page_32(size_used); /* * Make used memory pageable and get it into * copied-in form. Free any unused memory. */ kr = vm_map_unwire(ipc_kernel_map, addr1, addr1 + vm_size_used, FALSE); assert(kr == KERN_SUCCESS); kr = vm_map_unwire(ipc_kernel_map, addr2, addr2 + vm_size_used, FALSE); assert(kr == KERN_SUCCESS); kr = vm_map_copyin(ipc_kernel_map, addr1, size_used, TRUE, &memory1); assert(kr == KERN_SUCCESS); kr = vm_map_copyin(ipc_kernel_map, addr2, size_used, TRUE, &memory2); assert(kr == KERN_SUCCESS); if (vm_size_used != size) { kmem_free(ipc_kernel_map, addr1 + vm_size_used, size - vm_size_used); kmem_free(ipc_kernel_map, addr2 + vm_size_used, size - vm_size_used); } } *namesp = (mach_port_name_t *) memory1; *namesCnt = actual; *typesp = (mach_port_type_t *) memory2; *typesCnt = actual; return KERN_SUCCESS; }