コード例 #1
0
ファイル: printer_cups.c プロジェクト: kidfolk/FreeRDP
static void printer_cups_close_printjob(rdpPrintJob* printjob)
{
	rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;

#ifndef _CUPS_API_1_4

	{
		char buf[100];

		printer_cups_get_printjob_name(buf, sizeof(buf));
		if (cupsPrintFile(printjob->printer->name, (const char *)cups_printjob->printjob_object, buf, 0, NULL) == 0)
		{
			DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString());
		}
		unlink(cups_printjob->printjob_object);
		xfree(cups_printjob->printjob_object);
	}

#else

	cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name);
	cups_printjob->printjob_id = 0;
	httpClose((http_t*)cups_printjob->printjob_object);

#endif

	xfree(cups_printjob);

	((rdpCupsPrinter*)printjob->printer)->printjob = NULL;
}
コード例 #2
0
ファイル: ofxCUPS.cpp プロジェクト: hiroyuki/ofxCUPS
void ofxCUPS::printImage(string filename)
{
    int num_options = 0;  
    cups_option_t *options = NULL;  
    
    string path = ofFilePath::getAbsolutePath("");
    string currentFile = filename;
    string printFile = path + currentFile;
    //optionen = "media=DS_PC_size"; //ds40
    
    //num_options = cupsParseOptions(optionen.c_str(), num_options, &options);  
    
    
    int last_job_id = cupsPrintFile(
                                    printerName.c_str(),
                                    printFile.c_str(),
                                    jobTitle.c_str() ? jobTitle.c_str() : "print from ofxCUPS",
                                    num_options,
                                    options);  
    
    cout << "the job id is: " << last_job_id << endl;
    if (last_job_id == 0)
    {
        cout << "print Error: " << cupsLastErrorString() << endl;
    }
    
    
    
    cupsFreeOptions(num_options,options);
}
コード例 #3
0
ファイル: ofxCUPS.cpp プロジェクト: jkosoy/ofxCUPS
void ofxCUPS::printImage(string filename, bool isAbsolutePath) {
    int num_options = 0;
    cups_option_t *options = NULL;  

    string printFile;
    if(isAbsolutePath) {
        printFile = filename;
    }
    else {
        printFile = ofToDataPath("./",true) + filename;
    }

    //optionen = "media=DS_PC_size"; //ds40
    
    //num_options = cupsParseOptions(optionen.c_str(), num_options, &options);  
    
    
    int last_job_id = cupsPrintFile(
                                    printerName.c_str(),
                                    printFile.c_str(),
                                    jobTitle.c_str() ? jobTitle.c_str() : "print from ofxCUPS",
                                    num_options,
                                    options);  
    
    cout << "the job id is: " << last_job_id << endl;
    if (last_job_id == 0)
    {
        cout << "print Error: " << cupsLastErrorString() << endl;
    }
    
    
    
    cupsFreeOptions(num_options,options);
}
コード例 #4
0
ファイル: printer_cups.c プロジェクト: LawrenceK/FreeRDP
uint32
printer_hw_close(IRP * irp)
{
	PRINTER_DEVICE_INFO * info;

	info = (PRINTER_DEVICE_INFO *) irp->dev->info;
	LLOGLN(10, ("printe_hw_close: %s id=%d", info->printer_name, irp->fileID));

	if (irp->fileID != info->printjob_id)
	{
		LLOGLN(0, ("printer_hw_close: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}

#ifndef _CUPS_API_1_4

	{
		char buf[100];

		printer_hw_get_printjob_name(buf, sizeof(buf));
		if (cupsPrintFile(info->printer_name, (const char *) info->printjob_object, buf, 0, NULL) == 0)
		{
			LLOGLN(0, ("printer_hw_close: cupsPrintFile: %s", cupsLastErrorString()));
		}
		unlink(info->printjob_object);
		free(info->printjob_object);
	}

#else

	cupsFinishDocument((http_t *) info->printjob_object, info->printer_name);
	info->printjob_id = 0;
	httpClose((http_t *) info->printjob_object);

#endif

	info->printjob_object = NULL;

	return RD_STATUS_SUCCESS;
}
コード例 #5
0
ファイル: graceapp.c プロジェクト: mariusal/grace
int gapp_print(const GraceApp *gapp, const char *fname)
{
    char tbuf[128];
    int retval = RETURN_SUCCESS;
#ifdef HAVE_CUPS
    if (gapp->rt->use_cups) {
        PrintDest *pd = &gapp->rt->print_dests[gapp->rt->print_dest];
        int i, j;
        int jobid;
        int num_options = 0;
        cups_option_t *options = NULL;

        for (i = 0; i < pd->nogroups; i++) {
            PrintOptGroup *og = &pd->ogroups[i];

            for (j = 0; j < og->nopts; j++) {
                PrintOption *po = &og->opts[j];
                char *value;

                if (po->selected != po->choices->defaults.key) {
                    dict_get_name_by_key(po->choices, po->selected, &value);
                    num_options = cupsAddOption(po->name, value, num_options, &options);
                }
            }
        }
        
        jobid = cupsPrintFile(pd->name, fname, "Grace", num_options, options);
        if (jobid == 0) {
            errmsg(ippErrorString(cupsLastError()));
            retval = RETURN_FAILURE;
        }
    } else
#endif
    {
        sprintf(tbuf, "%s %s", get_print_cmd(gapp), fname);
        system_wrap(tbuf);
    }
    
    return retval;
}
コード例 #6
0
ファイル: cups.c プロジェクト: butzopower/cups
/*
* call-seq:
*   print_job.print -> Fixnum
*
* Submit a print job to the selected printer or class. Returns true on success.
*/
static VALUE cups_print(VALUE self, VALUE file, VALUE printer)
{
    int job_id;
    file = rb_iv_get(self, "@filename");
    printer = rb_iv_get(self, "@printer");

    char *fname = RSTRING_PTR(file); // Filename
    char *target = RSTRING_PTR(printer); // Target printer string

    FILE *fp = fopen(fname,"r");
    // Check @filename actually exists...
    if( fp ) {
        fclose(fp);
        job_id = cupsPrintFile(target, fname, "rCUPS", num_options, options); // Do it.
        rb_iv_set(self, "@job_id", INT2NUM(job_id));
        return Qtrue;
    } else {
        // and if it doesn't...
        rb_raise(rb_eRuntimeError, "Couldn't find file");
        return self;
    }
}
コード例 #7
0
ファイル: cups_print.c プロジェクト: CChiappa/darktable
void dt_print_file(const int32_t imgid, const char *filename, const char *job_title, const dt_print_info_t *pinfo)
{
  // first for safety check that filename exists and is readable

  if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
  {
    dt_control_log(_("file `%s' to print not found for image %d on `%s'"), filename, imgid, pinfo->printer.name);
    return;
  }

  cups_option_t *options = NULL;
  int num_options = 0;

  // for turboprint drived printer, use the turboprint dialog
  if (pinfo->printer.is_turboprint)
  {
    const char *tp_intent_name[] = { "perception_0", "colorimetric-relative_1", "saturation_1", "colorimetric-absolute_1" };
    char tmpfile[PATH_MAX] = { 0 };

    dt_loc_get_tmp_dir(tmpfile, sizeof(tmpfile));
    g_strlcat(tmpfile, "/dt_cups_opts_XXXXXX", sizeof(tmpfile));

    gint fd = g_mkstemp(tmpfile);
    if(fd == -1)
    {
      dt_control_log(_("failed to create temporary file for printing options"));
      fprintf(stderr, "failed to create temporary pdf for printing options\n");
      return;
    }
    close(fd);

    // ensure that intent is in the range, may happen if at some point we add new intent in the list
    const int intent = (pinfo->printer.intent < 4) ? pinfo->printer.intent : 0;

    // spawn turboprint command
    gchar * argv[15] = { 0 };

    argv[0] = "turboprint";
    argv[1] = g_strdup_printf("--printer=%s", pinfo->printer.name);
    argv[2] = "--options";
    argv[3] = g_strdup_printf("--output=%s", tmpfile);
    argv[4] = "-o";
    argv[5] = "copies=1";
    argv[6] = "-o";
    argv[7] = g_strdup_printf("PageSize=%s", pinfo->paper.common_name);
    argv[8] = "-o";
    argv[9] = "InputSlot=AutoSelect";
    argv[10] = "-o";
    argv[11] = g_strdup_printf("zedoIntent=%s", tp_intent_name[intent]);
    argv[12] = "-o";
    argv[13] = g_strdup_printf("MediaType=%s", pinfo->medium.name);
    argv[14] = NULL;

    gint exit_status = 0;

    g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
                  NULL, NULL, NULL, NULL, &exit_status, NULL);

    g_free(argv[1]);
    g_free(argv[3]);
    g_free(argv[7]);
    g_free(argv[11]);
    g_free(argv[13]);

    if (exit_status==0)
    {
      FILE *stream = g_fopen(tmpfile, "rb");

      while(1)
      {
        char optname[100];
        char optvalue[100];
        const int ropt = fscanf(stream, "%*s %[^= ]=%s", optname, optvalue);

        // if we parsed an option name=value
        if (ropt==2)
        {
          char *v = optvalue;

          // remove possible single quote around value
          if (*v == '\'') v++;
          if (v[strlen(v)-1] == '\'') v[strlen(v)-1] = '\0';

          num_options = cupsAddOption(optname, v, num_options, &options);
        }
        else if (ropt == EOF)
          break;
      }
      fclose(stream);
      g_unlink(tmpfile);
    }
    else
    {
      dt_print(DT_DEBUG_PRINT, "[print]   command fails with %d, cancel printing\n", exit_status);
      return;
    }
  }
  else
  {
    cups_dest_t *dests;
    int num_dests = cupsGetDests(&dests);
    cups_dest_t *dest = cupsGetDest(pinfo->printer.name, NULL, num_dests, dests);

    for (int j = 0; j < dest->num_options; j ++)
      if (cupsGetOption(dest->options[j].name, num_options,
                        options) == NULL)
        num_options = cupsAddOption(dest->options[j].name,
                                    dest->options[j].value,
                                    num_options, &options);

    cupsFreeDests(num_dests, dests);

    // if we have a profile, disable cm on CUPS, this is important as dt does the cm

    num_options = cupsAddOption("cm-calibration", *pinfo->printer.profile ? "true" : "false", num_options, &options);

    // media to print on

    num_options = cupsAddOption("media", pinfo->paper.name, num_options, &options);

    // the media type to print on

    num_options = cupsAddOption("MediaType", pinfo->medium.name, num_options, &options);

    // never print two-side

    num_options = cupsAddOption("sides", "one-sided", num_options, &options);

    // and a single image per page

    num_options = cupsAddOption("number-up", "1", num_options, &options);

    // if the printer has no hardward margins activate the borderless mode

    if (pinfo->printer.hw_margin_top == 0 || pinfo->printer.hw_margin_bottom == 0
        || pinfo->printer.hw_margin_left == 0 || pinfo->printer.hw_margin_right == 0)
    {
      // there is many variant for this parameter
      num_options = cupsAddOption("StpFullBleed", "true", num_options, &options);
      num_options = cupsAddOption("STP_FullBleed", "true", num_options, &options);
      num_options = cupsAddOption("Borderless", "true", num_options, &options);
    }

    num_options = cupsAddOption("landscape", pinfo->page.landscape ? "true" : "false", num_options, &options);
  }

  // print lp options

  dt_print(DT_DEBUG_PRINT, "[print] printer options (%d)\n", num_options);
  for (int k=0; k<num_options; k++)
    dt_print(DT_DEBUG_PRINT, "[print]   %2d  %s=%s\n", k+1, options[k].name, options[k].value);

  const int job_id = cupsPrintFile(pinfo->printer.name, filename, job_title, num_options, options);

  if (job_id == 0)
    dt_control_log(_("error while printing `%s' on `%s'"), job_title, pinfo->printer.name);
  else
    dt_control_log(_("printing `%s' on `%s'"), job_title, pinfo->printer.name);

  cupsFreeOptions (num_options, options);
}
コード例 #8
0
ファイル: testcups.c プロジェクト: jelmer/cups
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		status = 0,		/* Exit status */
		i,			/* Looping var */
		num_dests;		/* Number of destinations */
  cups_dest_t	*dests,			/* Destinations */
		*dest,			/* Current destination */
		*named_dest;		/* Current named destination */
  const char	*ppdfile;		/* PPD file */
  ppd_file_t	*ppd;			/* PPD file data */
  int		num_jobs;		/* Number of jobs for queue */
  cups_job_t	*jobs;			/* Jobs for queue */


  if (argc > 1)
  {
    if (!strcmp(argv[1], "enum"))
    {
      cups_ptype_t	mask = CUPS_PRINTER_LOCAL,
					/* Printer type mask */
			type = CUPS_PRINTER_LOCAL;
					/* Printer type */
      int		msec = 0;	/* Timeout in milliseconds */


      for (i = 2; i < argc; i ++)
        if (isdigit(argv[i][0] & 255) || argv[i][0] == '.')
          msec = (int)(atof(argv[i]) * 1000);
        else if (!_cups_strcasecmp(argv[i], "bw"))
        {
          mask |= CUPS_PRINTER_BW;
          type |= CUPS_PRINTER_BW;
        }
        else if (!_cups_strcasecmp(argv[i], "color"))
        {
          mask |= CUPS_PRINTER_COLOR;
          type |= CUPS_PRINTER_COLOR;
        }
        else if (!_cups_strcasecmp(argv[i], "mono"))
        {
          mask |= CUPS_PRINTER_COLOR;
        }
        else if (!_cups_strcasecmp(argv[i], "duplex"))
        {
          mask |= CUPS_PRINTER_DUPLEX;
          type |= CUPS_PRINTER_DUPLEX;
        }
        else if (!_cups_strcasecmp(argv[i], "simplex"))
        {
          mask |= CUPS_PRINTER_DUPLEX;
        }
        else if (!_cups_strcasecmp(argv[i], "staple"))
        {
          mask |= CUPS_PRINTER_STAPLE;
          type |= CUPS_PRINTER_STAPLE;
        }
        else if (!_cups_strcasecmp(argv[i], "copies"))
        {
          mask |= CUPS_PRINTER_COPIES;
          type |= CUPS_PRINTER_COPIES;
        }
        else if (!_cups_strcasecmp(argv[i], "collate"))
        {
          mask |= CUPS_PRINTER_COLLATE;
          type |= CUPS_PRINTER_COLLATE;
        }
        else if (!_cups_strcasecmp(argv[i], "punch"))
        {
          mask |= CUPS_PRINTER_PUNCH;
          type |= CUPS_PRINTER_PUNCH;
        }
        else if (!_cups_strcasecmp(argv[i], "cover"))
        {
          mask |= CUPS_PRINTER_COVER;
          type |= CUPS_PRINTER_COVER;
        }
        else if (!_cups_strcasecmp(argv[i], "bind"))
        {
          mask |= CUPS_PRINTER_BIND;
          type |= CUPS_PRINTER_BIND;
        }
        else if (!_cups_strcasecmp(argv[i], "sort"))
        {
          mask |= CUPS_PRINTER_SORT;
          type |= CUPS_PRINTER_SORT;
        }
        else if (!_cups_strcasecmp(argv[i], "mfp"))
        {
          mask |= CUPS_PRINTER_MFP;
          type |= CUPS_PRINTER_MFP;
        }
        else if (!_cups_strcasecmp(argv[i], "printer"))
        {
          mask |= CUPS_PRINTER_MFP;
        }
        else if (!_cups_strcasecmp(argv[i], "large"))
        {
          mask |= CUPS_PRINTER_LARGE;
          type |= CUPS_PRINTER_LARGE;
        }
        else if (!_cups_strcasecmp(argv[i], "medium"))
        {
          mask |= CUPS_PRINTER_MEDIUM;
          type |= CUPS_PRINTER_MEDIUM;
        }
        else if (!_cups_strcasecmp(argv[i], "small"))
        {
          mask |= CUPS_PRINTER_SMALL;
          type |= CUPS_PRINTER_SMALL;
        }
        else
          fprintf(stderr, "Unknown argument \"%s\" ignored...\n", argv[i]);

      cupsEnumDests(CUPS_DEST_FLAGS_NONE, msec, NULL, type, mask, enum_cb, NULL);
    }
    else if (!strcmp(argv[1], "password"))
    {
      const char *pass = cupsGetPassword("Password:"******"Password entered: %s\n", pass);
      else
	puts("No password entered.");
    }
    else if (!strcmp(argv[1], "ppd") && argc == 3)
    {
     /*
      * ./testcups ppd printer
      */

      http_status_t	http_status;	/* Status */
      char		buffer[1024];	/* PPD filename */
      time_t		modtime = 0;	/* Last modified */

      if ((http_status = cupsGetPPD3(CUPS_HTTP_DEFAULT, argv[2], &modtime,
                                     buffer, sizeof(buffer))) != HTTP_STATUS_OK)
        printf("Unable to get PPD: %d (%s)\n", (int)http_status,
               cupsLastErrorString());
      else
        puts(buffer);
    }
    else if (!strcmp(argv[1], "print") && argc == 5)
    {
     /*
      * ./testcups print printer file interval
      */

      int		interval,	/* Interval between writes */
			job_id;		/* Job ID */
      cups_file_t	*fp;		/* Print file */
      char		buffer[16384];	/* Read/write buffer */
      ssize_t		bytes;		/* Bytes read/written */

      if ((fp = cupsFileOpen(argv[3], "r")) == NULL)
      {
	printf("Unable to open \"%s\": %s\n", argv[2], strerror(errno));
	return (1);
      }

      if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, argv[2], "testcups", 0,
				  NULL)) <= 0)
      {
	printf("Unable to create print job on %s: %s\n", argv[1],
	       cupsLastErrorString());
	return (1);
      }

      interval = atoi(argv[4]);

      if (cupsStartDocument(CUPS_HTTP_DEFAULT, argv[1], job_id, argv[2],
			    CUPS_FORMAT_AUTO, 1) != HTTP_STATUS_CONTINUE)
      {
	puts("Unable to start document!");
	return (1);
      }

      while ((bytes = cupsFileRead(fp, buffer, sizeof(buffer))) > 0)
      {
	printf("Writing %d bytes...\n", (int)bytes);

	if (cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer,
				 bytes) != HTTP_STATUS_CONTINUE)
	{
	  puts("Unable to write bytes!");
	  return (1);
	}

        if (interval > 0)
	  sleep(interval);
      }

      cupsFileClose(fp);

      if (cupsFinishDocument(CUPS_HTTP_DEFAULT,
                             argv[1]) > IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED)
      {
	puts("Unable to finish document!");
	return (1);
      }
    }
    else
    {
      puts("Usage:");
      puts("");
      puts("Run basic unit tests:");
      puts("");
      puts("    ./testcups");
      puts("");
      puts("Enumerate printers (for N seconds, -1 for indefinitely):");
      puts("");
      puts("    ./testcups enum [seconds]");
      puts("");
      puts("Ask for a password:"******"");
      puts("    ./testcups password");
      puts("");
      puts("Get the PPD file:");
      puts("");
      puts("    ./testcups ppd printer");
      puts("");
      puts("Print a file (interval controls delay between buffers in seconds):");
      puts("");
      puts("    ./testcups print printer file interval");
      return (1);
    }

    return (0);
  }

 /*
  * cupsGetDests()
  */

  fputs("cupsGetDests: ", stdout);
  fflush(stdout);

  num_dests = cupsGetDests(&dests);

  if (num_dests == 0)
  {
    puts("FAIL");
    return (1);
  }
  else
  {
    printf("PASS (%d dests)\n", num_dests);

    for (i = num_dests, dest = dests; i > 0; i --, dest ++)
    {
      printf("    %s", dest->name);

      if (dest->instance)
        printf("    /%s", dest->instance);

      if (dest->is_default)
        puts(" ***DEFAULT***");
      else
        putchar('\n');
    }
  }

 /*
  * cupsGetDest(NULL)
  */

  fputs("cupsGetDest(NULL): ", stdout);
  fflush(stdout);

  if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) == NULL)
  {
    for (i = num_dests, dest = dests; i > 0; i --, dest ++)
      if (dest->is_default)
        break;

    if (i)
    {
      status = 1;
      puts("FAIL");
    }
    else
      puts("PASS (no default)");

    dest = NULL;
  }
  else
    printf("PASS (%s)\n", dest->name);

 /*
  * cupsGetNamedDest(NULL, NULL, NULL)
  */

  fputs("cupsGetNamedDest(NULL, NULL, NULL): ", stdout);
  fflush(stdout);

  if ((named_dest = cupsGetNamedDest(NULL, NULL, NULL)) == NULL ||
      !dests_equal(dest, named_dest))
  {
    if (!dest)
      puts("PASS (no default)");
    else if (named_dest)
    {
      puts("FAIL (different values)");
      show_diffs(dest, named_dest);
      status = 1;
    }
    else
    {
      puts("FAIL (no default)");
      status = 1;
    }
  }
  else
    printf("PASS (%s)\n", named_dest->name);

  if (named_dest)
    cupsFreeDests(1, named_dest);

 /*
  * cupsGetDest(printer)
  */

  printf("cupsGetDest(\"%s\"): ", dests[num_dests / 2].name);
  fflush(stdout);

  if ((dest = cupsGetDest(dests[num_dests / 2].name, NULL, num_dests,
                          dests)) == NULL)
  {
    puts("FAIL");
    return (1);
  }
  else
    puts("PASS");

 /*
  * cupsGetNamedDest(NULL, printer, instance)
  */

  printf("cupsGetNamedDest(NULL, \"%s\", \"%s\"): ", dest->name,
         dest->instance ? dest->instance : "(null)");
  fflush(stdout);

  if ((named_dest = cupsGetNamedDest(NULL, dest->name,
                                     dest->instance)) == NULL ||
      !dests_equal(dest, named_dest))
  {
    if (named_dest)
    {
      puts("FAIL (different values)");
      show_diffs(dest, named_dest);
    }
    else
      puts("FAIL (no destination)");


    status = 1;
  }
  else
    puts("PASS");

  if (named_dest)
    cupsFreeDests(1, named_dest);

 /*
  * cupsPrintFile()
  */

  fputs("cupsPrintFile: ", stdout);
  fflush(stdout);

  if (cupsPrintFile(dest->name, "../data/testprint", "Test Page",
                    dest->num_options, dest->options) <= 0)
  {
    printf("FAIL (%s)\n", cupsLastErrorString());
    return (1);
  }
  else
    puts("PASS");

 /*
  * cupsGetPPD(printer)
  */

  fputs("cupsGetPPD(): ", stdout);
  fflush(stdout);

  if ((ppdfile = cupsGetPPD(dest->name)) == NULL)
  {
    puts("FAIL");
  }
  else
  {
    puts("PASS");

   /*
    * ppdOpenFile()
    */

    fputs("ppdOpenFile(): ", stdout);
    fflush(stdout);

    if ((ppd = ppdOpenFile(ppdfile)) == NULL)
    {
      puts("FAIL");
      return (1);
    }
    else
      puts("PASS");

    ppdClose(ppd);
    unlink(ppdfile);
  }

 /*
  * cupsGetJobs()
  */

  fputs("cupsGetJobs: ", stdout);
  fflush(stdout);

  num_jobs = cupsGetJobs(&jobs, NULL, 0, -1);

  if (num_jobs == 0)
  {
    puts("FAIL");
    return (1);
  }
  else
    puts("PASS");

  cupsFreeJobs(num_jobs, jobs);
  cupsFreeDests(num_dests, dests);

  return (status);
}
コード例 #9
0
ファイル: cups_print.c プロジェクト: Acidburn0zzz/darktable
void dt_print_file(const int32_t imgid, const char *filename, const dt_print_info_t *pinfo)
{
  // first for safety check that filename exists and is readable

  if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
  {
    dt_control_log(_("file `%s' to print not found for image %d on `%s'"), filename, imgid, pinfo->printer.name);
    return;
  }

  cups_dest_t *dests;
  int num_dests = cupsGetDests(&dests);
  cups_dest_t *dest = cupsGetDest(pinfo->printer.name, NULL, num_dests, dests);

  cups_option_t *options = NULL;
  int num_options = 0;

  for (int j = 0; j < dest->num_options; j ++)
    if (cupsGetOption(dest->options[j].name, num_options,
                      options) == NULL)
      num_options = cupsAddOption(dest->options[j].name,
                                  dest->options[j].value,
                                  num_options, &options);

  // disable cm on CUPS, this is important as dt does the cm

  if (*pinfo->printer.profile)
    num_options = cupsAddOption("cm-calibration", "true", num_options, &options);

  // media to print on

  num_options = cupsAddOption("media", pinfo->paper.name, num_options, &options);

  // never print two-side

  num_options = cupsAddOption("sides", "one-sided", num_options, &options);

  // and a single image per page

  num_options = cupsAddOption("number-up", "1", num_options, &options);

  // if the printer has no hardward margins activate the borderless mode

  if (pinfo->printer.hw_margin_top == 0 || pinfo->printer.hw_margin_bottom == 0
      || pinfo->printer.hw_margin_left == 0 || pinfo->printer.hw_margin_right == 0)
  {
    // there is many variant for this parameter
    num_options = cupsAddOption("StpFullBleed", "true", num_options, &options);
    num_options = cupsAddOption("STP_FullBleed", "true", num_options, &options);
    num_options = cupsAddOption("Borderless", "true", num_options, &options);
  }

  if (pinfo->page.landscape)
    num_options = cupsAddOption("landscape", "true", num_options, &options);
  else
    num_options = cupsAddOption("landscape", "false", num_options, &options);

  // print lp options

  dt_print(DT_DEBUG_PRINT, "[print] printer options (%d)\n", num_options);
  for (int k=0; k<num_options; k++)
    dt_print(DT_DEBUG_PRINT, "[print]   %s=%s\n", options[k].name, options[k].value);

  const int job_id = cupsPrintFile(pinfo->printer.name, filename,  "darktable", num_options, options);

  if (job_id == 0)
    dt_control_log(_("error while printing image %d on `%s'"), imgid, pinfo->printer.name);
  else
    dt_control_log(_("printing image %d on `%s'"), imgid, pinfo->printer.name);

  cupsFreeOptions (num_options, options);
}