@esslassi/electron-printer 0.0.5 → 0.0.7

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.
@@ -1,166 +1,373 @@
1
- #include "mac_printer.h"
2
- #include <cups/cups.h>
3
-
4
- std::string MacPrinter::GetPrinterStatus(ipp_pstate_t state)
5
- {
6
- switch (state)
7
- {
8
- case IPP_PRINTER_IDLE:
9
- return "ready";
10
- case IPP_PRINTER_PROCESSING:
11
- return "printing";
12
- case IPP_PRINTER_STOPPED:
13
- return "stopped";
14
- default:
15
- return "unknown";
16
- }
17
- }
18
-
19
- PrinterInfo MacPrinter::GetPrinterDetails(const std::string &printerName, bool isDefault)
20
- {
21
- PrinterInfo info;
22
- info.name = printerName;
23
- info.isDefault = isDefault;
24
-
25
- cups_dest_t *dests;
26
- int num_dests = cupsGetDests(&dests);
27
- cups_dest_t *dest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);
28
-
29
- if (dest != NULL)
30
- {
31
- for (int i = 0; i < dest->num_options; i++)
32
- {
33
- info.details[dest->options[i].name] = dest->options[i].value;
34
- }
35
-
36
- http_t *http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
37
- HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
38
- if (http != NULL)
39
- {
40
- ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
41
-
42
- char uri[HTTP_MAX_URI];
43
- httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
44
- "localhost", 0, "/printers/%s", printerName.c_str());
45
-
46
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
47
- "printer-uri", NULL, uri);
48
-
49
- ipp_t *response = cupsDoRequest(http, request, "/");
50
- if (response != NULL)
51
- {
52
- ipp_attribute_t *attr = ippFindAttribute(response,
53
- "printer-state", IPP_TAG_ENUM);
54
- if (attr != NULL)
55
- {
56
- info.status = GetPrinterStatus((ipp_pstate_t)ippGetInteger(attr, 0));
57
- }
58
-
59
- attr = ippFindAttribute(response, "printer-location", IPP_TAG_TEXT);
60
- if (attr != NULL)
61
- info.details["location"] = ippGetString(attr, 0, NULL);
62
-
63
- attr = ippFindAttribute(response, "printer-info", IPP_TAG_TEXT);
64
- if (attr != NULL)
65
- info.details["comment"] = ippGetString(attr, 0, NULL);
66
-
67
- attr = ippFindAttribute(response, "printer-make-and-model", IPP_TAG_TEXT);
68
- if (attr != NULL)
69
- info.details["driver"] = ippGetString(attr, 0, NULL);
70
-
71
- ippDelete(response);
72
- }
73
- httpClose(http);
74
- }
75
- }
76
- cupsFreeDests(num_dests, dests);
77
- return info;
78
- }
79
-
80
- std::vector<PrinterInfo> MacPrinter::GetPrinters()
81
- {
82
- std::vector<PrinterInfo> printers;
83
- cups_dest_t *dests;
84
- int num_dests = cupsGetDests(&dests);
85
-
86
- for (int i = 0; i < num_dests; i++)
87
- {
88
- printers.push_back(GetPrinterDetails(dests[i].name, dests[i].is_default));
89
- }
90
-
91
- cupsFreeDests(num_dests, dests);
92
- return printers;
93
- }
94
-
95
- PrinterInfo MacPrinter::GetSystemDefaultPrinter()
96
- {
97
- cups_dest_t *dests;
98
- int num_dests = cupsGetDests(&dests);
99
- cups_dest_t *dest = cupsGetDest(NULL, NULL, num_dests, dests);
100
-
101
- PrinterInfo printer;
102
- if (dest != NULL)
103
- {
104
- printer = GetPrinterDetails(dest->name, true);
105
- }
106
-
107
- cupsFreeDests(num_dests, dests);
108
- return printer;
109
- }
110
-
111
- bool MacPrinter::PrintDirect(const std::string &printerName,
112
- const std::vector<uint8_t> &data,
113
- const std::string &dataType)
114
- {
115
- int jobId = cupsCreateJob(CUPS_HTTP_DEFAULT, printerName.c_str(),
116
- "Node.js Print Job", 0, NULL);
117
-
118
- if (jobId <= 0)
119
- return false;
120
-
121
- http_status_t status = cupsStartDocument(CUPS_HTTP_DEFAULT, printerName.c_str(),
122
- jobId, "Node.js Print Job",
123
- dataType.c_str(), 1);
124
-
125
- if (status != HTTP_STATUS_CONTINUE)
126
- {
127
- cupsCancelJob(printerName.c_str(), jobId);
128
- return false;
129
- }
130
-
131
- if (cupsWriteRequestData(CUPS_HTTP_DEFAULT,
132
- reinterpret_cast<const char *>(data.data()),
133
- data.size()) != HTTP_STATUS_CONTINUE)
134
- {
135
- cupsCancelJob(printerName.c_str(), jobId);
136
- return false;
137
- }
138
-
139
- status = static_cast<http_status_t>(cupsFinishDocument(CUPS_HTTP_DEFAULT, printerName.c_str()));
140
- return status == HTTP_STATUS_OK;
141
- }
142
-
143
- PrinterInfo MacPrinter::GetStatusPrinter(const std::string &printerName)
144
- {
145
- cups_dest_t *dests;
146
- int num_dests = cupsGetDests(&dests);
147
-
148
- cups_dest_t *defaultDest = cupsGetDest(NULL, NULL, num_dests, dests);
149
- bool isDefault = false;
150
-
151
- if (defaultDest != NULL)
152
- {
153
- isDefault = (printerName == defaultDest->name);
154
- }
155
-
156
- cups_dest_t *dest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);
157
- PrinterInfo printer;
158
-
159
- if (dest != NULL)
160
- {
161
- printer = GetPrinterDetails(printerName, isDefault);
162
- }
163
-
164
- cupsFreeDests(num_dests, dests);
165
- return printer;
166
- }
1
+ #include "mac_printer.h"
2
+
3
+ #include <cups/cups.h>
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
+ ========================================================= */
19
+
20
+ static std::string ToUpper(std::string s)
21
+ {
22
+ std::transform(s.begin(), s.end(), s.begin(),
23
+ [](unsigned char c) { return (char)std::toupper(c); });
24
+ return s;
25
+ }
26
+
27
+ static std::vector<uint8_t> ReadAllBytes(const std::string &path)
28
+ {
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 {};
35
+
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> MacPrinter::GetPrinters()
50
+ {
51
+ std::vector<PrinterDetailsNative> out;
52
+
53
+ cups_dest_t *dests = nullptr;
54
+ int num = cupsGetDests(&dests);
55
+
56
+ for (int i = 0; i < num; i++)
57
+ {
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++)
63
+ {
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;
66
+ }
67
+
68
+ out.push_back(std::move(p));
69
+ }
70
+
71
+ cupsFreeDests(num, dests);
72
+ return out;
73
+ }
74
+
75
+ PrinterDetailsNative MacPrinter::GetPrinter(const std::string &printerName)
76
+ {
77
+ auto list = GetPrinters();
78
+ for (auto &p : list)
79
+ if (p.name == printerName)
80
+ return p;
81
+
82
+ PrinterDetailsNative p;
83
+ p.name = printerName;
84
+ p.isDefault = false;
85
+ return p;
86
+ }
87
+
88
+ std::string MacPrinter::GetDefaultPrinterName()
89
+ {
90
+ cups_dest_t *dests = nullptr;
91
+ int num = cupsGetDests(&dests);
92
+
93
+ cups_dest_t *def = cupsGetDest(NULL, NULL, num, dests);
94
+
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 MacPrinter::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)
124
+ {
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;
137
+ }
138
+
139
+ ppdClose(ppd);
140
+ unlink(ppdPath);
141
+
142
+ return out;
143
+ }
144
+
145
+ std::string MacPrinter::GetSelectedPaperSize(const std::string &printerName)
146
+ {
147
+ std::string paper;
148
+
149
+ const char *ppdPath = cupsGetPPD(printerName.c_str());
150
+ if (!ppdPath) return paper;
151
+
152
+ ppd_file_t *ppd = ppdOpenFile(ppdPath);
153
+ if (!ppd)
154
+ {
155
+ unlink(ppdPath);
156
+ return paper;
157
+ }
158
+
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;
172
+ }
173
+
174
+ /* =========================================================
175
+ Capabilities
176
+ ========================================================= */
177
+
178
+ std::vector<std::string> MacPrinter::GetSupportedPrintFormats()
179
+ {
180
+ return { "RAW", "TEXT", "PDF", "JPEG", "POSTSCRIPT", "COMMAND", "AUTO" };
181
+ }
182
+
183
+ /* =========================================================
184
+ Printing
185
+ ========================================================= */
186
+
187
+ int MacPrinter::PrintDirect(const std::string &printerName,
188
+ const std::vector<uint8_t> &data,
189
+ const std::string &type,
190
+ const StringMap &options)
191
+ {
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);
243
+
244
+ if (jobId <= 0)
245
+ return 0;
246
+
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);
254
+
255
+ if (st != HTTP_STATUS_CONTINUE)
256
+ {
257
+ cupsCancelJob(printerName.c_str(), jobId);
258
+ return 0;
259
+ }
260
+
261
+ if (cupsWriteRequestData(
262
+ CUPS_HTTP_DEFAULT,
263
+ (const char*)data.data(),
264
+ data.size()) != HTTP_STATUS_CONTINUE)
265
+ {
266
+ cupsCancelJob(printerName.c_str(), jobId);
267
+ return 0;
268
+ }
269
+
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 MacPrinter::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;
292
+ }
293
+
294
+ /* =========================================================
295
+ Job Management
296
+ ========================================================= */
297
+
298
+ JobDetailsNative MacPrinter::GetJob(const std::string &printerName, int jobId)
299
+ {
300
+ JobDetailsNative j;
301
+ j.id = jobId;
302
+ j.printerName = printerName;
303
+
304
+ cups_job_t *jobs = nullptr;
305
+ int num = cupsGetJobs(
306
+ &jobs,
307
+ printerName.c_str(),
308
+ 0,
309
+ CUPS_WHICHJOBS_ALL);
310
+
311
+ for (int i = 0; i < num; i++)
312
+ {
313
+ if (jobs[i].id == jobId)
314
+ {
315
+ j.name = jobs[i].title ? jobs[i].title : "";
316
+ j.user = jobs[i].user ? jobs[i].user : "";
317
+ j.format = jobs[i].format ? jobs[i].format : "";
318
+ j.priority = jobs[i].priority;
319
+ j.size = jobs[i].size;
320
+
321
+ switch (jobs[i].state)
322
+ {
323
+ case IPP_JSTATE_PENDING: j.status = { "PENDING" }; break;
324
+ case IPP_JSTATE_HELD: j.status = { "PAUSED" }; break;
325
+ case IPP_JSTATE_PROCESSING: j.status = { "PRINTING" }; break;
326
+ case IPP_JSTATE_STOPPED: j.status = { "ABORTED" }; break;
327
+ case IPP_JSTATE_CANCELED: j.status = { "CANCELLED" }; break;
328
+ case IPP_JSTATE_ABORTED: j.status = { "ABORTED" }; break;
329
+ case IPP_JSTATE_COMPLETED: j.status = { "PRINTED" }; break;
330
+ default: j.status = { "PENDING" }; break;
331
+ }
332
+
333
+ j.creationTime = jobs[i].creation_time;
334
+ j.processingTime = jobs[i].processing_time;
335
+ j.completedTime = jobs[i].completed_time;
336
+
337
+ break;
338
+ }
339
+ }
340
+
341
+ cupsFreeJobs(num, jobs);
342
+ return j;
343
+ }
344
+
345
+ void MacPrinter::SetJob(const std::string &printerName,
346
+ int jobId,
347
+ const std::string &command)
348
+ {
349
+ std::string cmd = ToUpper(command);
350
+
351
+ if (cmd == "CANCEL")
352
+ {
353
+ cupsCancelJob(printerName.c_str(), jobId);
354
+ return;
355
+ }
356
+
357
+ if (cmd == "PAUSE" || cmd == "HOLD")
358
+ {
359
+ cupsHoldJob(printerName.c_str(), jobId);
360
+ return;
361
+ }
362
+
363
+ if (cmd == "RESUME" || cmd == "RELEASE")
364
+ {
365
+ cupsReleaseJob(printerName.c_str(), jobId);
366
+ return;
367
+ }
368
+ }
369
+
370
+ std::vector<std::string> MacPrinter::GetSupportedJobCommands()
371
+ {
372
+ return { "CANCEL", "PAUSE", "RESUME" };
373
+ }
package/src/mac_printer.h CHANGED
@@ -1,22 +1,31 @@
1
- #ifndef MAC_PRINTER_H
2
- #define MAC_PRINTER_H
3
-
4
- #include <cups/cups.h>
5
- #include <cups/ppd.h>
6
- #include <cstdint>
7
- #include "printer_interface.h"
8
-
9
- class MacPrinter : public PrinterInterface
10
- {
11
- private:
12
- std::string GetPrinterStatus(ipp_pstate_t state);
13
-
14
- public:
15
- virtual PrinterInfo GetPrinterDetails(const std::string &printerName, bool isDefault = false) override;
16
- virtual std::vector<PrinterInfo> GetPrinters() override;
17
- virtual PrinterInfo GetSystemDefaultPrinter() override;
18
- virtual bool PrintDirect(const std::string &printerName, const std::vector<uint8_t> &data, const std::string &dataType) override;
19
- virtual PrinterInfo GetStatusPrinter(const std::string &printerName) override;
20
- };
21
-
22
- #endif
1
+ #ifndef MAC_PRINTER_H
2
+ #define MAC_PRINTER_H
3
+
4
+ #include "printer_interface.h"
5
+
6
+ class MacPrinter : public PrinterInterface
7
+ {
8
+ public:
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;
29
+ };
30
+
31
+ #endif
package/src/main.cpp CHANGED
@@ -1,22 +1,51 @@
1
- #include <napi.h>
2
- #include "printer_factory.h"
3
-
4
- Napi::Value PrintDirect(const Napi::CallbackInfo &info);
5
- Napi::Value GetPrinters(const Napi::CallbackInfo &info);
6
- Napi::Value GetSystemDefaultPrinter(const Napi::CallbackInfo &info);
7
- Napi::Value GetStatusPrinter(const Napi::CallbackInfo &info);
8
-
9
- Napi::Object Init(Napi::Env env, Napi::Object exports)
10
- {
11
- exports.Set(Napi::String::New(env, "printDirect"),
12
- Napi::Function::New(env, PrintDirect));
13
- exports.Set(Napi::String::New(env, "getPrinters"),
14
- Napi::Function::New(env, GetPrinters));
15
- exports.Set(Napi::String::New(env, "getDefaultPrinter"),
16
- Napi::Function::New(env, GetSystemDefaultPrinter));
17
- exports.Set(Napi::String::New(env, "getStatusPrinter"),
18
- Napi::Function::New(env, GetStatusPrinter));
19
- return exports;
20
- }
21
-
1
+ #include <napi.h>
2
+
3
+ /* Forward declarations (implemented in print.cpp) */
4
+
5
+ Napi::Value getPrinters(const Napi::CallbackInfo &info);
6
+ Napi::Value getPrinter(const Napi::CallbackInfo &info);
7
+ Napi::Value getPrinterDriverOptions(const Napi::CallbackInfo &info);
8
+ Napi::Value getSelectedPaperSize(const Napi::CallbackInfo &info);
9
+ Napi::Value getDefaultPrinterName(const Napi::CallbackInfo &info);
10
+
11
+ Napi::Value printDirect(const Napi::CallbackInfo &info);
12
+ Napi::Value printFile(const Napi::CallbackInfo &info);
13
+
14
+ Napi::Value getSupportedPrintFormats(const Napi::CallbackInfo &info);
15
+
16
+ Napi::Value getJob(const Napi::CallbackInfo &info);
17
+ Napi::Value setJob(const Napi::CallbackInfo &info);
18
+ Napi::Value getSupportedJobCommands(const Napi::CallbackInfo &info);
19
+
20
+ /* Module initialization */
21
+
22
+ Napi::Object Init(Napi::Env env, Napi::Object exports)
23
+ {
24
+ // Printer listing
25
+ exports.Set("getPrinters", Napi::Function::New(env, getPrinters));
26
+ exports.Set("getPrinter", Napi::Function::New(env, getPrinter));
27
+ exports.Set("getPrinterDriverOptions", Napi::Function::New(env, getPrinterDriverOptions));
28
+ exports.Set("getSelectedPaperSize", Napi::Function::New(env, getSelectedPaperSize));
29
+ exports.Set("getDefaultPrinterName", Napi::Function::New(env, getDefaultPrinterName));
30
+
31
+ // Printing
32
+ exports.Set("printDirect", Napi::Function::New(env, printDirect));
33
+ exports.Set("printFile", Napi::Function::New(env, printFile));
34
+
35
+ // Capabilities
36
+ exports.Set("getSupportedPrintFormats", Napi::Function::New(env, getSupportedPrintFormats));
37
+ exports.Set("getSupportedJobCommands", Napi::Function::New(env, getSupportedJobCommands));
38
+
39
+ // Job management
40
+ exports.Set("getJob", Napi::Function::New(env, getJob));
41
+ exports.Set("setJob", Napi::Function::New(env, setJob));
42
+
43
+ return exports;
44
+ }
45
+
46
+ /*
47
+ IMPORTANT:
48
+ Module name MUST match bindings('electron_printer')
49
+ and binding.gyp target_name
50
+ */
22
51
  NODE_API_MODULE(electron_printer, Init)