Esempio n. 1
0
G_MODULE_EXPORT int
test_fbo_main (int argc, char *argv[])
{
  ClutterColor      blue   = {0x33, 0x44, 0x55, 0xff};

  ClutterActor     *fbo;
  ClutterActor     *onscreen_source;
  ClutterActor     *stage;
  ClutterAnimation *animation;
  int               x_pos = 200;
  int               y_pos = 100;

  clutter_init (&argc, &argv);

  if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE)
    g_error("This test requires CLUTTER_FEATURE_OFFSCREEN");

  stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
  clutter_stage_set_color (CLUTTER_STAGE (stage), &blue);

  /* Create the first source */
  onscreen_source = make_source();
  clutter_actor_show_all (onscreen_source);
  clutter_group_add (stage, onscreen_source);

  y_pos = (STAGE_HEIGHT/2.0) -
          (clutter_actor_get_height (onscreen_source)/2.0);
  clutter_actor_set_position (onscreen_source, x_pos, y_pos);
  x_pos += clutter_actor_get_width (onscreen_source);

  animation = clutter_actor_animate (onscreen_source,
                                     CLUTTER_LINEAR,
                                     5000, /* 1 second duration */
                                     "rotation-angle-y", 360.0f,
                                     NULL);
  clutter_animation_set_loop (animation, TRUE);

  /* Second hand = actor from onscreen_source */
  if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL)
    g_error("onscreen fbo creation failed");

  clutter_actor_set_position (fbo, x_pos, y_pos);
  x_pos += clutter_actor_get_width (fbo);
  clutter_group_add (stage, fbo);

  /* Third hand = actor from Second hand */
  if ((fbo = clutter_texture_new_from_actor (fbo)) == NULL)
    g_error("fbo from fbo creation failed");

  clutter_actor_set_position (fbo, x_pos, y_pos);
  x_pos += clutter_actor_get_width (fbo);
  clutter_group_add (stage, fbo);

  clutter_actor_show_all (stage);
  clutter_main ();

  return 0;
}
Esempio n. 2
0
qp_source_t qp_source_create_from_func(
    const char *name, int val_type,
    void (* func)(const void *))
{
  struct qp_source *source;
  source = make_source(name, val_type);

  /* TODO: add code here */

  add_source_buffer_remove_menus(source);

  qp_app_graph_detail_source_remake();
  qp_app_set_window_titles();

  return source;
}
Esempio n. 3
0
static gboolean
make_clips (GESFormatter * self)
{
  GESPitiviFormatterPrivate *priv = GES_PITIVI_FORMATTER (self)->priv;
  GHashTable *source_table;

  GList *keys = NULL, *tmp = NULL, *reflist = NULL;

  keys = g_hash_table_get_keys (priv->clips_table);

  for (tmp = keys; tmp; tmp = tmp->next) {
    gchar *fac_id = (gchar *) tmp->data;

    reflist = g_hash_table_lookup (priv->clips_table, fac_id);
    source_table = g_hash_table_lookup (priv->sources_table, fac_id);
    make_source (self, reflist, source_table);
  }

  g_list_free (keys);
  return TRUE;
}
GESPipeline *
make_timeline (char *path, float duration, char *text, guint32 color,
    gdouble xpos, gdouble ypos)
{
  GESTimeline *timeline;
  GESTrack *trackv, *tracka;
  GESLayer *layer1;
  GESClip *srca;
  GESClip *overlay;
  GESPipeline *pipeline;
  guint64 aduration;

  pipeline = ges_pipeline_new ();

  ges_pipeline_set_mode (pipeline, TIMELINE_MODE_PREVIEW_VIDEO);

  timeline = ges_timeline_new ();
  ges_pipeline_add_timeline (pipeline, timeline);

  trackv = GES_TRACK (ges_video_track_new ());
  ges_timeline_add_track (timeline, trackv);

  tracka = GES_TRACK (ges_audio_track_new ());
  ges_timeline_add_track (timeline, tracka);

  layer1 = GES_LAYER (ges_layer_new ());
  g_object_set (layer1, "priority", (gint32) 0, NULL);

  if (!ges_timeline_add_layer (timeline, layer1))
    exit (-1);

  aduration = (guint64) (duration * GST_SECOND);
  srca = make_source (path, 0, aduration, 1);
  overlay = make_overlay (text, 0, aduration, 0, color, xpos, ypos);
  ges_layer_add_clip (layer1, srca);
  ges_layer_add_clip (layer1, overlay);

  return pipeline;
}
Esempio n. 5
0
int main ( int argc, char *argv[] ) 

