LockedQueue() { _start = 0; _end = 0; _length = 0; _capacity = 0; _items = NULL; _shutdown = false; if (!(_mutex = os_mutex_create())) mutex_err = GenesisErrorNoMem; if (!(_cond = os_cond_create())) cond_err = GenesisErrorNoMem; }
/* ---------------------------------------------------------------------- * allocate space for a new non-wrap fifo, and return pointer to * opaque handle. returns NULL on failure * -------------------------------------------------------------------- */ VCHI_NWFIFO_T * non_wrap_fifo_create( const char *name, const uint32_t size, int alignment, int no_of_slots ) { int32_t success = -1; NON_WRAP_FIFO_HANDLE_T *fifo; // check that the alignment is a power of 2 or 0 #ifndef WIN32 os_assert((OS_COUNT(alignment) == 1) || (alignment == 0)); #endif // put the alignment into a form we can use (must be power of 2) alignment = alignment ? alignment - 1 : 0; // create new non-wrap fifo struct fifo = (NON_WRAP_FIFO_HANDLE_T *)os_malloc( sizeof(NON_WRAP_FIFO_HANDLE_T), OS_ALIGN_DEFAULT, "" ); os_assert( fifo ); if (!fifo) return NULL; memset( fifo, 0, sizeof(NON_WRAP_FIFO_HANDLE_T) ); fifo->name = name; // allocate slightly more space than we need so that we can get the required alignment fifo->malloc_address = (uint8_t *)os_malloc(size+alignment, OS_ALIGN_DEFAULT, ""); if ( fifo->malloc_address ) { fifo->base_address = (uint8_t *)(((size_t)fifo->malloc_address + alignment) & ~alignment); fifo->read_ptr = fifo->base_address; fifo->write_ptr = fifo->base_address; // now allocate the space for the slot_info structures fifo->slot_info = (NON_WRAP_SLOT_T *)os_malloc(no_of_slots*sizeof(NON_WRAP_SLOT_T), OS_ALIGN_DEFAULT, ""); memset( fifo->slot_info, 0, no_of_slots * sizeof(NON_WRAP_SLOT_T) ); fifo->size = size; fifo->num_of_slots = no_of_slots; success = os_semaphore_create( &fifo->sem, OS_SEMAPHORE_TYPE_SUSPEND ); os_assert(success == 0); success = os_cond_create( &fifo->space_available_cond, &fifo->sem ); os_assert(success == 0); } else { os_free(fifo); fifo = NULL; } return (VCHI_NWFIFO_T *)fifo; }
int audio_graph_create_render(Project *project, GenesisContext *genesis_context, const GenesisExportFormat *export_format, const ByteBuffer &out_path, AudioGraph **out_audio_graph) { AudioGraph *ag = audio_graph_create_common(project, genesis_context, 0.10); ag->render_export_format = *export_format; ag->render_out_path = out_path; ag->render_frame_index = 0; ag->render_frame_count = project_get_duration_frames(project); ag->render_cond = ok_mem(os_cond_create()); ag->is_playing = true; ag->render_descr = genesis_create_node_descriptor(ag->pipeline, 1, "render", "Master render node."); if (!ag->render_descr) panic("unable to create render node descriptor"); genesis_node_descriptor_set_userdata(ag->render_descr, ag); genesis_node_descriptor_set_run_callback(ag->render_descr, render_node_run); genesis_node_descriptor_set_activate_callback(ag->render_descr, render_node_activate); ag->render_port_descr = genesis_node_descriptor_create_port( ag->render_descr, 0, GenesisPortTypeAudioIn, "audio_in"); if (!ag->render_port_descr) panic("unable to create render port descriptor"); genesis_audio_port_descriptor_set_channel_layout(ag->render_port_descr, &project->channel_layout, true, -1); genesis_audio_port_descriptor_set_sample_rate(ag->render_port_descr, export_format->sample_rate, true, -1); ag->master_node = ok_mem(genesis_node_descriptor_create_node(ag->render_descr)); ag->render_stream = ok_mem(genesis_audio_file_stream_create(ag->pipeline->context)); int render_sample_rate = genesis_audio_file_codec_best_sample_rate(export_format->codec, export_format->sample_rate); genesis_audio_file_stream_set_sample_rate(ag->render_stream, render_sample_rate); genesis_audio_file_stream_set_channel_layout(ag->render_stream, &project->channel_layout); ByteBuffer encoded; encoded = project->tag_title.encode(); genesis_audio_file_stream_set_tag(ag->render_stream, "title", -1, encoded.raw(), encoded.length()); encoded = project->tag_artist.encode(); genesis_audio_file_stream_set_tag(ag->render_stream, "artist", -1, encoded.raw(), encoded.length()); encoded = project->tag_album_artist.encode(); genesis_audio_file_stream_set_tag(ag->render_stream, "album_artist", -1, encoded.raw(), encoded.length()); encoded = project->tag_album.encode(); genesis_audio_file_stream_set_tag(ag->render_stream, "album", -1, encoded.raw(), encoded.length()); // TODO looks like I messed up the year tag; it should actually be ISO 8601 "date" // TODO so we need to write the date tag here, not year. genesis_audio_file_stream_set_export_format(ag->render_stream, export_format); int err; if ((err = genesis_audio_file_stream_open(ag->render_stream, out_path.raw(), out_path.length()))) { audio_graph_destroy(ag); return err; } *out_audio_graph = ag; return 0; }
int ordered_map_file_open(const char *path, OrderedMapFile **out_omf) { *out_omf = nullptr; OrderedMapFile *omf = create_zero<OrderedMapFile>(); if (!omf) { ordered_map_file_close(omf); return GenesisErrorNoMem; } if (!(omf->cond = os_cond_create())) { ordered_map_file_close(omf); return GenesisErrorNoMem; } if (!(omf->mutex = os_mutex_create())) { ordered_map_file_close(omf); return GenesisErrorNoMem; } if (omf->queue.error()) { ordered_map_file_close(omf); return omf->queue.error(); } omf->list = create_zero<List<OrderedMapFileEntry *>>(); if (!omf->list) { ordered_map_file_close(omf); return GenesisErrorNoMem; } omf->map = create_zero<HashMap<ByteBuffer, OrderedMapFileEntry *, ByteBuffer::hash>>(); if (!omf->map) { ordered_map_file_close(omf); return GenesisErrorNoMem; } omf->running = true; int err; if ((err = os_thread_create(run_write, omf, false, &omf->write_thread))) { ordered_map_file_close(omf); return err; } bool open_for_writing = false; omf->file = fopen(path, "rb+"); if (omf->file) { int err = read_header(omf); if (err == GenesisErrorEmptyFile) { open_for_writing = true; } else if (err) { ordered_map_file_close(omf); return err; } } else { open_for_writing = true; } if (open_for_writing) { omf->file = fopen(path, "wb+"); if (!omf->file) { ordered_map_file_close(omf); return GenesisErrorFileAccess; } int err = write_header(omf); if (err) { ordered_map_file_close(omf); return err; } } // read everything into list bool partial_transaction = false; omf->write_buffer.resize(TRANSACTION_METADATA_SIZE); omf->transaction_offset = UUID_SIZE; for (;;) { size_t amt_read = fread(omf->write_buffer.raw(), 1, TRANSACTION_METADATA_SIZE, omf->file); if (amt_read != TRANSACTION_METADATA_SIZE) { // partial transaction. ignore it and we're done. if (amt_read > 0) partial_transaction = true; break; } uint8_t *transaction_ptr = (uint8_t*)omf->write_buffer.raw(); int transaction_size = read_uint32be(&transaction_ptr[4]); if (transaction_size < TRANSACTION_METADATA_SIZE || transaction_size > MAX_TRANSACTION_SIZE) { // invalid value partial_transaction = true; break; } omf->write_buffer.resize(transaction_size); transaction_ptr = (uint8_t*)omf->write_buffer.raw(); size_t amt_to_read = transaction_size - TRANSACTION_METADATA_SIZE; amt_read = fread(&transaction_ptr[TRANSACTION_METADATA_SIZE], 1, amt_to_read, omf->file); if (amt_read != amt_to_read) { // partial transaction. ignore it and we're done. partial_transaction = true; break; } uint32_t computed_crc = crc32(0, &transaction_ptr[4], transaction_size - 4); uint32_t crc_from_file = read_uint32be(&transaction_ptr[0]); if (computed_crc != crc_from_file) { // crc check failed. ignore this transaction and we're done. partial_transaction = true; break; } int put_count = read_uint32be(&transaction_ptr[8]); int del_count = read_uint32be(&transaction_ptr[12]); int offset = TRANSACTION_METADATA_SIZE; for (int i = 0; i < put_count; i += 1) { int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4; int val_size = read_uint32be(&transaction_ptr[offset]); offset += 4; OrderedMapFileEntry *entry = create_zero<OrderedMapFileEntry>(); if (!entry) { ordered_map_file_close(omf); return GenesisErrorNoMem; } entry->key = ByteBuffer((char*)&transaction_ptr[offset], key_size); offset += key_size; entry->offset = omf->transaction_offset + offset; entry->size = val_size; offset += val_size; auto old_hash_entry = omf->map->maybe_get(entry->key); if (old_hash_entry) { OrderedMapFileEntry *old_entry = old_hash_entry->value; destroy(old_entry, 1); } omf->map->put(entry->key, entry); } for (int i = 0; i < del_count; i += 1) { int key_size = read_uint32be(&transaction_ptr[offset]); offset += 4; ByteBuffer key((char*)&transaction_ptr[offset], key_size); offset += key_size; auto hash_entry = omf->map->maybe_get(key); if (hash_entry) { OrderedMapFileEntry *entry = hash_entry->value; omf->map->remove(key); destroy(entry, 1); } } omf->transaction_offset += transaction_size; } if (partial_transaction) fprintf(stderr, "Warning: Partial transaction found in project file.\n"); // transfer map to list and sort auto it = omf->map->entry_iterator(); if (omf->list->ensure_capacity(omf->map->size())) { ordered_map_file_close(omf); return GenesisErrorNoMem; } for (;;) { auto *map_entry = it.next(); if (!map_entry) break; ok_or_panic(omf->list->append(map_entry->value)); } omf->map->clear(); destroy_map(omf); omf->list->sort<compare_entries>(); *out_omf = omf; return 0; }