@esslassi/electron-printer 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +235 -167
- package/lib/electronPrinter.d.ts +52 -24
- package/lib/electronPrinter.js +82 -31
- package/package.json +1 -1
- package/src/linux_printer.cpp +312 -112
- package/src/linux_printer.h +21 -11
- package/src/mac_printer.cpp +317 -110
- package/src/mac_printer.h +21 -12
- package/src/main.cpp +42 -13
- package/src/print.cpp +288 -207
- package/src/printer_interface.h +48 -10
- package/src/windows_printer.cpp +271 -134
- package/src/windows_printer.h +40 -11
- package/test.js +120 -0
package/package.json
CHANGED
package/src/linux_printer.cpp
CHANGED
|
@@ -1,171 +1,371 @@
|
|
|
1
1
|
#include "linux_printer.h"
|
|
2
|
+
|
|
2
3
|
#include <cups/cups.h>
|
|
3
4
|
#include <cups/ppd.h>
|
|
5
|
+
#include <cups/ipp.h>
|
|
6
|
+
#include <cups/http.h>
|
|
7
|
+
|
|
8
|
+
#include <vector>
|
|
9
|
+
#include <string>
|
|
10
|
+
#include <map>
|
|
11
|
+
#include <fstream>
|
|
12
|
+
#include <algorithm>
|
|
13
|
+
#include <unistd.h>
|
|
14
|
+
#include <cstring>
|
|
15
|
+
|
|
16
|
+
/* =========================================================
|
|
17
|
+
Helpers
|
|
18
|
+
========================================================= */
|
|
4
19
|
|
|
5
|
-
std::string
|
|
20
|
+
static std::string ToUpper(std::string s)
|
|
6
21
|
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return "ready";
|
|
11
|
-
case IPP_PRINTER_PROCESSING:
|
|
12
|
-
return "printing";
|
|
13
|
-
case IPP_PRINTER_STOPPED:
|
|
14
|
-
return "stopped";
|
|
15
|
-
default:
|
|
16
|
-
return "unknown";
|
|
17
|
-
}
|
|
22
|
+
std::transform(s.begin(), s.end(), s.begin(),
|
|
23
|
+
[](unsigned char c) { return (char)std::toupper(c); });
|
|
24
|
+
return s;
|
|
18
25
|
}
|
|
19
26
|
|
|
20
|
-
|
|
27
|
+
static std::vector<uint8_t> ReadAllBytes(const std::string &path)
|
|
21
28
|
{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
std::ifstream f(path, std::ios::binary);
|
|
30
|
+
if (!f) return {};
|
|
31
|
+
|
|
32
|
+
f.seekg(0, std::ios::end);
|
|
33
|
+
std::streamsize size = f.tellg();
|
|
34
|
+
if (size < 0) return {};
|
|
25
35
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
f.seekg(0, std::ios::beg);
|
|
37
|
+
|
|
38
|
+
std::vector<uint8_t> buf((size_t)size);
|
|
39
|
+
if (size > 0)
|
|
40
|
+
f.read((char*)buf.data(), size);
|
|
41
|
+
|
|
42
|
+
return buf;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* =========================================================
|
|
46
|
+
Printer Listing
|
|
47
|
+
========================================================= */
|
|
48
|
+
|
|
49
|
+
std::vector<PrinterDetailsNative> LinuxPrinter::GetPrinters()
|
|
50
|
+
{
|
|
51
|
+
std::vector<PrinterDetailsNative> out;
|
|
29
52
|
|
|
30
|
-
|
|
53
|
+
cups_dest_t *dests = nullptr;
|
|
54
|
+
int num = cupsGetDests(&dests);
|
|
55
|
+
|
|
56
|
+
for (int i = 0; i < num; i++)
|
|
31
57
|
{
|
|
32
|
-
|
|
58
|
+
PrinterDetailsNative p;
|
|
59
|
+
p.name = dests[i].name ? dests[i].name : "";
|
|
60
|
+
p.isDefault = dests[i].is_default != 0;
|
|
61
|
+
|
|
62
|
+
for (int k = 0; k < dests[i].num_options; k++)
|
|
33
63
|
{
|
|
34
|
-
|
|
64
|
+
if (dests[i].options[k].name && dests[i].options[k].value)
|
|
65
|
+
p.options[dests[i].options[k].name] = dests[i].options[k].value;
|
|
35
66
|
}
|
|
36
67
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (http != NULL)
|
|
40
|
-
{
|
|
41
|
-
ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
|
|
68
|
+
out.push_back(std::move(p));
|
|
69
|
+
}
|
|
42
70
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
71
|
+
cupsFreeDests(num, dests);
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
46
74
|
|
|
47
|
-
|
|
48
|
-
|
|
75
|
+
PrinterDetailsNative LinuxPrinter::GetPrinter(const std::string &printerName)
|
|
76
|
+
{
|
|
77
|
+
auto list = GetPrinters();
|
|
78
|
+
for (auto &p : list)
|
|
79
|
+
if (p.name == printerName)
|
|
80
|
+
return p;
|
|
49
81
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
"printer-state", IPP_TAG_ENUM);
|
|
55
|
-
if (attr != NULL)
|
|
56
|
-
{
|
|
57
|
-
info.status = GetPrinterStatus((ipp_pstate_t)ippGetInteger(attr, 0));
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
attr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT);
|
|
61
|
-
if (attr != NULL)
|
|
62
|
-
info.details["location"] = ippGetString(attr, 0, NULL);
|
|
63
|
-
|
|
64
|
-
attr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT);
|
|
65
|
-
if (attr != NULL)
|
|
66
|
-
info.details["comment"] = ippGetString(attr, 0, NULL);
|
|
67
|
-
|
|
68
|
-
attr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT);
|
|
69
|
-
if (attr != NULL)
|
|
70
|
-
info.details["driver"] = ippGetString(attr, 0, NULL);
|
|
71
|
-
|
|
72
|
-
attr = ippFindAttribute(response, "port", IPP_TAG_TEXT);
|
|
73
|
-
if (attr != NULL)
|
|
74
|
-
info.details["port"] = ippGetString(attr, 0, NULL);
|
|
75
|
-
|
|
76
|
-
ippDelete(response);
|
|
77
|
-
}
|
|
78
|
-
httpClose(http);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
cupsFreeDests(num_dests, dests);
|
|
82
|
-
return info;
|
|
82
|
+
PrinterDetailsNative p;
|
|
83
|
+
p.name = printerName;
|
|
84
|
+
p.isDefault = false;
|
|
85
|
+
return p;
|
|
83
86
|
}
|
|
84
87
|
|
|
85
|
-
std::
|
|
88
|
+
std::string LinuxPrinter::GetDefaultPrinterName()
|
|
86
89
|
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
cups_dest_t *dests = nullptr;
|
|
91
|
+
int num = cupsGetDests(&dests);
|
|
92
|
+
|
|
93
|
+
cups_dest_t *def = cupsGetDest(NULL, NULL, num, dests);
|
|
90
94
|
|
|
91
|
-
|
|
95
|
+
std::string name;
|
|
96
|
+
if (def && def->name)
|
|
97
|
+
name = def->name;
|
|
98
|
+
|
|
99
|
+
cupsFreeDests(num, dests);
|
|
100
|
+
return name;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* =========================================================
|
|
104
|
+
Driver Options / Paper
|
|
105
|
+
========================================================= */
|
|
106
|
+
|
|
107
|
+
DriverOptions LinuxPrinter::GetPrinterDriverOptions(const std::string &printerName)
|
|
108
|
+
{
|
|
109
|
+
DriverOptions out;
|
|
110
|
+
|
|
111
|
+
const char *ppdPath = cupsGetPPD(printerName.c_str());
|
|
112
|
+
if (!ppdPath) return out;
|
|
113
|
+
|
|
114
|
+
ppd_file_t *ppd = ppdOpenFile(ppdPath);
|
|
115
|
+
if (!ppd)
|
|
116
|
+
{
|
|
117
|
+
unlink(ppdPath);
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
ppdMarkDefaults(ppd);
|
|
122
|
+
|
|
123
|
+
for (ppd_option_t *opt = ppd->options; opt; opt = opt->next)
|
|
92
124
|
{
|
|
93
|
-
|
|
125
|
+
std::map<std::string, bool> choices;
|
|
126
|
+
|
|
127
|
+
for (int i = 0; i < opt->num_choices; i++)
|
|
128
|
+
{
|
|
129
|
+
bool isDefault =
|
|
130
|
+
(opt->defchoice &&
|
|
131
|
+
strcmp(opt->defchoice, opt->choices[i].choice) == 0);
|
|
132
|
+
|
|
133
|
+
choices[opt->choices[i].choice] = isDefault;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
out[opt->keyword ? opt->keyword : ""] = choices;
|
|
94
137
|
}
|
|
95
138
|
|
|
96
|
-
|
|
97
|
-
|
|
139
|
+
ppdClose(ppd);
|
|
140
|
+
unlink(ppdPath);
|
|
141
|
+
|
|
142
|
+
return out;
|
|
98
143
|
}
|
|
99
144
|
|
|
100
|
-
|
|
145
|
+
std::string LinuxPrinter::GetSelectedPaperSize(const std::string &printerName)
|
|
101
146
|
{
|
|
102
|
-
|
|
103
|
-
int num_dests = cupsGetDests(&dests);
|
|
104
|
-
cups_dest_t *dest = cupsGetDest(NULL, NULL, num_dests, dests);
|
|
147
|
+
std::string paper;
|
|
105
148
|
|
|
106
|
-
|
|
107
|
-
if (
|
|
149
|
+
const char *ppdPath = cupsGetPPD(printerName.c_str());
|
|
150
|
+
if (!ppdPath) return paper;
|
|
151
|
+
|
|
152
|
+
ppd_file_t *ppd = ppdOpenFile(ppdPath);
|
|
153
|
+
if (!ppd)
|
|
108
154
|
{
|
|
109
|
-
|
|
155
|
+
unlink(ppdPath);
|
|
156
|
+
return paper;
|
|
110
157
|
}
|
|
111
158
|
|
|
112
|
-
|
|
113
|
-
|
|
159
|
+
ppdMarkDefaults(ppd);
|
|
160
|
+
|
|
161
|
+
ppd_option_t *opt = ppdFindOption(ppd, "PageSize");
|
|
162
|
+
if (!opt)
|
|
163
|
+
opt = ppdFindOption(ppd, "PageRegion");
|
|
164
|
+
|
|
165
|
+
if (opt && opt->defchoice)
|
|
166
|
+
paper = opt->defchoice;
|
|
167
|
+
|
|
168
|
+
ppdClose(ppd);
|
|
169
|
+
unlink(ppdPath);
|
|
170
|
+
|
|
171
|
+
return paper;
|
|
114
172
|
}
|
|
115
173
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
174
|
+
/* =========================================================
|
|
175
|
+
Capabilities
|
|
176
|
+
========================================================= */
|
|
177
|
+
|
|
178
|
+
std::vector<std::string> LinuxPrinter::GetSupportedPrintFormats()
|
|
179
|
+
{
|
|
180
|
+
return { "RAW", "TEXT", "PDF", "JPEG", "POSTSCRIPT", "COMMAND", "AUTO" };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* =========================================================
|
|
184
|
+
Printing
|
|
185
|
+
========================================================= */
|
|
186
|
+
|
|
187
|
+
int LinuxPrinter::PrintDirect(const std::string &printerName,
|
|
188
|
+
const std::vector<uint8_t> &data,
|
|
189
|
+
const std::string &type,
|
|
190
|
+
const StringMap &options)
|
|
119
191
|
{
|
|
120
|
-
|
|
121
|
-
|
|
192
|
+
std::string t = ToUpper(type);
|
|
193
|
+
|
|
194
|
+
// For PDF/JPEG/POSTSCRIPT -> use temp file + cupsPrintFile
|
|
195
|
+
if (t == "PDF" || t == "JPEG" || t == "POSTSCRIPT")
|
|
196
|
+
{
|
|
197
|
+
char tmpName[] = "/tmp/esslassi_print_XXXXXX";
|
|
198
|
+
int fd = mkstemp(tmpName);
|
|
199
|
+
if (fd < 0)
|
|
200
|
+
return 0;
|
|
201
|
+
|
|
202
|
+
FILE *fp = fdopen(fd, "wb");
|
|
203
|
+
if (!fp)
|
|
204
|
+
{
|
|
205
|
+
close(fd);
|
|
206
|
+
return 0;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
fwrite(data.data(), 1, data.size(), fp);
|
|
210
|
+
fclose(fp);
|
|
211
|
+
|
|
212
|
+
cups_option_t *cupOpts = nullptr;
|
|
213
|
+
int num = 0;
|
|
214
|
+
|
|
215
|
+
for (auto &kv : options)
|
|
216
|
+
num = cupsAddOption(kv.first.c_str(),
|
|
217
|
+
kv.second.c_str(),
|
|
218
|
+
num,
|
|
219
|
+
&cupOpts);
|
|
220
|
+
|
|
221
|
+
int jobId = cupsPrintFile(
|
|
222
|
+
printerName.c_str(),
|
|
223
|
+
tmpName,
|
|
224
|
+
"Node Print Job",
|
|
225
|
+
num,
|
|
226
|
+
cupOpts);
|
|
227
|
+
|
|
228
|
+
if (cupOpts)
|
|
229
|
+
cupsFreeOptions(num, cupOpts);
|
|
230
|
+
|
|
231
|
+
unlink(tmpName);
|
|
232
|
+
|
|
233
|
+
return jobId > 0 ? jobId : 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// RAW / TEXT / COMMAND
|
|
237
|
+
int jobId = cupsCreateJob(
|
|
238
|
+
CUPS_HTTP_DEFAULT,
|
|
239
|
+
printerName.c_str(),
|
|
240
|
+
"Node Print Job",
|
|
241
|
+
0,
|
|
242
|
+
NULL);
|
|
122
243
|
|
|
123
244
|
if (jobId <= 0)
|
|
124
|
-
return
|
|
245
|
+
return 0;
|
|
125
246
|
|
|
126
|
-
http_status_t
|
|
127
|
-
|
|
128
|
-
|
|
247
|
+
http_status_t st = cupsStartDocument(
|
|
248
|
+
CUPS_HTTP_DEFAULT,
|
|
249
|
+
printerName.c_str(),
|
|
250
|
+
jobId,
|
|
251
|
+
"Node Print Job",
|
|
252
|
+
CUPS_FORMAT_RAW,
|
|
253
|
+
1);
|
|
129
254
|
|
|
130
|
-
if (
|
|
255
|
+
if (st != HTTP_STATUS_CONTINUE)
|
|
131
256
|
{
|
|
132
257
|
cupsCancelJob(printerName.c_str(), jobId);
|
|
133
|
-
return
|
|
258
|
+
return 0;
|
|
134
259
|
}
|
|
135
260
|
|
|
136
|
-
if (cupsWriteRequestData(
|
|
137
|
-
|
|
138
|
-
|
|
261
|
+
if (cupsWriteRequestData(
|
|
262
|
+
CUPS_HTTP_DEFAULT,
|
|
263
|
+
(const char*)data.data(),
|
|
264
|
+
data.size()) != HTTP_STATUS_CONTINUE)
|
|
139
265
|
{
|
|
140
266
|
cupsCancelJob(printerName.c_str(), jobId);
|
|
141
|
-
return
|
|
267
|
+
return 0;
|
|
142
268
|
}
|
|
143
269
|
|
|
144
|
-
|
|
145
|
-
|
|
270
|
+
ipp_status_t fin =
|
|
271
|
+
(ipp_status_t)cupsFinishDocument(
|
|
272
|
+
CUPS_HTTP_DEFAULT,
|
|
273
|
+
printerName.c_str());
|
|
274
|
+
|
|
275
|
+
if (fin > IPP_STATUS_OK_CONFLICT)
|
|
276
|
+
return 0;
|
|
277
|
+
|
|
278
|
+
return jobId;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
int LinuxPrinter::PrintFile(const std::string &printerName,
|
|
282
|
+
const std::string &filename)
|
|
283
|
+
{
|
|
284
|
+
int jobId = cupsPrintFile(
|
|
285
|
+
printerName.c_str(),
|
|
286
|
+
filename.c_str(),
|
|
287
|
+
"Node Print Job",
|
|
288
|
+
0,
|
|
289
|
+
NULL);
|
|
290
|
+
|
|
291
|
+
return jobId > 0 ? jobId : 0;
|
|
146
292
|
}
|
|
147
293
|
|
|
148
|
-
|
|
294
|
+
/* =========================================================
|
|
295
|
+
Job Management
|
|
296
|
+
========================================================= */
|
|
297
|
+
|
|
298
|
+
JobDetailsNative LinuxPrinter::GetJob(const std::string &printerName, int jobId)
|
|
149
299
|
{
|
|
150
|
-
|
|
151
|
-
|
|
300
|
+
JobDetailsNative j;
|
|
301
|
+
j.id = jobId;
|
|
302
|
+
j.printerName = printerName;
|
|
303
|
+
|
|
304
|
+
cups_job_t *jobs = nullptr;
|
|
305
|
+
int num = cupsGetJobs(&jobs,
|
|
306
|
+
printerName.c_str(),
|
|
307
|
+
0,
|
|
308
|
+
CUPS_WHICHJOBS_ALL);
|
|
309
|
+
|
|
310
|
+
for (int i = 0; i < num; i++)
|
|
311
|
+
{
|
|
312
|
+
if (jobs[i].id == jobId)
|
|
313
|
+
{
|
|
314
|
+
j.name = jobs[i].title ? jobs[i].title : "";
|
|
315
|
+
j.user = jobs[i].user ? jobs[i].user : "";
|
|
316
|
+
j.format = jobs[i].format ? jobs[i].format : "";
|
|
317
|
+
j.priority = jobs[i].priority;
|
|
318
|
+
j.size = jobs[i].size;
|
|
319
|
+
|
|
320
|
+
switch (jobs[i].state)
|
|
321
|
+
{
|
|
322
|
+
case IPP_JSTATE_PENDING: j.status = { "PENDING" }; break;
|
|
323
|
+
case IPP_JSTATE_HELD: j.status = { "PAUSED" }; break;
|
|
324
|
+
case IPP_JSTATE_PROCESSING: j.status = { "PRINTING" }; break;
|
|
325
|
+
case IPP_JSTATE_STOPPED: j.status = { "ABORTED" }; break;
|
|
326
|
+
case IPP_JSTATE_CANCELED: j.status = { "CANCELLED" }; break;
|
|
327
|
+
case IPP_JSTATE_ABORTED: j.status = { "ABORTED" }; break;
|
|
328
|
+
case IPP_JSTATE_COMPLETED: j.status = { "PRINTED" }; break;
|
|
329
|
+
default: j.status = { "PENDING" }; break;
|
|
330
|
+
}
|
|
152
331
|
|
|
153
|
-
|
|
154
|
-
|
|
332
|
+
j.creationTime = jobs[i].creation_time;
|
|
333
|
+
j.processingTime = jobs[i].processing_time;
|
|
334
|
+
j.completedTime = jobs[i].completed_time;
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
cupsFreeJobs(num, jobs);
|
|
340
|
+
return j;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
void LinuxPrinter::SetJob(const std::string &printerName,
|
|
344
|
+
int jobId,
|
|
345
|
+
const std::string &command)
|
|
346
|
+
{
|
|
347
|
+
std::string cmd = ToUpper(command);
|
|
155
348
|
|
|
156
|
-
if (
|
|
349
|
+
if (cmd == "CANCEL")
|
|
157
350
|
{
|
|
158
|
-
|
|
351
|
+
cupsCancelJob(printerName.c_str(), jobId);
|
|
352
|
+
return;
|
|
159
353
|
}
|
|
160
354
|
|
|
161
|
-
|
|
162
|
-
|
|
355
|
+
if (cmd == "PAUSE" || cmd == "HOLD")
|
|
356
|
+
{
|
|
357
|
+
cupsHoldJob(printerName.c_str(), jobId);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
163
360
|
|
|
164
|
-
if (
|
|
361
|
+
if (cmd == "RESUME" || cmd == "RELEASE")
|
|
165
362
|
{
|
|
166
|
-
|
|
363
|
+
cupsReleaseJob(printerName.c_str(), jobId);
|
|
364
|
+
return;
|
|
167
365
|
}
|
|
366
|
+
}
|
|
168
367
|
|
|
169
|
-
|
|
170
|
-
|
|
368
|
+
std::vector<std::string> LinuxPrinter::GetSupportedJobCommands()
|
|
369
|
+
{
|
|
370
|
+
return { "CANCEL", "PAUSE", "RESUME" };
|
|
171
371
|
}
|
package/src/linux_printer.h
CHANGED
|
@@ -1,21 +1,31 @@
|
|
|
1
1
|
#ifndef LINUX_PRINTER_H
|
|
2
2
|
#define LINUX_PRINTER_H
|
|
3
|
-
|
|
4
|
-
#include <cups/ppd.h>
|
|
5
|
-
#include <cstdint>
|
|
3
|
+
|
|
6
4
|
#include "printer_interface.h"
|
|
7
5
|
|
|
8
6
|
class LinuxPrinter : public PrinterInterface
|
|
9
7
|
{
|
|
10
|
-
private:
|
|
11
|
-
std::string GetPrinterStatus(ipp_pstate_t state);
|
|
12
|
-
|
|
13
8
|
public:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
std::vector<PrinterDetailsNative> GetPrinters() override;
|
|
10
|
+
PrinterDetailsNative GetPrinter(const std::string &printerName) override;
|
|
11
|
+
std::string GetDefaultPrinterName() override;
|
|
12
|
+
|
|
13
|
+
DriverOptions GetPrinterDriverOptions(const std::string &printerName) override;
|
|
14
|
+
std::string GetSelectedPaperSize(const std::string &printerName) override;
|
|
15
|
+
|
|
16
|
+
int PrintDirect(const std::string &printerName,
|
|
17
|
+
const std::vector<uint8_t> &data,
|
|
18
|
+
const std::string &type,
|
|
19
|
+
const StringMap &options) override;
|
|
20
|
+
|
|
21
|
+
int PrintFile(const std::string &printerName,
|
|
22
|
+
const std::string &filename) override;
|
|
23
|
+
|
|
24
|
+
std::vector<std::string> GetSupportedPrintFormats() override;
|
|
25
|
+
|
|
26
|
+
JobDetailsNative GetJob(const std::string &printerName, int jobId) override;
|
|
27
|
+
void SetJob(const std::string &printerName, int jobId, const std::string &command) override;
|
|
28
|
+
std::vector<std::string> GetSupportedJobCommands() override;
|
|
19
29
|
};
|
|
20
30
|
|
|
21
31
|
#endif
|