/******************************************************************************/
/*
  Purpose:

    MAIN is the main program for POISSON_MPI.

  Discussion:

    This program solves Poisson's equation in a 2D region.

    The Jacobi iterative method is used to solve the linear system.

    MPI is used for parallel execution, with the domain divided
    into strips.

  Modified:

    22 September 2013

  Local parameters:

    Local, double F[(N+2)x(N+2)], the source term.

    Local, int N, the number of interior vertices in one dimension.

    Local, int NUM_PROCS, the number of MPI processes.

    Local, double U[(N+2)*(N+2)], a solution estimate.

    Local, double U_NEW[(N+2)*(N+2)], a solution estimate.
*/
{
  char file_name[100];
  double change,
         epsilon = 1.0E-03,
         *f,
         *swap,
         wall_time,
         my_change;
  int i,
      j,
      my_n,
      n,
      num_procs,
      step;
/*
  MPI initialization.
*/
  MPI_Init ( &argc, &argv );

  MPI_Comm_size ( MPI_COMM_WORLD, &num_procs );

  MPI_Comm_rank ( MPI_COMM_WORLD, &my_rank );
/*
  Read commandline arguments, if present.
*/
  if ( 1 < argc )
  {
    sscanf ( argv[1], "%d", &N );
  }
  else
  {
    N = 32;
  }

  if ( 2 < argc )
  {
    sscanf ( argv[2], "%lf", &epsilon );
  }
  else
  {
    epsilon = 1.0E-03;
  }
  if ( 3 < argc )
  {
    strcpy ( file_name, argv[3] );
  }
  else
  {
    strcpy ( file_name, "poisson_mpi.out" );
  }
/*
  Print out initial information.
*/
  if ( my_rank == 0 ) 
  {
    timestamp ( );
    printf ( "\n" );
    printf ( "POISSON_MPI:\n" );
    printf ( "  C version\n" );
    printf ( "  2-D Poisson equation using Jacobi algorithm\n" );
    printf ( "  ===========================================\n" );
    printf ( "  MPI version: 1-D domains, non-blocking send/receive\n" );
    printf ( "  Number of processes         = %d\n", num_procs );
    printf ( "  Number of interior vertices = %d\n", N );
    printf ( "  Desired fractional accuracy = %f\n", epsilon );
    printf ( "\n" );
  }

  allocate_arrays ( );
  f = make_source ( );
  make_domains ( num_procs );

  step = 0;
/*
  Begin timing.
*/
  wall_time = MPI_Wtime ( );
/*
  Begin iteration.
*/
  do 
  {
    jacobi ( num_procs, f );
    ++step;
/* 
  Estimate the error 
*/
    change = 0.0;
    n = 0;

    my_change = 0.0;
    my_n = 0;

    for ( i = i_min[my_rank]; i <= i_max[my_rank]; i++ )
    {
      for ( j = 1; j <= N; j++ )
      {
        if ( u_new[INDEX(i,j)] != 0.0 ) 
        {
          my_change = my_change + fabs ( 1.0 - u[INDEX(i,j)] / u_new[INDEX(i,j)] );
          my_n = my_n + 1;
        }
      }
    }
    MPI_Allreduce ( &my_change, &change, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD );

    MPI_Allreduce ( &my_n, &n, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );

    if ( n != 0 )
    {
      change = change / n;
    }
    if ( my_rank == 0 && ( step % 10 ) == 0 ) 
    {
      printf ( "  N = %d, n = %d, my_n = %d, Step %4d  Error = %g\n", N, n, my_n, step, change );
    }
/* 
  Interchange U and U_NEW.
*/
    swap = u;
    u = u_new;
    u_new = swap;
  } while ( epsilon < change );

/* 
  Here is where you can copy the solution to process 0 
  and print to a file.
*/

/*
  Report on wallclock time.
*/
  wall_time = MPI_Wtime() - wall_time;
  if ( my_rank == 0 )
  {
    printf ( "\n" );
    printf ( "  Wall clock time = %f secs\n", wall_time );
  }
/*
  Terminate MPI.
*/
  MPI_Finalize ( );
/*
  Free memory.
*/
  free ( f );
/*
  Terminate.
*/
  if ( my_rank == 0 )
  {
    printf ( "\n" );
    printf ( "POISSON_MPI:\n" );
    printf ( "  Normal end of execution.\n" );
    printf ( "\n" );
    timestamp ( );
  }
 
  return 0;
}
void TestRandomSequence(int window_width, int stride, int frames) {
    int planes = 4;
    int image_width = 30;
    int image_height = 50;

    srand(0);

    input::Traits<engine::ImageStack> meta_info;
    for (int plane = 0; plane < planes; ++plane) {
        image::MetaInfo<2> plane_meta_info;
        plane_meta_info.size = engine::Image2D::Size(
            image_width * boost::units::camera::pixel,
            image_height * boost::units::camera::pixel);
        meta_info.push_back(plane_meta_info, traits::Optics());
    }

    std::vector<engine::ImageStack> images;
    for (int image = 0; image < frames; ++image) {
	engine::ImageStack three_d;
	for (int plane = 0; plane < planes; ++plane) {
	    engine::Image2D two_d(engine::Image2D::Size(image_width * boost::units::camera::pixel,
                                                        image_height * boost::units::camera::pixel));
	    for (int x = 0; x < image_width; ++x) {
		for (int y = 0; y < image_height; ++y) {
		    two_d(x, y) = rand();
		}
	    }
	    three_d.push_back(two_d);
	}
	images.push_back(three_d);
    }


    std::unique_ptr<input::Source<engine::ImageStack>> filter(
        make_source(
            std::unique_ptr<input::Source<engine::ImageStack>>(
                new input::FakeSource<engine::ImageStack>(meta_info, images)),
            frame_index::from_value(window_width),
            frame_index::from_value(stride)));
    filter->get_traits();

    bool all_equal = true;
    bool did_reset = false;
    engine::ImageStack output;
    for (int i = 0; i < frames; ++i) {
        BOOST_CHECK(filter->GetNext(0, &output));

        if (i == frames / 2 && !did_reset) {
            i = -1;
            did_reset = true;
            input::BaseSource::Messages m;
            m.set(input::BaseSource::RepeatInput);
            filter->dispatch(m);
            continue;
        }

        for (int p = 0; p < planes; ++p) {
	    for (int x = 0; x < image_width; ++x) {
		for (int y = 0; y < image_height; ++y) {
                    std::vector<int> window_values(window_width, -1);
                    int natural_window_start = i / stride - window_width / 2;
                    int max_window_start = (frames - 1) / stride - window_width + 1;
                    int window_start = std::max(0,
                            std::min(natural_window_start, max_window_start));
                    for (int k = 0; k < window_width; ++k) {
                        window_values[k] = images[(k + window_start) * stride].plane(p)(x, y);
                    }
                    std::sort(window_values.begin(), window_values.end());
                    int naive_median = window_values[window_width/2];
                    if (naive_median != output.background(p)(x,y)) {
                        all_equal = false;
                    }
                }
            }
        }
    }
    BOOST_CHECK(all_equal);

    BOOST_CHECK(!filter->GetNext(0, &output));
}
Esempio n. 7
0
File: io.cpp Progetto: orlp/kwik
 Source read_file(const std::string& filename) {
     auto file = std::fopen(filename.c_str(), "r");
     if (!file) throw kwik::FilesystemError(std::strerror(errno));
     OP_SCOPE_EXIT { std::fclose(file); };
     return make_source(read_full_stream(file), filename);
 }
