static int ProcessRootElement(xmlNode * a_node) { xmlNode *cur_node = NULL; int ret = 0; if (a_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(a_node->name, (xmlChar*) X_NODE_ROOT)) { for (cur_node = a_node->children; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_CONTROLLER)) { ret = ProcessControllerElement(cur_node); } else { ret = -1; gwarn("bad element name: %s\n", cur_node->name); } } } } else { ret = -1; gwarn("bad element name: %s\n", a_node->name); } } return ret; }
static int ProcessControllerElement(xmlNode * a_node) { xmlNode* cur_node = NULL; int ret = 0; ret = GetUnsignedIntProp(a_node, X_ATTR_ID, &r_controller_id); if(ret != -1) { r_controller_id--; if (r_controller_id >= MAX_CONTROLLERS) { gwarn("bad controller id: %d\n", r_controller_id); ret = -1; } } for (cur_node = a_node->children; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_CONFIGURATION)) { ret = ProcessConfigurationElement(cur_node); } else { ret = -1; gwarn("bad element name: %s\n", cur_node->name); } } } return ret; }
static char* waveform_get_peak_filename(const char* filename) { // filename should be absolute. // caller must g_free the returned value. if(wf->load_peak == wf_load_ardour_peak) { gwarn("cannot automatically determine path of Ardour peakfile"); return NULL; } GError* error = NULL; gchar* uri = g_filename_to_uri(filename, NULL, &error); if(error) { gwarn("%s", error->message); return NULL; } dbg(1, "uri=%s", uri); gchar* md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5, uri, -1); g_free(uri); gchar* peak_basename = g_strdup_printf("%s.peak", md5); g_free(md5); char* cache_dir = get_cache_dir(); gchar* peak_filename = g_build_filename(cache_dir, peak_basename, NULL); g_free(cache_dir); dbg(1, "peak_filename=%s", peak_filename); g_free(peak_basename); return peak_filename; }
static int ProcessAxisElement(xmlNode * a_node) { int ret = 0; xmlNode* cur_node = NULL; for (cur_node = a_node->children; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_DEVICE)) { ret = ProcessDeviceElement(cur_node); break; } else { gwarn("bad element name: %s", cur_node->name); ret = -1; } } } if (!cur_node) { gwarn("missing device element"); ret = -1; } if(r_device_type != E_DEVICE_TYPE_MOUSE || r_device_id < 0) { return ret; } for (cur_node = cur_node->next; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_EVENT)) { ret = ProcessEventElement(cur_node); break; } else { gwarn("bad element name: %s", cur_node->name); ret = -1; } } } if (!cur_node) { gwarn("missing event element"); ret = -1; } return ret; }
static FileTypePluginPtr file_manager__plugin_load (const gchar* filepath) { FileTypePluginPtr plugin = NULL; gboolean success = FALSE; #if GLIB_CHECK_VERSION(2,3,3) GModule* handle = g_module_open(filepath, G_MODULE_BIND_LOCAL); #else GModule* handle = g_module_open(filepath, 0); #endif if(!handle) { gwarn("cannot open %s (%s)!", filepath, g_module_error()); return NULL; } infoFunc plugin_get_info; if(g_module_symbol(handle, "plugin_get_info", (void*)&plugin_get_info)) { // load generic plugin info if(NULL != (plugin = (*plugin_get_info)())) { // check plugin version if(FILETYPE_PLUGIN_API_VERSION != plugin->api_version){ dbg(0, "API version mismatch: \"%s\" (%s, type=%d) has version %d should be %d", plugin->name, filepath, plugin->type, plugin->api_version, FILETYPE_PLUGIN_API_VERSION); } /* check if all mandatory symbols are provided */ if (!(plugin->init && plugin->deinit)) { dbg(0, "'%s': mandatory symbols missing.", plugin->name); return false; } success = true; // try to load specific plugin type symbols switch(plugin->type) { default: if(plugin->type >= PLUGIN_TYPE_MAX) { dbg(0, "Unknown or unsupported plugin type: %s (%s, type=%d)", plugin->name, filepath, plugin->type); } else { dbg(0, "name='%s'", plugin->name); } break; } } } else { gwarn("File '%s' is not a valid Filtype plugin", filepath); } if(!success) { g_module_close(handle); return NULL; } return plugin; }
/* * This function modifies a config file according to the calibrated values. */ int cfgw_modify_file(char* file) { xmlDoc *doc = NULL; xmlNode *root_element = NULL; int ret = 0; char file_path[PATH_MAX]; snprintf(file_path, sizeof(file_path), "%s%s%s%s", gimx_params.homedir, GIMX_DIR, CONFIG_DIR, file); /* * this initialize the library and check potential ABI mismatches * between the version it was compiled for and the actual shared * library used. */ LIBXML_TEST_VERSION /*parse the file and get the DOM */ doc = xmlReadFile(file_path, NULL, 0); #ifdef WIN32 if(!xmlFree) xmlMemGet(&xmlFree,&xmlMalloc,&xmlRealloc,NULL); #endif if (doc != NULL) { /*Get the root element node */ root_element = xmlDocGetRootElement(doc); if(root_element != NULL) { ret = ProcessRootElement(root_element); } else { ret = -1; gwarn("error: no root element\n"); } if(ret != -1) { xmlSaveFormatFileEnc(file_path, doc, "UTF-8", 1); } } else { ret = -1; gwarn("error: could not parse file %s\n", file_path); } /*free the document */ xmlFreeDoc(doc); return ret; }
static inline FAR const struct nx_fontset_s * nxf_getglyphset(uint16_t ch, FAR const struct nx_fontpackage_s *package) { FAR const struct nx_fontset_s *fontset; /* Select the 7- or 8-bit font set */ if (ch < 128) { /* Select the 7-bit font set */ fontset = &package->font7; } else if (ch < 256) { #if CONFIG_NXFONTS_CHARBITS >= 8 /* Select the 8-bit font set */ fontset = &package->font8; #else gwarn("WARNING: 8-bit font support disabled: %d\n", ch); return NULL; #endif } else { /* Someday, perhaps 16-bit fonts will go here */ gwarn("WARNING: 16-bit font not currently supported\n"); return NULL; } /* Then verify that the character actually resides in the font */ if (ch >= fontset->first && ch < fontset->first +fontset->nchars) { return fontset; } /* Too much debug output for the case of space which never resides in the * font. */ if (ch != ' ') { gwarn("WARNING: No bitmap for code %02x\n", ch); } return NULL; }
GList* get_dirlist(const char* path) { /* scan a directory and return a list of any subdirectoies. Not recursive. -the list, and each entry in it, must be freed. */ GList* dir_list = NULL; char filepath[256]; G_CONST_RETURN gchar *file; GError *error = NULL; GDir *dir; if((dir = g_dir_open(path, 0, &error))){ while((file = g_dir_read_name(dir))){ if(file[0]=='.') continue; snprintf(filepath, 128, "%s/%s", path, file); if(g_file_test(filepath, G_FILE_TEST_IS_DIR)){ dbg (2, "found dir: %s", filepath); dir_list = g_list_append(dir_list, g_strdup(filepath)); } } g_dir_close(dir); }else{ if(wf_debug > 1) gwarn ("cannot open directory. %s", error->message); g_error_free(error); error = NULL; } return dir_list; }
void gdl_dock_add_item (GdlDock *dock, GdlDockItem *item, GdlDockPlacement placement) { g_return_if_fail (dock != NULL); g_return_if_fail (item != NULL); if (placement == GDL_DOCK_FLOATING) /* Add the item to a new floating dock */ gdl_dock_add_floating_item (dock, item, 0, 0, -1, -1); else { GdlDockItem *best_dock_item; /* Non-floating item. */ if (dock->root) { GdlDockPlacement local_placement; GtkRequisition preferred_size; best_dock_item = gdl_dock_find_best_placement_item (GDL_DOCK_ITEM (dock->root), placement, 0); local_placement = gdl_dock_refine_placement (dock, best_dock_item, placement); if(local_placement != placement) gwarn("placement changed"); gdl_dock_object_dock (GDL_DOCK_OBJECT (best_dock_item), GDL_DOCK_OBJECT (item), local_placement, NULL); } else { gdl_dock_object_dock (GDL_DOCK_OBJECT (dock), GDL_DOCK_OBJECT (item), placement, NULL); } } }
/* * load the contents of a peak file from an Ardour project. */ int wf_load_ardour_peak(Waveform* wv, const char* peak_file) { g_return_val_if_fail(wv, 0); int fp = open(peak_file, O_RDONLY); if(!fp){ gwarn ("file open failure."); goto out; } dbg(2, "%s", peak_file); size_t n_frames = get_n_words(wv, peak_file); uint32_t bytes = n_frames * peak_byte_depth * WF_PEAK_VALUES_PER_SAMPLE; //read the whole peak file into memory: float* read_buf = g_malloc(bytes); if(read(fp, read_buf, bytes) != bytes) gerr ("read error. couldnt read %i bytes from %s", bytes, peak_file); close(fp); //convert from float to short short* buf = waveform_peak_malloc(wv, n_frames * sizeof(short) * WF_PEAK_VALUES_PER_SAMPLE); int i; for(i=0;i<n_frames;i++){ //ardour peak files have negative peak first. ABS is used because values occasionally have incorrect sign. buf[2 * i ] = ABS(read_buf[2 * i + 1] * (1 << 15)); buf[2 * i + 1] = -(ABS(read_buf[2 * i ]) * (1 << 15)); } g_free(read_buf); #if 0 dbg(1, "peaks:"); for (i=0;i<20;i++) printf(" %i %i\n", buf[2 * i], buf[2 * i + 1]); #endif int ch_num = wv->priv->peak.buf[WF_LEFT] ? 1 : 0; //this makes too many assumptions. better to pass explicitly as argument. wv->priv->peak.buf[ch_num] = buf; wv->priv->peak.size = n_frames * WF_PEAK_VALUES_PER_SAMPLE; #ifdef ENABLE_CHECKS int k; for(k=0;k<n_frames;k++){ if(wv->priv->peak.buf[0][2*k + 0] < 0.0){ gwarn("positive peak not positive"); break; } if(wv->priv->peak.buf[0][2*k + 1] > 0.0){ gwarn("negative peak not negative"); break; } } #endif out: return 1; }
static void file_manager__load_plugins () { FileTypePluginPtr plugin = NULL; GError* error = NULL; if(!g_module_supported()) g_error("Modules not supported! (%s)", g_module_error()); int found = 0; char* plugin_path = g_strdup_printf("%s:%s", "../lib/file_manager/filetypes/.libs", PLUGIN_PATH); gchar** paths = g_strsplit(plugin_path, ":", 0); g_free(plugin_path); char* path; int i = 0; while((path = paths[i++])){ if(!g_file_test(path, G_FILE_TEST_EXISTS)) continue; dbg(1, "scanning for plugins (%s) ...", path); GDir* dir = g_dir_open(path, 0, &error); if (!error) { const gchar* filename = g_dir_read_name(dir); while (filename) { dbg(1, "testing %s...", filename); gchar* filepath = g_build_filename(path, filename, NULL); // filter files with correct library suffix if(!strncmp(G_MODULE_SUFFIX, filename + strlen(filename) - strlen(G_MODULE_SUFFIX), strlen(G_MODULE_SUFFIX))) { // If we find one, try to load plugin info and if this was successful try to invoke the specific plugin // type loader. If the second loading went well add the plugin to the plugin list. if (!(plugin = file_manager__plugin_load(filepath))) { dbg(0, "'%s' failed to load.", filename); } else { found++; plugin->init(); plugins = g_slist_append(plugins, plugin); } } else { dbg(2, "-> no library suffix"); } g_free(filepath); filename = g_dir_read_name(dir); } g_dir_close(dir); } else { gwarn("dir='%s' failed. %s", path, error->message); g_error_free(error); error = NULL; } } g_strfreev(paths); dbg(1, "filetype plugins loaded: %i.", found); }
static int ProcessConfigurationElement(xmlNode * a_node) { int ret = 0; xmlNode* cur_node = NULL; ret = GetUnsignedIntProp(a_node, X_ATTR_ID, &r_profile_id); if(ret != -1) { r_profile_id--; if (r_profile_id >= MAX_PROFILES) { gwarn("bad profile id: %d\n", r_profile_id); ret = -1; } } cur_node = a_node->children; for (cur_node = cur_node->next; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_AXIS_MAP)) { ret = ProcessAxisMapElement(cur_node); break; } } } if (!cur_node) { gwarn("missing axis_map element"); ret = -1; } return ret; }
static void mysql__dir_iter_new() { #define DIR_LIST_QRY "SELECT DISTINCT filedir FROM samples ORDER BY filedir" if(dir_iter_result) gwarn("previous query not free'd?"); if(!mysql__exec_sql(DIR_LIST_QRY)){ dir_iter_result = mysql_store_result(&mysql); dbg(2, "num_rows=%i", mysql_num_rows(dir_iter_result)); } else{ dbg(0, "failed to find any records: %s", mysql_error(&mysql)); } }
WaveformView* construct () { WaveformView* self = (WaveformView*) g_object_new (TYPE_WAVEFORM_VIEW, NULL); gtk_widget_add_events ((GtkWidget*) self, (gint) ((GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK) | GDK_POINTER_MOTION_MASK)); gtk_widget_set_size_request ((GtkWidget*) self, 200, 100); //GdkGLConfig* glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB | GDK_GL_MODE_DOUBLE); if(!gtk_widget_set_gl_capability((GtkWidget*)self, glconfig, gl_context, DIRECT, GDK_GL_RGBA_TYPE)){ gwarn("failed to set gl capability"); } WaveformViewPrivate* priv = self->priv; priv->gl_init_done = false; return self; }
void sample_unref(Sample* sample) { if (!sample) return; #ifdef DEBUG_REFCOUNTS if(sample->name && !strcmp(sample->name, "test.wav")) printf("- %i --> %i\n", sample->ref_count, sample->ref_count-1); #endif sample->ref_count--; #ifdef DEBUG_REFCOUNTS g_return_if_fail(sample->ref_count >= 0); if(sample->ref_count < 1) gwarn("freeing sample... %s", sample->name ? sample->name : ""); #endif if(sample->ref_count < 1) sample_free(sample); }
static void sample_free(Sample* sample) { if(sample->ref_count > 0) { gwarn("freeing sample with refcount: %d", sample->ref_count); } if(sample->row_ref) gtk_tree_row_reference_free(sample->row_ref); if(sample->name) g_free(sample->name); if(sample->full_path) g_free(sample->full_path); if(sample->mimetype) g_free(sample->mimetype); if(sample->ebur) g_free(sample->ebur); if(sample->notes) g_free(sample->notes); if(sample->sample_dir) g_free(sample->sample_dir); if(sample->meta_data) g_ptr_array_unref(sample->meta_data); //if(sample->overview) g_free(sample->overview); // check how to free that! g_free(sample); }
void waveform_peakgen(Waveform* w, const char* peak_filename, WfCallback2 callback, gpointer user_data) { if(!peakgen.msg_queue) wf_worker_init(&peakgen); typedef struct { char* infilename; const char* peak_filename; struct { bool failed; // returned true if peakgen failed } out; WfCallback2 callback; void* user_data; } PeakJob; PeakJob* job = g_new0(PeakJob, 1); *job = (PeakJob) { .infilename = g_path_is_absolute(w->filename) ? g_strdup(w->filename) : g_build_filename(g_get_current_dir(), w->filename, NULL), .peak_filename = peak_filename, .callback = callback, .user_data = user_data, }; void peakgen_execute_job(Waveform* w, gpointer _job) { // runs in worker thread PeakJob* job = _job; if(!wf_peakgen__sync(job->infilename, job->peak_filename)) { #ifdef DEBUG if(wf_debug) gwarn("peakgen failed"); #endif job->out.failed = true; // writing to object owned by main thread } } void peakgen_free(gpointer item) { PeakJob* job = item; g_free0(job->infilename); g_free(job); }
static int ProcessAxisMapElement(xmlNode * a_node) { int ret = 0; xmlNode* cur_node = NULL; for (cur_node = a_node->children; cur_node && ret != -1; cur_node = cur_node->next) { if (cur_node->type == XML_ELEMENT_NODE) { if (xmlStrEqual(cur_node->name, (xmlChar*) X_NODE_AXIS)) { ret = ProcessAxisElement(cur_node); } else { gwarn("bad element name: %s", cur_node->name); ret = -1; } } } return ret; }
ssize_t ad_read_sndfile(WfDecoder* d, float* out, size_t len) { SndfileDecoder* priv = (SndfileDecoder*)d->d; if (!priv) return -1; switch(d->info.bit_depth){ case 32: return sf_read_float (priv->sffile, out, len); case 16: { short* d16 = g_malloc0(len * sizeof(short)); ssize_t r = sf_read_short (priv->sffile, d16, len); int16_to_float(out, d16, d->info.channels, len / d->info.channels, 0); g_free(d16); return r; } #ifdef DEBUG default: gwarn("unhandled bit depth: %i", d->info.bit_depth); #endif } return -1; }
ssize_t ad_read_ffmpeg(void *sf, float* d, size_t len) { ffmpeg_audio_decoder *priv = (ffmpeg_audio_decoder*) sf; if (!priv) return -1; size_t frames = len / priv->channels; int written = 0; int ret = 0; while (ret >= 0 && written < frames) { dbg(3, "loop: %i/%i (bl:%lu)",written, frames, priv->m_tmpBufferLen ); if (priv->seek_frame == 0 && priv->m_tmpBufferLen > 0 ) { int s = MIN(priv->m_tmpBufferLen / priv->channels, frames - written ); int16_to_float(priv->m_tmpBufferStart, d, priv->channels, s , written); written += s; priv->output_clock+=s; s = s * priv->channels; priv->m_tmpBufferStart += s; priv->m_tmpBufferLen -= s; ret = 0; } else { priv->m_tmpBufferStart = priv->m_tmpBuffer; priv->m_tmpBufferLen = 0; if (!priv->pkt_ptr || priv->pkt_len < 1) { if (priv->packet.data) av_free_packet(&priv->packet); ret = av_read_frame(priv->formatContext, &priv->packet); if (ret < 0) { dbg(2, "reached end of file."); break; } priv->pkt_len = priv->packet.size; priv->pkt_ptr = priv->packet.data; } if (priv->packet.stream_index != priv->audioStream) { priv->pkt_ptr = NULL; continue; } /* decode all chunks in packet */ int data_size= AVCODEC_MAX_AUDIO_FRAME_SIZE; #if 0 // TODO ffcompat.h -- this works but is not optimal (channels may not be planar/interleaved) AVFrame avf; // TODO statically allocate memset(&avf, 0, sizeof(AVFrame)); // not sure if that is needed int got_frame = 0; ret = avcodec_decode_audio4(priv->codecContext, &avf, &got_frame, &priv->packet); data_size = avf.linesize[0]; memcpy(priv->m_tmpBuffer, avf.data[0], avf.linesize[0] * sizeof(uint8_t)); #else // this was deprecated in LIBAVCODEC_VERSION_MAJOR 53 ret = avcodec_decode_audio3(priv->codecContext, priv->m_tmpBuffer, &data_size, &priv->packet); #endif if (ret < 0 || ret > priv->pkt_len) { #if 0 dbg(0, "audio decode error"); return -1; #endif priv->pkt_len = 0; ret = 0; continue; } priv->pkt_len -= ret; priv->pkt_ptr += ret; /* sample exact alignment */ if (priv->packet.pts != AV_NOPTS_VALUE) { priv->decoder_clock = priv->samplerate * av_q2d(priv->formatContext->streams[priv->audioStream]->time_base) * priv->packet.pts; } else { dbg(0, "!!! NO PTS timestamp in file"); priv->decoder_clock += (data_size>>1) / priv->channels; } if (data_size > 0) { priv->m_tmpBufferLen+= (data_size>>1); // 2 bytes per sample } /* align buffer after seek. */ if (priv->seek_frame > 0) { const int diff = priv->output_clock-priv->decoder_clock; if (diff < 0) { /* seek ended up past the wanted sample */ gwarn("audio seek failed."); return -1; } else if (priv->m_tmpBufferLen < (diff*priv->channels)) { /* wanted sample not in current buffer - keep going */ dbg(2, " !!! seeked sample was not in decoded buffer. frames-to-go: %li", diff); priv->m_tmpBufferLen = 0; } else if (diff!=0 && data_size > 0) { /* wanted sample is in current buffer but not at the beginnning */ dbg(2, " !!! sync buffer to seek. (diff:%i)", diff); priv->m_tmpBufferStart+= diff*priv->codecContext->channels; priv->m_tmpBufferLen -= diff*priv->codecContext->channels; #if 1 memmove(priv->m_tmpBuffer, priv->m_tmpBufferStart, priv->m_tmpBufferLen); priv->m_tmpBufferStart = priv->m_tmpBuffer; #endif priv->seek_frame = 0; priv->decoder_clock += diff; } else if (data_size > 0) { dbg(2, "Audio exact sync-seek (%"PRIi64" == %"PRIi64")", priv->decoder_clock, priv->seek_frame); priv->seek_frame = 0; } else { dbg(0, "Error: no audio data in packet"); } } //dbg(0, "PTS: decoder:%"PRIi64". - want: %"PRIi64, priv->decoder_clock, priv->output_clock); //dbg(0, "CLK: frame: %"PRIi64" T:%.3fs",priv->decoder_clock, (float) priv->decoder_clock/priv->samplerate); } }
/* * Load a single audio block for the case where the audio is on a local filesystem. * For thread-safety, the Waveform is not modified. */ gboolean waveform_load_audio_block(Waveform* waveform, WfBuf16* buf16, int block_num) { //TODO handle split stereo files g_return_val_if_fail(waveform, false); // which parts of the audio file are present? // tier 1: 0, 128 // tier 2: 0, 64, 128, 196 // tier 3: 0, 32, 64, 96, 128, ... 196 // tier 4: 0, 16, ... // tier 5: 0, 8, ... // tier 6: 0, 4, ... // tier 7: 0, 2, ... // tier 8: 0, 1, ... //guint n_peaks = ((n_frames * 1 ) / WF_PEAK_RATIO) << audio->n_tiers_present; //int spacing = WF_PEAK_RATIO >> (audio->n_tiers_present - 1); uint64_t start_pos = block_num * (WF_PEAK_BLOCK_SIZE - 2.0 * TEX_BORDER * 256.0); uint64_t end_pos = start_pos + WF_PEAK_BLOCK_SIZE; int n_chans = waveform_get_n_channels(waveform); g_return_val_if_fail(n_chans, false); SF_INFO sfinfo; SNDFILE* sffile; sfinfo.format = 0; if(!(sffile = sf_open(waveform->filename, SFM_READ, &sfinfo))){ gwarn ("not able to open input file %s.", waveform->filename); puts(sf_strerror(NULL)); return false; } if(start_pos > sfinfo.frames){ gerr("startpos too high. %Li > %Li block=%i", start_pos, sfinfo.frames, block_num); return false; } if(end_pos > sfinfo.frames){ dbg(1, "*** last block: end_pos=%Lu max=%Lu", end_pos, sfinfo.frames); end_pos = sfinfo.frames; } sf_seek(sffile, start_pos, SEEK_SET); dbg(1, "block=%s%i%s (%i/%i) start=%Li end=%Li", wf_bold, block_num, wf_white, block_num+1, waveform_get_n_audio_blocks(waveform), start_pos, end_pos); sf_count_t n_frames = MIN(buf16->size, end_pos - start_pos); //1st of these isnt needed? g_return_val_if_fail(buf16 && buf16->buf[WF_LEFT], false); #ifdef WF_DEBUG buf16->start_frame = start_pos; #endif gboolean sf_read_float_to_short(SNDFILE* sffile, WfBuf16* buf, int ch, sf_count_t n_frames) { float readbuf[buf->size]; sf_count_t readcount; if((readcount = sf_readf_float(sffile, readbuf, n_frames)) < n_frames){ gwarn("unexpected EOF: %s", waveform->filename); gwarn(" start_frame=%Li n_frames=%Lu/%Lu read=%Li", start_pos, n_frames, sfinfo.frames, readcount); return false; } //convert to short int j; for(j=0;j<readcount;j++){ buf->buf[ch][j] = readbuf[j] * (1 << 15); } return true; }
static gboolean mysql__search_iter_new(char* dir, const char* category, int* n_results) { //return TRUE on success. g_return_val_if_fail(model, false); gboolean ok = true; if(search_result) gwarn("previous query not free'd?"); GString* q = g_string_new("SELECT * FROM samples WHERE 1 "); const char* search = model->filters.search->value; if(search && strlen(search)) { #if 0 g_string_append_printf(q, "AND (filename LIKE '%%%s%%' OR filedir LIKE '%%%s%%' OR keywords LIKE '%%%s%%') ", search, search, search); #else gchar* where = NULL; char* sd = strdup(search); char* s = sd; char* tok; while ((tok = strtok(s, " _")) != 0) { MYSQL_ESCAPE(esc, tok); gchar* tmp = g_strdup_printf("%s %s (filename LIKE '%%%s%%' OR filedir LIKE '%%%s%%' OR keywords LIKE '%%%s%%') ", where?where:"", where?"AND":"", esc, esc, esc); free(esc); if (where) g_free(where); where = tmp; s = NULL; } if (where) { g_string_append_printf(q, "AND (%s)", where); g_free(where); } #endif } if(dir && strlen(dir)) { MYSQL_ESCAPE(esc, dir); #ifdef DONT_SHOW_SUBDIRS //TODO g_string_append_printf(q, "AND filedir='%s' ", esc); #else g_string_append_printf(q, "AND filedir LIKE '%s%%' ", esc); #endif free(esc); } if(model->filters.category->value) { MYSQL_ESCAPE(esc, category); g_string_append_printf(q, "AND keywords LIKE '%%%s%%' ", esc); free(esc); } dbg(1, "%s", q->str); int e; if((e = mysql__exec_sql(q->str)) != 0){ dbg(1, "Failed to find any records: %s", mysql_error(&mysql)); if((e == CR_SERVER_GONE_ERROR) || (e == CR_SERVER_LOST)){ //default is to time out after 8 hours dbg(0, "mysql connection timed out. Reconnecting... (not tested!)"); mysql__connect(); }else{ dbg(0, "2: Failed to find any records: %i: %s", e, mysql_error(&mysql)); } ok = false; } else { search_result = mysql_store_result(&mysql); if(n_results){ uint32_t tot_rows = (uint32_t)mysql_affected_rows(&mysql); *n_results = tot_rows; db->n_results = tot_rows; } } g_string_free(q, true); return ok; }
bool wf_ff_peakgen(const char* infilename, const char* peak_filename) { WfDecoder f = {{0,}}; if(!ad_open(&f, infilename)) return false; SNDFILE* outfile; SF_INFO sfinfo = { .format = SF_FORMAT_WAV | SF_FORMAT_PCM_16, .channels = f.info.channels, .samplerate = f.info.sample_rate, }; gchar* basename = g_path_get_basename(peak_filename); gchar* tmp_path = g_build_filename("/tmp", basename, NULL); g_free(basename); if(!(outfile = sf_open(tmp_path, SFM_WRITE, &sfinfo))) { printf ("Not able to open output file %s.\n", tmp_path); puts(sf_strerror(NULL)); return false; } int total_frames_written = 0; WfPeakSample total[sfinfo.channels]; memset(total, 0, sizeof(WfPeakSample) * sfinfo.channels); int n = 8; int read_len = WF_PEAK_RATIO * n; float* sf_data = g_malloc(sizeof(float) * read_len); int16_t data[f.info.channels][read_len]; WfBuf16 buf = { .buf = { data[0], data[1] }, .size = n * WF_PEAK_RATIO }; int readcount; int total_readcount = 0; do { readcount = ad_read_short(&f, &buf); total_readcount += readcount; int remaining = readcount; WfPeakSample peak[sfinfo.channels]; int j = 0; for(; j<n; j++) { WfPeakSample w[sfinfo.channels]; memset(peak, 0, sizeof(WfPeakSample) * sfinfo.channels); int k; for (k = 0; k < MIN(remaining, WF_PEAK_RATIO); k+=sfinfo.channels) { int c; for(c=0; c<sfinfo.channels; c++) { int16_t val = buf.buf[c][WF_PEAK_RATIO * j + k]; peak[c] = (WfPeakSample) { MAX(peak[c].positive, val), MIN(peak[c].negative, MAX(val, -32767)), // TODO value of SHRT_MAX messes up the rendering - why? }; } }; remaining -= WF_PEAK_RATIO; int c; for(c=0; c<sfinfo.channels; c++) { w[c] = peak[c]; total[c] = (WfPeakSample) { MAX(total[c].positive, w[c].positive), MIN(total[c].negative, w[c].negative), }; } total_frames_written += sf_writef_short (outfile, (short*)w, WF_PEAK_VALUES_PER_SAMPLE); } } while (readcount > 0); #if 0 if(f.info.channels > 1) dbg(0, "max=%i,%i min=%i,%i", total[0].positive, total[1].positive, total[0].negative, total[1].negative); else dbg(0, "max=%i min=%i", total[0].positive, total[0].negative); #endif #ifdef DEBUG if(g_str_has_suffix(infilename, ".mp3")) { dbg(1, "mp3"); f.info.frames = total_readcount; // update the estimate with the real frame count. } #else if(total_frames_written / WF_PEAK_VALUES_PER_SAMPLE != f.info.frames / WF_PEAK_RATIO) { gwarn("unexpected number of frames: %i != %Lu", total_frames_written / WF_PEAK_VALUES_PER_SAMPLE, f.info.frames / WF_PEAK_RATIO); } #endif ad_close(&f); sf_close (outfile); g_free(sf_data); int renamed = !rename(tmp_path, peak_filename); g_free(tmp_path); if(!renamed) return false; return true; }
bool draw_wave_buffer_v_hi(Renderer* renderer, WaveformActor* actor, int block, bool is_first, bool is_last, double x_block0) { //for use at resolution 1, operates on audio data, NOT peak data. // @b_region - sample range within the current block. b_region.start is relative to the Waveform, not the block. // @rect - the canvas area corresponding exactly to the WfSampleRegion. XXX changed. // variable names: variables prefixed with x_ relate to screen coordinates (pixels), variables prefixed with s_ related to sample frames. const Waveform* w = actor->waveform; const WaveformContext* wfc = actor->canvas; const WfActorPriv* _a = actor->priv; const RenderInfo* ri = &_a->render_info; VHiRenderer* vhr = (VHiRenderer*)renderer; const WfRectangle* rect = &ri->rect; WfAudioData* audio = &w->priv->audio; if(!audio->n_blocks || w->offline) return false; WfBuf16* buf = audio->buf16[block]; if(!buf) return false; if(is_last) vhr->block_region_v_hi.len = (ri->region.start + ri->region.len) % WF_SAMPLES_PER_TEXTURE; //alternative calculation of block_region_v_hi - does it give same results? NO uint64_t st = MAX((uint64_t)(ri->region.start), (uint64_t)((block) * ri->samples_per_texture)); uint64_t e = MIN((uint64_t)(ri->region.start + ri->region.len), (uint64_t)((block + 1) * ri->samples_per_texture)); WfSampleRegion block_region_v_hi2 = {st, e - st}; //dbg(0, "block_region_v_hi=%Lu(%Lu)-->%Lu len=%Lu (buf->size=%Lu r->region=%Lu-->%Lu)", st, (uint64_t)block_region_v_hi.start, e, (uint64_t)block_region_v_hi2.len, ((uint64_t)buf->size), ((uint64_t)region.start), ((uint64_t)region.start) + ((uint64_t)region.len)); WfSampleRegion b_region = block_region_v_hi2; g_return_val_if_fail(b_region.len <= buf->size, false); if(rect->left + rect->len < ri->viewport.left){ gerr("rect is outside viewport"); } _v_hi_set_gl_state(actor); //#define BIG_NUMBER 4096 #define BIG_NUMBER 8192 // temporarily increased pending cropping to viewport-left Range sr = {{0,0},{0,0}, 0}; //TODO check we are consistent in that these values are all *within the current block* Range xr = {{0,0},{0,0}, 0}; const double zoom = rect->len / (double)ri->region.len; const float _block_wid = WF_SAMPLES_PER_TEXTURE * zoom; float block_rect_start = is_first ? fmodf(rect->left, _block_wid) : x_block0; // TODO simplify. why 2 separate cases needed? ** try just using the first case WfRectangle b_rect = {block_rect_start, rect->top, b_region.len * zoom, rect->height}; if(!(ri->viewport.right > b_rect.left)) gwarn("outside viewport: vp.r=%.2f b_rect.l=%.2f", ri->viewport.right, b_rect.left); g_return_val_if_fail(ri->viewport.right > b_rect.left, false); if(!(b_rect.left + b_rect.len > ri->viewport.left)) gwarn("outside viewport: vp.l=%.1f b_rect.l=%.1f b_rect.len=%.1f", ri->viewport.left, b_rect.left, b_rect.len); g_return_val_if_fail(b_rect.left + b_rect.len > ri->viewport.left, false); #ifdef MULTILINE_SHADER #elif defined(VERTEX_ARRAYS) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); int n_lines = MIN(BIG_NUMBER, ri->viewport.right - b_rect.left); // TODO the arrays possibly can be smaller - dont use b_rect.left, use x0 Quad quads[n_lines]; Vertex texture_coords[n_lines * 4]; int j; for(j=0;j<n_lines;j++){ texture_coords[j * 4 ] = (Vertex){0.0, 0.0}; texture_coords[j * 4 + 1] = (Vertex){1.0, 0.0}; texture_coords[j * 4 + 2] = (Vertex){1.0, 1.0}; texture_coords[j * 4 + 3] = (Vertex){0.0, 1.0}; } glVertexPointer (TWO_COORDS_PER_VERTEX, GL_FLOAT, 0, quads); glTexCoordPointer (TWO_COORDS_PER_VERTEX, GL_FLOAT, 0, texture_coords); #endif #ifndef MULTILINE_SHADER uint32_t rgba = actor->fg_colour; const float r = ((float)((rgba >> 24) ))/0x100; const float g = ((float)((rgba >> 16) & 0xff))/0x100; const float b = ((float)((rgba >> 8) & 0xff))/0x100; const float alpha = ((float)((rgba ) & 0xff))/0x100; #endif #ifdef MULTILINE_SHADER xr.border = TEX_BORDER_HI; #else xr.border = 0; #endif sr.border = xr.border / zoom; sr.inner.l = b_region.start % WF_SAMPLES_PER_TEXTURE; //const int x0 = MAX(0, floor(viewport->left - rect->left) - 3); const int x0 = b_rect.left; //const int x0 = MIN(b_rect.left, viewport->left - xr.border); // no, x and s should not be calculated independently. // sr.inner.l = (x0 - x_block0) / zoom; //TODO crop to viewport-left const int s0 = sr.outer.l = sr.inner.l - sr.border; xr.inner.l = x0; xr.outer.l = x0 - xr.border; const int x_bregion_end = b_rect.left + (b_region.start + b_region.len) * zoom; xr.inner.r = MIN(MIN(MIN( x0 + BIG_NUMBER, (int)(b_rect.left + b_rect.len)), ri->viewport.right), x_bregion_end); const int x_stop = xr.inner.r + xr.border; /* if(x_stop < b_rect.left + b_rect.len){ dbg(0, "stopping early. x_bregion_end=%i x0+B=%i", x_bregion_end, x0 + BIG_NUMBER); } */ //dbg(0, "rect=%.2f-->%.2f b_region=%Lu-->%Lu viewport=%.1f-->%.1f zoom=%.3f", b_rect.left, b_rect.left + b_rect.len, b_region.start, b_region.start + ((uint64_t)b_region.len), viewport->left, viewport->right, zoom); #ifdef MULTILINE_SHADER int mls_tex_w = x_stop - x0 + 2 * TEX_BORDER_HI; int mls_tex_h = 2; // TODO if we really are not going to add the indirection for x (for zoom > 1), use a 1d texture. int t_width = agl_power_of_two(mls_tex_w); guchar* _pbuf = g_new0(guchar, t_width * mls_tex_h); guchar* pbuf[] = {_pbuf, _pbuf + t_width}; #endif sr.inner.r = s0 + (xr.inner.r - xr.inner.l) / zoom; sr.outer.r = s0 /* TODO should include border? */+ ((double)x_stop - x0) / zoom; //dbg(0, "x0=%i x_stop=%i s=%i,%i,%i,%i xre=%i", x0, x_stop, sr.outer.l, sr.inner.l, sr.inner.r, sr.outer.r, x_bregion_end); // because we access adjacent samples, s_max is the absolute maximum index into the sample buffer (must be less than). int s_max = /*s0 + */sr.outer.r + 4 + sr.border; if(s_max > buf->size){ int over = s_max - buf->size; if(over < 4 + sr.border) dbg(0, "TODO block overlap - need to access next block"); else gerr("error at block changeover. s_max=%i over=%i", s_max, over); }else{ // its fairly normal to be limited by region, as the region can be set deliberately to match the viewport. // (the region can either correspond to a defined Section/Part of the waveform, or dynamically created with the viewport // -if it is a defined Section, we must not go beyond it. As we do not know which case we have, we must honour the region limit) //uint64_t b_region_end1 = (region.start + region.len) % buf->size; //TODO this should be the same as b_region_end2 ? but appears to be too short uint64_t b_region_end2 = (!((b_region.start + b_region.len) % WF_SAMPLES_PER_TEXTURE)) ? WF_SAMPLES_PER_TEXTURE : (b_region.start + b_region.len) % WF_SAMPLES_PER_TEXTURE;//buf->size; //if(s_max > b_region_end2) gwarn("limited by region length. region_end=%Lu %Lu", (uint64_t)((region.start + region.len) % buf->size), b_region_end2); //s_max = MIN(s_max, (region.start + region.len) % buf->size); s_max = MIN(s_max, b_region_end2); } s_max = MIN(s_max, buf->size); //note that there is never any need to be separately limited by b_region - that should be taken care of by buffer limitation? int c; for(c=0;c<w->n_channels;c++){ if(!buf->buf[c]){ gwarn("audio buf not set. c=%i", c); continue; } if(!buf->buf[c]) continue; #ifdef MULTILINE_SHADER int val0 = ((2*c + 1) * 128) / w->n_channels; if(mls_tex_w > TEX_BORDER_HI + 7) //TODO improve this test - make sure index is not negative --- may not be needed (texture is bigger now (includes borders)) memset((void*)((uintptr_t)pbuf[c] + (uintptr_t)(mls_tex_w - TEX_BORDER_HI)) - 7, val0, TEX_BORDER_HI + 7); // zero the rhs border in case it is not filled with content. memset((void*)((uintptr_t)pbuf[c]), val0, t_width); #endif #ifndef MULTILINE_SHADER int oldx = x0 - 1; int oldy = 0; #endif int s = 0; int i = 0; //int x; for(x = x0; x < x0 + BIG_NUMBER && /*rect->left +*/ x < viewport->right + border_right; x++, i++){ // note that when using texture borders, at the viewport left edge x is NOT zero, it is TEX_BORDER_HI. int x; for(x = xr.inner.l; x < x_stop; x++, i++){ double s_ = ((double)x - xr.inner.l) / zoom; double dist = s_ - s; // dist = distance in samples from one pixel to the next. //if(i < 5) dbg(0, "x=%i s_=%.3f dist=%.2f", x, s_, dist); if (dist > 2.0) { // if(dist > 5.0) gwarn("dist %.2f", dist); int ds = dist - 1; dist -= ds; s += ds; } //if(c == 0 && i < 5) dbg(0, " ss=%i", s0 + s); #ifdef MULTILINE_SHADER if (s0 + s < 0){ // left border and no valid data. pbuf[c][i] = val0; continue; } #endif if (s0 + s >= (int)buf->size ) { gwarn("end of block reached: b_region.start=%i b_region.end=%"PRIi64" %i", s0, b_region.start + ((uint64_t)b_region.len), buf->size); break; } /* if (s + 3 >= b_region.len) { gwarn("end of b_region reached: b_region.len=%i x=%i s0=%i s=%i", b_region.len, x, s0, s); break; } */ short* d = buf->buf[c]; double y1 = (s0 + s < s_max) ? d[s0 + s ] : 0; //TODO have a separately loop for the last 4 values. double y2 = (s0 + s+1 < s_max) ? d[s0 + s+1] : 0; double y3 = (s0 + s+2 < s_max) ? d[s0 + s+2] : 0; double y4 = (s0 + s+3 < s_max) ? d[s0 + s+3] : 0; double d0 = dist; double d1 = dist - 1.0; double d2 = dist - 2.0; double d3 = dist - 3.0; //TODO for MULTILINE_SHADER we probably dont want b_rect.height to affect y. int y = (int)( ( - (d1 * d2 * d3 * y1) / 6 + (d0 * d2 * d3 * y2) / 2 - (d0 * d1 * d3 * y3) / 2 + (d0 * d1 * d2 * y4) / 6 ) * wfc->v_gain * (b_rect.height / (2.0 * w->n_channels )) / (1 << 15) ); //if(i < 10) printf(" x=%i s=%i %i y=%i dist=%.2f s=%i %.2f\n", x, s0 + s, d[s0 + s], y, dist, s, floor((x / zoom) - 1)); #if defined (MULTILINE_SHADER) if(i >= mls_tex_w){ gwarn("tex index out of range %i %i", i, mls_tex_w); break; } { //int val = ((2*c + 1) * 128 + y) / w->n_channels; //if(val < 0 || val > 256) gwarn("val out of range: %i", val); -- will be out of range when vgain is high. pbuf[c][i] = val0 + MIN(y, 63); // the 63 is to stop it wrapping - would be nice to remove this. //if(i >= 0 && i < 10) dbg(0, " s=%i y2=%.4f y=%i val=%i", s + s0, y2, y, ((2*c + 1) * 128 + y) / w->n_channels); } #elif defined(VERTEX_ARRAYS) { //float ys = y * rect->height / 256.0; float x0 = oldx; float y0 = b_rect.top - oldy + b_rect.height / 2; float x1 = x; float y1 = b_rect.top - y + b_rect.height / 2; float len = sqrtf(powf((y1 - y0), 2) + powf((x1 - x0), 2)); float xoff = (y1 - y0) * 5.0 / len; float yoff = (x1 - x0) * 5.0 / len; quads[i] = (Quad){ (Vertex){x0 - xoff/2, y0 + yoff/2}, (Vertex){x1 - xoff/2, y1 + yoff/2}, (Vertex){x1 + xoff/2, y1 - yoff/2}, (Vertex){x0 + xoff/2, y0 - yoff/2}, }; //if(i > 40 && i < 50) dbg(0, "len=%.2f xoff=%.2f yoff=%.2f (%.2f, %.2f) (%.2f, %.2f)", len, xoff, yoff, quads[i].v0.x, quads[i].v0.y, quads[i].v1.x, quads[i].v1.y); } #else // draw straight line from old pos to new pos _draw_line( oldx, b_rect.top - oldy + b_rect.height / 2, x, b_rect.top - y + b_rect.height / 2, r, g, b, alpha); #endif #ifndef MULTILINE_SHADER oldx = x; oldy = y; #endif } dbg(2, "n_lines=%i x=%i-->%i", i, x0, x); #if defined (MULTILINE_SHADER) #elif defined(VERTEX_ARRAYS) glColor4f(r, g, b, alpha); glPushMatrix(); glTranslatef(0.0, (w->n_channels == 2 ? -b_rect.height/4 : 0.0) + c * b_rect.height/2, 0.0); GLsizei count = (i - 0) * 4; glDrawArrays(GL_QUADS, 0, count); glPopMatrix(); #endif } // end channel #if defined (MULTILINE_SHADER) #define TEXELS_PER_PIXEL 1.0 guint texture =_wf_create_lines_texture(pbuf[0], t_width, mls_tex_h); float len = MIN(viewport->right - viewport->left, b_rect.len); //the texture contents are cropped by viewport so we should do the same when setting the rect width. AGlQuad t = { ((float)TEX_BORDER_HI)/((float)t_width), 0.0, ((float)((x_stop - x0) * TEXELS_PER_PIXEL)) / (float)t_width, 1.0 }; wfc->priv->shaders.lines->uniform.texture_width = t_width; agl_use_program((AGlShader*)wfc->priv->shaders.lines); // to set the uniform glPushMatrix(); glTranslatef(b_rect.left, 0.0, 0.0); agl_textured_rect_real(texture, 0.0, b_rect.top, len, b_rect.height, &t); glPopMatrix(); g_free(_pbuf); #elif defined(VERTEX_ARRAYS) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif // increment for next block vhr->block_region_v_hi.start = (vhr->block_region_v_hi.start / WF_PEAK_BLOCK_SIZE + 1) * WF_PEAK_BLOCK_SIZE; vhr->block_region_v_hi.len = WF_PEAK_BLOCK_SIZE - vhr->block_region_v_hi.start % WF_PEAK_BLOCK_SIZE; return true; }