Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
/*
 * 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;
}
Example #7
0
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;
}
Example #8
0
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;
}
Example #9
0
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);
        }
    }
}
Example #10
0
/*
 *  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;
}
Example #11
0
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);
}
Example #12
0
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;
}
Example #13
0
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));
	}
}
Example #14
0
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;
}
Example #15
0
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);
}
Example #16
0
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);
}
Example #17
0
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);
    }
Example #18
0
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;
}
Example #19
0
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;
}
Example #20
0
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);
    }
  }
Example #21
0
/*
 *  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;
	}
Example #22
0
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;
}
Example #23
0
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;
}
Example #24
0
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;
}