Esempio n. 8
0
File: io.cpp Progetto: orlp/kwik
 Source read_stdin() {
     return make_source(read_full_stream(stdin), "<stdin>");
 }
static GstStateChangeReturn
gst_uri_transcode_bin_change_state (GstElement * element,
    GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstUriTranscodeBin *self = GST_URI_TRANSCODE_BIN (element);

  switch (transition) {
    case GST_STATE_CHANGE_READY_TO_PAUSED:

      if (!make_dest (self))
        goto setup_failed;

      if (!make_transcodebin (self))
        goto setup_failed;

      if (!make_source (self))
        goto setup_failed;

      if (gst_element_set_state (self->sink,
              GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
        GST_ERROR_OBJECT (self,
            "Could not set %" GST_PTR_FORMAT " state to PAUSED", self->sink);
        goto setup_failed;
      }

      if (gst_element_set_state (self->transcodebin,
              GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
        GST_ERROR_OBJECT (self,
            "Could not set %" GST_PTR_FORMAT " state to PAUSED",
            self->transcodebin);
        goto setup_failed;
      }

      if (gst_element_set_state (self->src,
              GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
        GST_ERROR_OBJECT (self,
            "Could not set %" GST_PTR_FORMAT " state to PAUSED", self->src);
        goto setup_failed;
      }

      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  if (ret == GST_STATE_CHANGE_FAILURE)
    goto beach;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      remove_all_children (self);
      break;
    default:
      break;
  }

beach:
  return ret;

setup_failed:
  remove_all_children (self);
  return GST_STATE_CHANGE_FAILURE;
}
Esempio n. 10
0
void OCL_base::init_kernel(const char* kernel_source, const char* kernel_name, 
			   std::string define_statements, bool compile_source)
{
  if(!compile_source){
    Rprintf("Binary sources not supported yet\n");
    return;
  }  

  char* kernel_buffer = 0;
  size_t k_buffer_size=0;
  // if the kernel source has been predefined in "../oCL_Kernels/oCL_Kernels.h"
  // then use that.
  if(!strcmp(kernel_source, "move_deltoids")){  // strcmp returns 0 for equal
    kernel_buffer = make_source(define_statements, move_deltoids, k_buffer_size);
  }
  if(!strcmp(kernel_source, "move_deltoids_2")){
    kernel_buffer = make_source(define_statements, move_deltoids_2, k_buffer_size);
  }
  if(!strcmp(kernel_source, "move_deltoids_dummy")){
    kernel_buffer = make_source(define_statements, move_deltoids_dummy, k_buffer_size);
  }
    

  // if kernel buffer is not defined yet, try to read it from a file
  if(!kernel_buffer){
    std::ifstream in(kernel_source, std::ios::binary);
    if(!in){
      Rprintf("Unable to open kernel source file\n");
      return;
    }
    in.seekg(0, std::ios::end);
    ssize_t end_pos = in.tellg();
    Rprintf("in.tellg() reports : %d\n", end_pos);
    in.seekg(0, std::ios::beg);
    if(!end_pos){
      Rprintf("Unable to read from kernel source file\n");
      return;
    }
    // prepend #define statements to the kernal source.
    // add one extra \n to the 
    
    k_buffer_size = 1 + define_statements.size() + (size_t)end_pos + 1;
    kernel_buffer = new char[ k_buffer_size ];
    memset((void*)kernel_buffer, 0, sizeof(char) * k_buffer_size);
    //  kernel_buffer[k_buffer_size] = 0;  // this may not be needed.
    
    size_t copied_bytes = define_statements.copy(kernel_buffer, define_statements.size());
    if(copied_bytes != define_statements.size()){
      Rprintf("Unable to copy the full define statements\n");
      delete []kernel_buffer;
      return;
    }

    kernel_buffer[ define_statements.size() ] = '\n'; // add a new line for safety

    in.read((kernel_buffer + 1 + define_statements.size()), end_pos);
    if(in.gcount() != end_pos){
      Rprintf("Unable to read to end of kernel source file: %d != %d\n",
	      end_pos, in.gcount());
      delete []kernel_buffer;
      return;
    }
  }
  // at this point kernel_buffer should be defined.
  // and we can use it to compile the kernel.

  cl_int ret = 0; // return value. Use the same for all.
  
  ret = clGetPlatformIDs(1, &platform_id, &num_platforms);
  if(ret) report_error_pf("clGetPlatformIDs", ret);
  ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_GPU, 1,
			&device_id, &num_devices );
  if(ret) report_error_pf("clGetDeviceIDs", ret);
  if(ret != CL_SUCCESS){
    Rprintf("clGetDevice returned with error: %d\n", (int)ret);
    return;
  }

  context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
  report_error_pf("clCreateContext", ret);

  command_que = clCreateCommandQueue(context, device_id, CL_QUEUE_PROFILING_ENABLE, &ret);
  report_error_pf("clCreateCommandQueue", ret);

  program = clCreateProgramWithSource(context, 1, (const char**)&kernel_buffer, 
				      (const size_t*)&k_buffer_size, &ret);
  report_error_pf("clCreateProgramWithSource", ret);

  
  clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
  report_error_pf("clBuildProgram", ret);

  char* build_log = NULL;
  size_t log_size = 1000;
  ret = clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, 0, build_log, &log_size);
  report_error_pf("clGetProgramBuildInfo", ret);
  build_log = new char[log_size+1];
  ret = clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, log_size, build_log, NULL);
  report_error_pf("clGetProgramBuildInfo", ret);
  
  // the below doesn't make much sense. But log_size is never 0, so, need to do something
  Rprintf("After building the kernel the log size is : %d\n", log_size);
  if(log_size > 2){
    Rprintf("clBuildProgram Error encountered:\n%s\n", build_log);
    Rprintf(".....\n%s\n....\n", kernel_buffer);
  }
  delete []build_log;

  kernel = clCreateKernel(program, kernel_name, &ret);
  report_error_pf("clCreateKernel", ret);
  
  delete []kernel_buffer;
  
}
Esempio n. 11
0
qp_source_t qp_source_create(const char *filename, int value_type)
{
  struct qp_source *source;
  struct qp_reader rd;
  int r;

  source = make_source(filename, value_type);

  rd.fd = -1;
  rd.rd = 0;
  rd.len = 0;
  rd.past = 0;
  rd.file = NULL;
  rd.buf = NULL;
  rd.filename = (char *) filename;
  qp_rd = &rd;

  if(strcmp(filename,"-") == 0)
  {
    rd.file = stdin;
    rd.fd = STDIN_FILENO;
  }

  if(rd.fd == -1)
    rd.fd = open(filename, O_RDONLY);

  if(rd.fd == -1)
  {
    EWARN("open(\"%s\",O_RDONLY) failed\n", filename);
    QP_EWARN("%sFailed to open file%s %s%s%s\n",
        bred, trm, btur, filename, trm);
    goto fail;
  }

  if(!is_pipe(&rd))
  {
    /* don't buffer read() and lseek() */
    qp_rd = NULL;
  }
  else
  {
    /* this is a pipe */
    DEBUG("Virturalizing a pipe%s%s\n",
        (filename[0] == '-' && filename[1] == '\0')?
        "":" with name ",
        (filename[0] == '-' && filename[1] == '\0')?
        "":filename);
    rd.buf = qp_malloc(BUF_LEN);
  }

  if((r = read_sndfile(source, &rd)))
  {
    if(r == -1)
      goto fail;


    if(rd.past && qp_rd)
    {
      VASSERT(0, "libsndfile read to much data "
          "to see that the file was not a sndfile\n");
      QP_WARN("%sFailed to read file%s %s%s%s:"
          " read wrapper failed\n",
          bred, trm, btur, filename, trm);
      goto fail;
    }

    if(qp_rd)
    {
      /* Start reading the data from the qp_rd read() buffer */
      rd.rd = 0;
      /* no need to add more to the qp_rd read() buffer */
      rd.fd = -1;
    }
    /* The above lseek() should work fine. */
    else if(lseek(rd.fd, 0, SEEK_SET))
    {
      EWARN("lseek(fd=%d, 0, SEEK_SET) failed\n", rd.fd);
      QP_EWARN("%sFailed to read file%s %s%s%s: lseek() failed\n",
          bred, trm, btur, filename, trm);
    }

    if(!rd.file)
    {
      errno = 0;
      rd.file = fdopen(rd.fd, "r");
      ASSERT(fileno(rd.file) == rd.fd);
    }
    if(!rd.file)
    {
      EWARN("fopen(\"%s\",\"r\") failed\n", filename);
      QP_EWARN("%sFailed to open file%s %s%s%s\n",
          bred, trm, btur, filename, trm);
      goto fail;
    }

    errno = 0;

    if(read_ascii(source, &rd))
      goto fail;
  }

  if(rd.buf)
  {
    free(rd.buf);
    rd.buf = NULL;
  }

  {
    /* remove any channels that have very bad data */
    struct qp_channel **c;
    size_t i = 0, chan_num = 0;
    ASSERT(source->channels);
    c = source->channels;
    while(c[i])
    {
      ASSERT(c[i]->form == QP_CHANNEL_FORM_SERIES);
      if(!is_good_double(c[i]->series.min) ||
          !is_good_double(c[i]->series.max))
      {
        struct qp_channel **n;
        
        qp_channel_destroy(c[i]);

        /* move of all pointers from c[i+1] back one */
        for(n=&c[i]; *n;++n)
          *n = *(n+1);

        /* re-malloc copying and removing one */
        source->channels = 
          qp_realloc(source->channels, sizeof(struct qp_channel *)*
              ((source->num_channels)--));
        
        /* reset c to the next one which is now at the
         * same index */
        c = source->channels;

        QP_NOTICE("removed bad channel number %zu\n", chan_num);
      }
      else
        ++i;
      ++chan_num;
    }
    ASSERT(source->num_channels == i);
  }
  
  
  if(source->num_channels == 0)
    goto fail;


  if(source->num_channels > 1)
  {
    /****** Check that there is at least one point in all the channels */
    ssize_t i, num;
    double *x;
    num = source->num_values;
    x = qp_malloc(sizeof(double)*source->num_channels);
    for(i=0;i<source->num_channels;++i)
      x[i] = qp_channel_series_double_begin(source->channels[i]);

    while(num)
    {
      int found = 0;
      for(i=0;i<source->num_channels;++i)
        if(is_good_double(x[i]))
          ++found;

      if(found >= 2)
        /* that means there is at least one x/y point
         * in all the channels. */
        break;

      --num;
      if(!num)
        break;

      for(i=0;i<source->num_channels;++i)
        x[i] = qp_channel_series_double_next(source->channels[i]);
    }

    if(!num)
    {
      QP_WARN("Failed to find a good point in data from file \"%s\"\n",
          filename);
      goto fail;
    }
  }

  
  if(source->num_channels == 0)
    goto fail;


  if(app->op_linear_channel || source->num_channels == 1)
  {
    /* Prepend a linear channel */

    /* TODO: Make this use less memory */
    
    struct qp_channel *c, **new_channels;
    double start = 0, step = 1;
    size_t len, i;

    if(app->op_linear_channel)
    {
      c = app->op_linear_channel;
      ASSERT(c->data);
      start = ((double*)c->data)[0];
      step = ((double*)c->data)[1];
    }
    else
    {
      c = qp_channel_linear_create(start, step);
    }


    len = source->num_values;
    for(i=0;i<len;++i)
      qp_channel_series_double_append(c, start + i*step);
   
    /* Prepend the channel to source->channels */
    /* reuse dummy len */
    len = source->num_channels + 1;
    new_channels = qp_malloc(sizeof(c)*len+1);
    new_channels[0] = c;
    for(i=1;i<len;++i)
      new_channels[i] = source->channels[i-1];
    new_channels[i] = NULL;
    free(source->channels);
    source->channels = new_channels;
    ++(source->num_channels);

    if(source->labels && source->num_labels !=  source->num_channels)
    {
      // shift the labels and add the linear channel label
      source->labels = qp_realloc(source->labels,
          sizeof(char *)*(source->num_labels+2));
      source->labels[source->num_labels+1] = NULL;
      for(i=source->num_labels;i>=1;--i)
        source->labels[i] = source->labels[i-1];

      char s[128];
      snprintf(s,128, "%s[0]", source->name);
      // The first channel is the linear channel.
      source->labels[0] = qp_strdup(s);
      ++source->num_labels;
    }

    /* Another source may have more values so
     * we must make a new one in case it is used again. */
    if(app->op_linear_channel)
      app->op_linear_channel = qp_channel_linear_create(start, step);
  }
  
  add_source_buffer_remove_menus(source);
  
  {
    char skip[64];
    skip[0] = '\0';
    if(app->op_skip_lines)
      snprintf(skip, 64, "(after skipping %zu) ", app->op_skip_lines);


    INFO("created source with %zu sets of values %s"
      "in %zu channels from file %s\n",
      source->num_values, skip, source->num_channels,
      filename);

    QP_INFO("created source with %zu sets of "
      "values %sin %zu channels from file \"%s\"\n",
      source->num_values, skip, source->num_channels,
      filename);
#if QP_DEBUG
    if(source->labels)
    {
      char **labels;
      APPEND("Read labels:");
      for(labels = source->labels; *labels; ++labels)
        APPEND(" \"%s\"", *labels);
      APPEND("\n");
    }
#endif
  }

  qp_rd = NULL;

  if(strcmp(filename,"-") == 0)
    /* We do not close stdin */
    return source;

  if(rd.file)
    fclose(rd.file);
  else if(rd.fd != -1)
    close(rd.fd);

  qp_app_graph_detail_source_remake();
  qp_app_set_window_titles();

  return source;

fail:

  QP_WARN("No data loaded from file \"%s\"\n",
      filename);

  if(rd.buf)
    free(rd.buf);

  if(strcmp(filename,"-") != 0)
  {
    if(rd.file)
      fclose(rd.file);
    else if(rd.fd != -1)
      close(rd.fd);
  }

  if(source)
    qp_source_destroy(source);

  qp_rd = NULL;

  return NULL;
}