summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2020-01-21 11:08:26 -0500
committerSolomon Peachy <pizza@shaftnet.org>2020-01-21 21:48:57 -0500
commit7cbc76ebd6e582a8d3f23d17e47c5bf5fbef160d (patch)
tree04213d6654946fa695de0c5277f78f3c9736b656
parenta3940462a60bac6700d7ca17402669e74caa84c7 (diff)
downloadselphy_print-7cbc76ebd6e582a8d3f23d17e47c5bf5fbef160d.tar.gz
selphy_print-7cbc76ebd6e582a8d3f23d17e47c5bf5fbef160d.tar.bz2
selphy_print-7cbc76ebd6e582a8d3f23d17e47c5bf5fbef160d.zip
Common: Major rejiggering of print job combining
* Decision logic for combining jobs is global, with a per-backend combine_job() call for the nitty-gritty * Job combining code now handles multipage jobs as well as multiple copies of a given page * Will attempt to batch multipage jobs * Automatically invoked every time a job is appended to a joblist * Only used by DNP and Mitsu D70 backends (so far)
-rw-r--r--backend_common.c240
-rw-r--r--backend_common.h65
-rw-r--r--backend_dnpds40.c78
-rw-r--r--backend_mitsu70x.c69
4 files changed, 314 insertions, 138 deletions
diff --git a/backend_common.c b/backend_common.c
index dfdca87..dfc6a4a 100644
--- a/backend_common.c
+++ b/backend_common.c
@@ -28,7 +28,7 @@
#include <errno.h>
#include <signal.h>
-#define BACKEND_VERSION "0.101"
+#define BACKEND_VERSION "0.102"
#ifndef URI_PREFIX
#error "Must Define URI_PREFIX"
#endif
@@ -823,7 +823,7 @@ static struct dyesub_backend *find_backend(const char *uri_prefix)
return NULL;
}
-static int query_markers(struct dyesub_backend *backend, void *ctx, int full)
+static int query_markers(const struct dyesub_backend *backend, void *ctx, int full)
{
struct marker *markers = NULL;
int marker_count = 0;
@@ -1063,9 +1063,10 @@ static int handle_input(struct dyesub_backend *backend, void *backend_ctx,
{
int ret = CUPS_BACKEND_OK;
int i;
- const void *job = NULL;
+ const void *job;
int data_fd = fileno(stdin);
- int current_page = 0;
+ int read_page = 0, print_page = 0;
+ struct dyesub_joblist *jlist = NULL;
if (!fname) {
if (uri && strlen(uri))
@@ -1119,71 +1120,70 @@ static int handle_input(struct dyesub_backend *backend, void *backend_ctx,
goto done;
}
-newpage:
+ /* Emit a verbose marker dump */
+ ret = query_markers(backend, backend_ctx, 1);
+ if (ret)
+ goto done;
+newpage:
/* Read in data */
+ job = NULL;
if ((ret = backend->read_parse(backend_ctx, &job, data_fd, ncopies))) {
- if (current_page)
+ if (read_page)
goto done_multiple;
else
goto done;
}
- /* The backend parser might not return a job due to job dependencies.
- Try and read another page. */
- if (!job)
+ if (!job) {
+ WARNING("No job returned by backend read_parse?\n");
goto newpage;
-
- /* Create our own joblist if necessary */
- if (!(backend->flags & BACKEND_FLAG_JOBLIST)) {
- struct dyesub_joblist *jlist = dyesub_joblist_create(backend, backend_ctx);
- if (!jlist)
- goto done;
- dyesub_joblist_addjob(jlist, job);
- job = jlist;
}
- /* Dump the full marker dump */
- ret = query_markers(backend, backend_ctx, !current_page);
- if (ret)
+ /* Create a joblist if needed */
+ if (!jlist) {
+ jlist = dyesub_joblist_create(backend, backend_ctx);
+ }
+ if (!jlist) {
+ backend->cleanup_job(job);
goto done;
-
- INFO("Printing page %d\n", ++current_page);
-
- if (test_mode >= TEST_MODE_NOPRINT ) {
- WARNING("**** TEST MODE, bypassing printing!\n");
- } else {
- ret = dyesub_joblist_print(job);
}
- dyesub_joblist_cleanup(job);
+ /* Stick it onto the end of the list */
+ dyesub_joblist_appendjob(jlist, job);
+ read_page++;
- if (ret)
- goto done;
+ INFO("Parsed page %d (%d copies)\n", read_page, ncopies);
- /* Log the completed page */
- if (!uri || !strlen(uri))
- PAGE("%d %d\n", current_page, ncopies);
+ /* If we get here, we can wait for another combined job, do so */
+ if (dyesub_joblist_canwait(jlist))
+ goto newpage;
- /* Dump a marker status update */
- ret = query_markers(backend, backend_ctx, !current_page);
+print_list:
+ /* Print the pagelist */
+ ret = dyesub_joblist_print(jlist, &print_page);
if (ret)
goto done;
+ dyesub_joblist_cleanup(jlist);
+ jlist = NULL;
+
/* Since we have no way of telling if there's more data remaining
to be read (without actually trying to read it), always assume
multiple print jobs. */
goto newpage;
done_multiple:
+ if (jlist)
+ goto print_list;
+
close(data_fd);
- /* Done printing, log the total number of pages */
- if (!uri || !strlen(uri))
- PAGE("total %d\n", current_page * ncopies);
ret = CUPS_BACKEND_OK;
done:
+ if (jlist) dyesub_joblist_cleanup(jlist);
+
return ret;
}
@@ -1709,7 +1709,7 @@ void dyesub_joblist_cleanup(const struct dyesub_joblist *list)
free((void*)list);
}
-int dyesub_joblist_addjob(struct dyesub_joblist *list, const void *job)
+static int __dyesub_joblist_addjob(struct dyesub_joblist *list, const void *job)
{
if (list->num_entries >= DYESUB_MAX_JOB_ENTRIES)
return 1;
@@ -1717,19 +1717,172 @@ int dyesub_joblist_addjob(struct dyesub_joblist *list, const void *job)
list->entries[list->num_entries++] = job;
return CUPS_BACKEND_OK;
+};
+
+static int __dyesub_append_job(struct dyesub_joblist *list, const void **vjob, int polarity)
+{
+ struct dyesub_job_common *job, *combined;
+ const struct dyesub_job_common *oldjob;
+
+ /* Create writable copy of the new job */
+ job = malloc(((const struct dyesub_job_common *)*vjob)->jobsize);
+ if (!job) {
+ ERROR("Memory allocation failure!\n");
+ return CUPS_BACKEND_RETRY_CURRENT;
+ }
+ memcpy(job, *vjob, ((const struct dyesub_job_common *)*vjob)->jobsize);
+
+ /* If we can't combine the new job, don't bother doing anything else */
+ if (!job->can_combine) {
+ free(job);
+ return CUPS_BACKEND_OK;
+ }
+
+ /* Get the old job */
+ oldjob = dyesub_joblist_popjob(list);
+
+ /* If we can't combine with it, carry on as before */
+ if (oldjob && (oldjob->copies > 1 || !oldjob->can_combine)) {
+ __dyesub_joblist_addjob(list, oldjob);
+ oldjob = NULL;
+ }
+
+ if (oldjob) {
+ /* Try to combine first copy with old job */
+ combined = list->backend->combine_jobs(oldjob, job);
+ if (combined) {
+ /* Success, add it to the list */
+ __dyesub_joblist_addjob(list, combined);
+ combined = NULL;
+
+ /* Clean up the old job */
+ list->backend->cleanup_job(oldjob);
+
+ /* Anything left in the new job? */
+ job->copies--;
+ if (job->copies == 0) {
+ /* Nope, we're done */
+ list->backend->cleanup_job(job);
+ } else if (job->copies == 1) {
+ /* Just one, shove it on the list */
+ __dyesub_joblist_addjob(list, job);
+ }
+
+ goto done;
+ } else {
+ /* Failed to combine, restore old job and continue */
+ __dyesub_joblist_addjob(list, oldjob);
+ }
+
+ polarity = 0;
+ }
+
+ /* If we have no work to do, just return */
+ if (job->copies == 1) {
+ free(job);
+ return CUPS_BACKEND_OK;
+ }
+
+ /* Attempt to combine multiple copies! */
+ combined = list->backend->combine_jobs(job, job);
+
+ if (!combined) {
+ /* Failed, so return */
+ free(job);
+ return CUPS_BACKEND_OK;
+ }
+
+ combined->copies = job->copies / 2;
+ job->copies = job->copies % 2;
+
+ /* Add the combined job at start if we can */
+ if (!polarity) {
+ __dyesub_joblist_addjob(list, combined);
+ }
+
+ /* Add the remainder, if any */
+ if (job->copies) {
+ __dyesub_joblist_addjob(list, job);
+ } else {
+ list->backend->cleanup_job(job);
+ }
+
+ /* Add combined job at end of we need to */
+ if (polarity) {
+ __dyesub_joblist_addjob(list, combined);
+ }
+
+done:
+ /* Clean up */
+ free((void*)*vjob);
+ *vjob = NULL;
+
+ return CUPS_BACKEND_OK;
}
-int dyesub_joblist_print(const struct dyesub_joblist *list)
+int dyesub_joblist_appendjob(struct dyesub_joblist *list, const void *job)
+{
+ if (list->backend->combine_jobs) {
+ int polarity = 0;
+ if (list->backend->job_polarity)
+ polarity = list->backend->job_polarity(list->ctx);
+ __dyesub_append_job(list, &job, polarity);
+ }
+
+ if (job)
+ __dyesub_joblist_addjob(list, job);
+
+ return CUPS_BACKEND_OK;
+}
+
+const void *dyesub_joblist_popjob(struct dyesub_joblist *list)
+{
+ if (list->num_entries) {
+ return list->entries[--list->num_entries];
+ }
+
+ return NULL;
+}
+
+int dyesub_joblist_canwait(struct dyesub_joblist *list)
+{
+ if (list->num_entries == DYESUB_MAX_JOB_ENTRIES)
+ return 0;
+ if (!list->num_entries)
+ return 1;
+
+ return ((const struct dyesub_job_common *)(list->entries[list->num_entries - 1]))->can_combine;
+}
+
+int dyesub_joblist_print(const struct dyesub_joblist *list, int *pagenum)
{
int i, j;
int ret;
+// int pages = 0;
+
for (i = 0 ; i < list->copies ; i++) {
for (j = 0 ; j < list->num_entries ; j++) {
if (list->entries[j]) {
- ret = list->backend->main_loop(list->ctx, list->entries[j]);
+ int copies = ((const struct dyesub_job_common *)(list->entries[j]))->copies;
+
+ INFO("Printing page %d (%d copies)\n", *pagenum + 1, copies);
+ if (test_mode >= TEST_MODE_NOPRINT )
+ WARNING("**** TEST MODE, bypassing printing!\n");
+
+ /* Print this page */
+ if (test_mode < TEST_MODE_NOPRINT ||
+ list->backend->flags & BACKEND_FLAG_DUMMYPRINT) {
+ ret = list->backend->main_loop(list->ctx, list->entries[j]);
+ if (ret)
+ return ret;
+ }
+
+// pages += copies;
+
+ /* Dump a marker status update */
+ ret = query_markers(list->backend, list->ctx, 0);
if (ret)
return ret;
-
#if 0
/* Free up the job as we go along
if we're on the final copy */
@@ -1741,5 +1894,8 @@ int dyesub_joblist_print(const struct dyesub_joblist *list)
}
}
}
+
+// INFO("Printed %d total pages/copies\n", pages);
+
return CUPS_BACKEND_OK;
}
diff --git a/backend_common.h b/backend_common.h
index afb77ae..efdb9e9 100644
--- a/backend_common.h
+++ b/backend_common.h
@@ -215,31 +215,7 @@ struct printerstats {
int32_t cnt_life[DECKS_MAX]; /* Lifetime prints */
};
-#define BACKEND_FLAG_JOBLIST 0x00000001
-#define BACKEND_FLAG_BADISERIAL 0x00000002
-
-/* Backend Functions */
-struct dyesub_backend {
- const char *name;
- const char *version;
- const char **uri_prefixes;
- const uint32_t flags;
- void (*cmdline_usage)(void); /* Optional */
- void *(*init)(void);
- int (*attach)(void *ctx, struct libusb_device_handle *dev, int type,
- uint8_t endp_up, uint8_t endp_down, int iface, uint8_t jobid);
- void (*teardown)(void *ctx);
- int (*cmdline_arg)(void *ctx, int argc, char **argv);
- int (*read_parse)(void *ctx, const void **job, int data_fd, int copies);
- void (*cleanup_job)(const void *job);
- int (*main_loop)(void *ctx, const void *job);
- int (*query_serno)(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, int iface, char *buf, int buf_len); /* Optional */
- int (*query_markers)(void *ctx, struct marker **markers, int *count);
- int (*query_stats)(void *ctx, struct printerstats *stats); /* Optional */
- const struct device_id devices[];
-};
-
-#define DYESUB_MAX_JOB_ENTRIES 2
+#define DYESUB_MAX_JOB_ENTRIES 3
struct dyesub_joblist {
// TODO: mutex/lock
@@ -250,6 +226,13 @@ struct dyesub_joblist {
const void *entries[DYESUB_MAX_JOB_ENTRIES];
};
+/* This should be the start of every per-printer job struct! */
+struct dyesub_job_common {
+ size_t jobsize;
+ int copies;
+ int can_combine;
+};
+
/* Exported functions */
int send_data(struct libusb_device_handle *dev, uint8_t endp,
const uint8_t *buf, int len);
@@ -276,9 +259,37 @@ int backend_claim_interface(struct libusb_device_handle *dev, int iface,
/* Job list manipulation */
struct dyesub_joblist *dyesub_joblist_create(const struct dyesub_backend *backend, void *ctx);
-int dyesub_joblist_addjob(struct dyesub_joblist *list, const void *job);
+int dyesub_joblist_appendjob(struct dyesub_joblist *list, const void *job);
void dyesub_joblist_cleanup(const struct dyesub_joblist *list);
-int dyesub_joblist_print(const struct dyesub_joblist *list);
+int dyesub_joblist_print(const struct dyesub_joblist *list, int *pagenum);
+const void *dyesub_joblist_popjob(struct dyesub_joblist *list);
+int dyesub_joblist_canwait(struct dyesub_joblist *list);
+
+#define BACKEND_FLAG_BADISERIAL 0x00000001
+#define BACKEND_FLAG_DUMMYPRINT 0x00000002
+
+/* Backend Functions */
+struct dyesub_backend {
+ const char *name;
+ const char *version;
+ const char **uri_prefixes;
+ const uint32_t flags;
+ void (*cmdline_usage)(void); /* Optional */
+ void *(*init)(void);
+ int (*attach)(void *ctx, struct libusb_device_handle *dev, int type,
+ uint8_t endp_up, uint8_t endp_down, int iface, uint8_t jobid);
+ void (*teardown)(void *ctx);
+ int (*cmdline_arg)(void *ctx, int argc, char **argv);
+ int (*read_parse)(void *ctx, const void **job, int data_fd, int copies);
+ void (*cleanup_job)(const void *job);
+ void *(*combine_jobs)(const void *job1, const void *job2);
+ int (*job_polarity)(void *ctx);
+ int (*main_loop)(void *ctx, const void *job);
+ int (*query_serno)(struct libusb_device_handle *dev, uint8_t endp_up, uint8_t endp_down, int iface, char *buf, int buf_len); /* Optional */
+ int (*query_markers)(void *ctx, struct marker **markers, int *count);
+ int (*query_stats)(void *ctx, struct printerstats *stats); /* Optional */
+ const struct device_id devices[];
+};
/* Global data */
extern int terminate;
diff --git a/backend_dnpds40.c b/backend_dnpds40.c
index 15374b6..e4f9ee6 100644
--- a/backend_dnpds40.c
+++ b/backend_dnpds40.c
@@ -44,10 +44,13 @@
/* Private data structure */
struct dnpds40_printjob {
+ size_t jobsize;
+ int copies;
+ int can_combine;
+
uint8_t *databuf;
int datalen;
- int copies;
uint32_t dpi;
int matte;
int cutter;
@@ -55,6 +58,7 @@ struct dnpds40_printjob {
int fullcut;
int printspeed;
int can_rewind;
+
int buf_needed;
int cut_paper;
};
@@ -201,9 +205,12 @@ static int dnpds40_query_markers(void *vctx, struct marker **markers, int *count
#define JOB_EQUIV(__x) if (job1->__x != job2->__x) goto done
-static struct dnpds40_printjob *combine_jobs(const struct dnpds40_printjob *job1,
- const struct dnpds40_printjob *job2)
+/* NOTE: Does _not_ free the input jobs */
+static void *dnp_combine_jobs(const void *vjob1,
+ const void *vjob2)
{
+ const struct dnpds40_printjob *job1 = vjob1;
+ const struct dnpds40_printjob *job2 = vjob2;
struct dnpds40_printjob *newjob = NULL;
uint32_t new_multicut;
uint16_t new_w, new_h;
@@ -308,6 +315,8 @@ static struct dnpds40_printjob *combine_jobs(const struct dnpds40_printjob *job1
newjob->databuf = malloc(((new_w*new_h+1024+54+10))*3+1024);
newjob->datalen = 0;
newjob->multicut = new_multicut;
+ newjob->can_rewind = 0;
+ newjob->can_combine = 0;
if (!newjob->databuf) {
dnpds40_cleanup_job(newjob);
newjob = NULL;
@@ -1295,8 +1304,6 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co
char buf[9] = { 0 };
struct dnpds40_printjob *job = NULL;
- struct dyesub_joblist *list;
- int can_combine = 0;
if (!ctx)
return CUPS_BACKEND_FAILED;
@@ -1307,6 +1314,7 @@ static int dnpds40_read_parse(void *vctx, const void **vjob, int data_fd, int co
return CUPS_BACKEND_RETRY_CURRENT;
}
memset(job, 0, sizeof(*job));
+ job->jobsize = sizeof(*job);
job->printspeed = -1;
/* There's no way to figure out the total job length in advance, we
@@ -1853,32 +1861,9 @@ skip_checks:
DEBUG("job->dpi %u matte %d mcut %u cutter %d/%d, bufs %d spd %d\n",
job->dpi, job->matte, job->multicut, job->cutter, job->fullcut, job->buf_needed, job->printspeed);
- list = dyesub_joblist_create(&dnpds40_backend, ctx);
-
- can_combine = job->can_rewind; /* Any rewindable size can be stacked */
+ job->can_combine = job->can_rewind; /* Any rewindable size can be stacked */
- /* Try to combine prints */
- if (job->copies > 1 && can_combine) {
- struct dnpds40_printjob *combined;
- combined = combine_jobs(job, job);
- if (combined) {
- combined->copies = job->copies / 2;
- combined->can_rewind = 0;
- dyesub_joblist_addjob(list, combined);
-
- if (job->copies & 1) {
- job->copies = 1;
- } else {
- dnpds40_cleanup_job(job);
- job = NULL;
- }
- }
- }
- if (job) {
- dyesub_joblist_addjob(list, job);
- }
-
- *vjob = list;
+ *vjob = job;
return CUPS_BACKEND_OK;
}
@@ -3189,6 +3174,34 @@ static int dnp_query_stats(void *vctx, struct printerstats *stats)
return CUPS_BACKEND_OK;
}
+static int dnp_job_polarity(void *vctx)
+{
+ struct dnpds40_ctx *ctx = vctx;
+ struct dnpds40_cmd cmd;
+ uint8_t *resp;
+ int count;
+ int len = 0;
+
+ if (test_mode >= TEST_MODE_NOATTACH)
+ return 0;
+
+ if (!ctx->supports_rewind)
+ return 0;
+
+ /* Get Media remaining */
+ dnpds40_build_cmd(&cmd, "INFO", "RQTY", 0);
+
+ resp = dnpds40_resp_cmd(ctx, &cmd, &len);
+ if (!resp)
+ return 0;
+
+ dnpds40_cleanup_string((char*)resp, len);
+ count = atoi((char*)resp+4);
+ free(resp);
+
+ return (count & 1);
+}
+
static const char *dnpds40_prefixes[] = {
"dnp_citizen", "dnpds40", // Family names, do *not* nuke.
"dnp-ds40", "dnp-ds80", "dnp-ds80dx", "dnp-ds620", "dnp-ds820", "dnp-dsrx1",
@@ -3221,9 +3234,8 @@ static const char *dnpds40_prefixes[] = {
/* Exported */
struct dyesub_backend dnpds40_backend = {
.name = "DNP DS-series / Citizen C-series",
- .version = "0.127",
+ .version = "0.128",
.uri_prefixes = dnpds40_prefixes,
- .flags = BACKEND_FLAG_JOBLIST,
.cmdline_usage = dnpds40_cmdline,
.cmdline_arg = dnpds40_cmdline_arg,
.init = dnpds40_init,
@@ -3235,6 +3247,8 @@ struct dyesub_backend dnpds40_backend = {
.query_serno = dnpds40_query_serno,
.query_markers = dnpds40_query_markers,
.query_stats = dnp_query_stats,
+ .combine_jobs = dnp_combine_jobs,
+ .job_polarity = dnp_job_polarity,
.devices = {
{ USB_VID_CITIZEN, USB_PID_DNP_DS40, P_DNP_DS40, NULL, "dnp-ds40"}, // Also Citizen CX
{ USB_VID_CITIZEN, USB_PID_DNP_DS80, P_DNP_DS80, NULL, "dnp-ds80"}, // Also Citizen CX-W and Mitsubishi CP-3800DW
diff --git a/backend_mitsu70x.c b/backend_mitsu70x.c
index 9490e55..60e38cf 100644
--- a/backend_mitsu70x.c
+++ b/backend_mitsu70x.c
@@ -114,6 +114,10 @@ typedef int (*send_image_dataFN)(struct BandImage *out, void *context,
/* Private data structure */
struct mitsu70x_printjob {
+ size_t jobsize;
+ int copies;
+ int can_combine;
+
uint8_t *databuf;
int datalen;
@@ -125,7 +129,6 @@ struct mitsu70x_printjob {
uint32_t planelen;
uint32_t matte;
int raw_format;
- int copies;
int decks_exact[2]; /* Media is exact match */
int decks_ok[2]; /* Media can be used */
@@ -920,9 +923,11 @@ static void mitsu70x_teardown(void *vctx) {
#define JOB_EQUIV(__x) if (job1->__x != job2->__x) goto done
-static struct mitsu70x_printjob *combine_jobs(const struct mitsu70x_printjob *job1,
- const struct mitsu70x_printjob *job2)
+static void *mitsu70x_combine_jobs(const void *vjob1,
+ const void *vjob2)
{
+ const struct mitsu70x_printjob *job1 = vjob1;
+ const struct mitsu70x_printjob *job2 = vjob2;
struct mitsu70x_printjob *newjob = NULL;
uint16_t newrows;
uint16_t newcols;
@@ -1059,8 +1064,6 @@ static int mitsu70x_read_parse(void *vctx, const void **vjob, int data_fd, int c
struct mitsu70x_hdr mhdr;
struct mitsu70x_printjob *job = NULL;
- struct dyesub_joblist *list;
- int can_combine;
if (!ctx)
return CUPS_BACKEND_FAILED;
@@ -1071,6 +1074,7 @@ static int mitsu70x_read_parse(void *vctx, const void **vjob, int data_fd, int c
return CUPS_BACKEND_RETRY_CURRENT;
}
memset(job, 0, sizeof(*job));
+ job->jobsize = sizeof(*job);
job->copies = copies;
repeat:
@@ -1323,8 +1327,6 @@ repeat:
}
done:
- list = dyesub_joblist_create(&mitsu70x_backend, ctx);
-
for (i = 0 ; i < ctx->num_decks ; i++) {
switch (ctx->medias[i]) {
case 0x1: // 5x3.5
@@ -1377,7 +1379,7 @@ done:
}
/* 6x4 can be combined, only on 6x8/6x9" media. */
- can_combine = 0;
+ job->can_combine = 0;
if (job->decks_exact[0] ||
job->decks_exact[1]) {
/* Exact media match, don't combine. */
@@ -1387,40 +1389,17 @@ done:
ctx->medias[0] == 0x5 ||
ctx->medias[1] == 0xf || /* Two decks possible */
ctx->medias[1] == 0x5)
- can_combine = !job->raw_format;
+ job->can_combine = !job->raw_format;
} else if (job->rows == 1076) {
if (ctx->type == P_KODAK_305 ||
ctx->type == P_MITSU_K60) {
if (ctx->medias[0] == 0x4) /* Only one deck */
- can_combine = !job->raw_format;
+ job->can_combine = !job->raw_format;
}
}
- if (copies > 1 && can_combine) {
- struct mitsu70x_printjob *combined;
- combined = combine_jobs(job, job);
- if (combined) {
- combined->copies = job->copies / 2;
- dyesub_joblist_addjob(list, combined);
-
- if (job->copies & 1) {
- job->copies = 1;
- } else {
- mitsu70x_cleanup_job(job);
- job = NULL;
- }
- }
- }
-
- if (job) {
- dyesub_joblist_addjob(list, job);
- }
-
- /* All further work is in main loop */
- if (test_mode >= TEST_MODE_NOPRINT)
- dyesub_joblist_print(list);
-
- *vjob = list;
+ /* Return what we found */
+ *vjob = job;
return CUPS_BACKEND_OK;
}
@@ -2501,6 +2480,20 @@ static int mitsu70x_query_markers(void *vctx, struct marker **markers, int *coun
return CUPS_BACKEND_OK;
}
+static int mitsu70x_job_polarity(void *vctx)
+{
+ struct mitsu70x_ctx *ctx = vctx;
+
+ if (test_mode >= TEST_MODE_NOATTACH)
+ return 0;
+
+ if (mitsu70x_query_markers(ctx, NULL, NULL))
+ return 0;
+
+ /* Only single-deck models support rewinding! */
+ return (ctx->marker[0].levelnow & 1);
+}
+
static int mitsu70x_query_stats(void *vctx, struct printerstats *stats)
{
struct mitsu70x_ctx *ctx = vctx;
@@ -2577,9 +2570,9 @@ static const char *mitsu70x_prefixes[] = {
/* Exported */
struct dyesub_backend mitsu70x_backend = {
.name = "Mitsubishi CP-D70 family",
- .version = "0.96",
+ .version = "0.97",
+ .flags = BACKEND_FLAG_DUMMYPRINT,
.uri_prefixes = mitsu70x_prefixes,
- .flags = BACKEND_FLAG_JOBLIST,
.cmdline_usage = mitsu70x_cmdline,
.cmdline_arg = mitsu70x_cmdline_arg,
.init = mitsu70x_init,
@@ -2591,6 +2584,8 @@ struct dyesub_backend mitsu70x_backend = {
.query_serno = mitsu70x_query_serno,
.query_markers = mitsu70x_query_markers,
.query_stats = mitsu70x_query_stats,
+ .combine_jobs = mitsu70x_combine_jobs,
+ .job_polarity = mitsu70x_job_polarity,
.devices = {
{ USB_VID_MITSU, USB_PID_MITSU_D70X, P_MITSU_D70X, NULL, "mitsubishi-d70dw"},
{ USB_VID_MITSU, USB_PID_MITSU_K60, P_MITSU_K60, NULL, "mitsubishi-k60dw"},