@esslassi/electron-printer 0.0.3 → 0.0.6
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 +222 -53
- package/binding.gyp +51 -33
- package/lib/electronPrinter.d.ts +33 -0
- package/lib/electronPrinter.js +38 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +17 -1
- package/package.json +47 -33
- package/src/linux_printer.cpp +171 -0
- package/src/linux_printer.h +21 -0
- package/src/mac_printer.cpp +166 -0
- package/src/mac_printer.h +22 -0
- package/src/main.cpp +22 -0
- package/src/print.cpp +272 -0
- package/src/printer_factory.cpp +20 -0
- package/src/printer_factory.h +13 -0
- package/src/printer_interface.h +29 -0
- package/src/windows_printer.cpp +210 -0
- package/src/windows_printer.h +35 -0
- package/.gitattributes +0 -2
- package/Gruntfile.js +0 -80
- package/LICENSE +0 -21
- package/binding.js +0 -244
- package/index.js +0 -1
- package/lib/binding.js +0 -244
- package/printer.js +0 -1
- package/src/hello_world.cc +0 -8
- package/src/macros.hh +0 -53
- package/src/node_printer.cc +0 -31
- package/src/node_printer.hpp +0 -77
- package/src/node_printer_win.cc +0 -586
- package/test/getDefaultPrinterName.test.js +0 -18
- package/test/getPrinters.test.js +0 -26
- package/test/incompleteFunctions.js +0 -56
- package/test/printDirect.test.js +0 -34
- package/test/sayMyName.test.js +0 -21
- package/tools/buildElectronLinux.sh +0 -10
- package/tools/buildElectronWindows.ps1 +0 -20
- package/tools/buildWindows.ps1 +0 -23
- package/tools/generateReleaseBuildsLinux.sh +0 -59
- package/tools/generateReleaseBuildsWindows.ps1 +0 -63
- package/tools/getSourceFiles.py +0 -12
- package/tools/remove_directory.py +0 -27
- package/tsconfig.json +0 -22
- package/types/index.d.ts +0 -56
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#include "linux_printer.h"
|
|
2
|
+
#include <cups/cups.h>
|
|
3
|
+
#include <cups/ppd.h>
|
|
4
|
+
|
|
5
|
+
std::string LinuxPrinter::GetPrinterStatus(ipp_pstate_t state)
|
|
6
|
+
{
|
|
7
|
+
switch (state)
|
|
8
|
+
{
|
|
9
|
+
case IPP_PRINTER_IDLE:
|
|
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
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
PrinterInfo LinuxPrinter::GetPrinterDetails(const std::string &printerName, bool isDefault)
|
|
21
|
+
{
|
|
22
|
+
PrinterInfo info;
|
|
23
|
+
info.name = printerName;
|
|
24
|
+
info.isDefault = isDefault;
|
|
25
|
+
|
|
26
|
+
cups_dest_t *dests;
|
|
27
|
+
int num_dests = cupsGetDests(&dests);
|
|
28
|
+
cups_dest_t *dest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);
|
|
29
|
+
|
|
30
|
+
if (dest != NULL)
|
|
31
|
+
{
|
|
32
|
+
for (int i = 0; i < dest->num_options; i++)
|
|
33
|
+
{
|
|
34
|
+
info.details[dest->options[i].name] = dest->options[i].value;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
http_t *http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
|
|
38
|
+
HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL);
|
|
39
|
+
if (http != NULL)
|
|
40
|
+
{
|
|
41
|
+
ipp_t *request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
|
|
42
|
+
|
|
43
|
+
char uri[HTTP_MAX_URI];
|
|
44
|
+
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
|
|
45
|
+
"localhost", 0, "/printers/%s", printerName.c_str());
|
|
46
|
+
|
|
47
|
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
|
|
48
|
+
"printer-uri", NULL, uri);
|
|
49
|
+
|
|
50
|
+
ipp_t *response = cupsDoRequest(http, request, "/");
|
|
51
|
+
if (response != NULL)
|
|
52
|
+
{
|
|
53
|
+
ipp_attribute_t *attr = ippFindAttribute(response,
|
|
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;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
std::vector<PrinterInfo> LinuxPrinter::GetPrinters()
|
|
86
|
+
{
|
|
87
|
+
std::vector<PrinterInfo> printers;
|
|
88
|
+
cups_dest_t *dests;
|
|
89
|
+
int num_dests = cupsGetDests(&dests);
|
|
90
|
+
|
|
91
|
+
for (int i = 0; i < num_dests; i++)
|
|
92
|
+
{
|
|
93
|
+
printers.push_back(GetPrinterDetails(dests[i].name, dests[i].is_default));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
cupsFreeDests(num_dests, dests);
|
|
97
|
+
return printers;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
PrinterInfo LinuxPrinter::GetSystemDefaultPrinter()
|
|
101
|
+
{
|
|
102
|
+
cups_dest_t *dests;
|
|
103
|
+
int num_dests = cupsGetDests(&dests);
|
|
104
|
+
cups_dest_t *dest = cupsGetDest(NULL, NULL, num_dests, dests);
|
|
105
|
+
|
|
106
|
+
PrinterInfo printer;
|
|
107
|
+
if (dest != NULL)
|
|
108
|
+
{
|
|
109
|
+
printer = GetPrinterDetails(dest->name, true);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
cupsFreeDests(num_dests, dests);
|
|
113
|
+
return printer;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
bool LinuxPrinter::PrintDirect(const std::string &printerName,
|
|
117
|
+
const std::vector<uint8_t> &data,
|
|
118
|
+
const std::string &dataType)
|
|
119
|
+
{
|
|
120
|
+
int jobId = cupsCreateJob(CUPS_HTTP_DEFAULT, printerName.c_str(),
|
|
121
|
+
"Node.js Print Job", 0, NULL);
|
|
122
|
+
|
|
123
|
+
if (jobId <= 0)
|
|
124
|
+
return false;
|
|
125
|
+
|
|
126
|
+
http_status_t status = cupsStartDocument(CUPS_HTTP_DEFAULT, printerName.c_str(),
|
|
127
|
+
jobId, "Node.js Print Job",
|
|
128
|
+
dataType.c_str(), 1);
|
|
129
|
+
|
|
130
|
+
if (status != HTTP_STATUS_CONTINUE)
|
|
131
|
+
{
|
|
132
|
+
cupsCancelJob(printerName.c_str(), jobId);
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (cupsWriteRequestData(CUPS_HTTP_DEFAULT,
|
|
137
|
+
reinterpret_cast<const char *>(data.data()),
|
|
138
|
+
data.size()) != HTTP_STATUS_CONTINUE)
|
|
139
|
+
{
|
|
140
|
+
cupsCancelJob(printerName.c_str(), jobId);
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
status = static_cast<http_status_t>(cupsFinishDocument(CUPS_HTTP_DEFAULT, printerName.c_str()));
|
|
145
|
+
return status == HTTP_STATUS_OK;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
PrinterInfo LinuxPrinter::GetStatusPrinter(const std::string &printerName)
|
|
149
|
+
{
|
|
150
|
+
cups_dest_t *dests;
|
|
151
|
+
int num_dests = cupsGetDests(&dests);
|
|
152
|
+
|
|
153
|
+
cups_dest_t *defaultDest = cupsGetDest(NULL, NULL, num_dests, dests);
|
|
154
|
+
bool isDefault = false;
|
|
155
|
+
|
|
156
|
+
if (defaultDest != NULL)
|
|
157
|
+
{
|
|
158
|
+
isDefault = (printerName == defaultDest->name);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
cups_dest_t *dest = cupsGetDest(printerName.c_str(), NULL, num_dests, dests);
|
|
162
|
+
PrinterInfo printer;
|
|
163
|
+
|
|
164
|
+
if (dest != NULL)
|
|
165
|
+
{
|
|
166
|
+
printer = GetPrinterDetails(printerName, isDefault);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
cupsFreeDests(num_dests, dests);
|
|
170
|
+
return printer;
|
|
171
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#ifndef LINUX_PRINTER_H
|
|
2
|
+
#define LINUX_PRINTER_H
|
|
3
|
+
#include <cups/cups.h>
|
|
4
|
+
#include <cups/ppd.h>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include "printer_interface.h"
|
|
7
|
+
|
|
8
|
+
class LinuxPrinter : public PrinterInterface
|
|
9
|
+
{
|
|
10
|
+
private:
|
|
11
|
+
std::string GetPrinterStatus(ipp_pstate_t state);
|
|
12
|
+
|
|
13
|
+
public:
|
|
14
|
+
virtual PrinterInfo GetPrinterDetails(const std::string &printerName, bool isDefault = false) override;
|
|
15
|
+
virtual std::vector<PrinterInfo> GetPrinters() override;
|
|
16
|
+
virtual PrinterInfo GetSystemDefaultPrinter() override;
|
|
17
|
+
virtual bool PrintDirect(const std::string &printerName, const std::vector<uint8_t> &data, const std::string &dataType) override;
|
|
18
|
+
virtual PrinterInfo GetStatusPrinter(const std::string &printerName) override;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
#endif
|
|
@@ -0,0 +1,166 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
package/src/main.cpp
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
|
|
22
|
+
NODE_API_MODULE(electron_printer, Init)
|
package/src/print.cpp
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
#include <napi.h>
|
|
2
|
+
#include "printer_factory.h"
|
|
3
|
+
|
|
4
|
+
class PrinterWorker : public Napi::AsyncWorker
|
|
5
|
+
{
|
|
6
|
+
private:
|
|
7
|
+
std::unique_ptr<PrinterInterface> printer;
|
|
8
|
+
std::function<void(PrinterWorker *)> work;
|
|
9
|
+
PrinterInfo printerResult;
|
|
10
|
+
std::vector<PrinterInfo> printersResult;
|
|
11
|
+
bool isMultiplePrinters;
|
|
12
|
+
bool success;
|
|
13
|
+
|
|
14
|
+
public:
|
|
15
|
+
PrinterWorker(Napi::Function &callback, std::function<void(PrinterWorker *)> executeWork)
|
|
16
|
+
: Napi::AsyncWorker(callback),
|
|
17
|
+
work(executeWork),
|
|
18
|
+
isMultiplePrinters(false),
|
|
19
|
+
success(false)
|
|
20
|
+
{
|
|
21
|
+
printer = PrinterFactory::Create();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void Execute() override
|
|
25
|
+
{
|
|
26
|
+
if (printer)
|
|
27
|
+
{
|
|
28
|
+
work(this);
|
|
29
|
+
}
|
|
30
|
+
else
|
|
31
|
+
{
|
|
32
|
+
SetError("Failed to create printer");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void OnOK() override
|
|
37
|
+
{
|
|
38
|
+
Napi::Env env = Env();
|
|
39
|
+
Napi::HandleScope scope(env);
|
|
40
|
+
|
|
41
|
+
if (isMultiplePrinters)
|
|
42
|
+
{
|
|
43
|
+
Napi::Array result = Napi::Array::New(env, printersResult.size());
|
|
44
|
+
for (size_t i = 0; i < printersResult.size(); i++)
|
|
45
|
+
{
|
|
46
|
+
result.Set(i, CreatePrinterObject(env, printersResult[i]));
|
|
47
|
+
}
|
|
48
|
+
Callback().Call({env.Null(), result});
|
|
49
|
+
}
|
|
50
|
+
else
|
|
51
|
+
{
|
|
52
|
+
Callback().Call({env.Null(), CreatePrinterObject(env, printerResult)});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
PrinterInterface *GetPrinter() { return printer.get(); }
|
|
57
|
+
void SetPrinterResult(const PrinterInfo &result) { printerResult = result; }
|
|
58
|
+
void SetPrintersResult(const std::vector<PrinterInfo> &result)
|
|
59
|
+
{
|
|
60
|
+
printersResult = result;
|
|
61
|
+
isMultiplePrinters = true;
|
|
62
|
+
}
|
|
63
|
+
void SetSuccess(bool value) { success = value; }
|
|
64
|
+
bool GetSuccess() const { return success; }
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
Napi::Object CreatePrinterObject(Napi::Env env, const PrinterInfo &printer)
|
|
68
|
+
{
|
|
69
|
+
Napi::Object result = Napi::Object::New(env);
|
|
70
|
+
result.Set("name", printer.name);
|
|
71
|
+
result.Set("status", printer.status);
|
|
72
|
+
|
|
73
|
+
// Só incluir estes campos se NÃO for um resultado do PrintDirect
|
|
74
|
+
if (!success)
|
|
75
|
+
{ // Se success for true, é um PrintDirect
|
|
76
|
+
result.Set("isDefault", printer.isDefault);
|
|
77
|
+
|
|
78
|
+
Napi::Object details = Napi::Object::New(env);
|
|
79
|
+
for (const auto &detail : printer.details)
|
|
80
|
+
{
|
|
81
|
+
details.Set(detail.first, detail.second);
|
|
82
|
+
}
|
|
83
|
+
result.Set("details", details);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
Napi::Value PrintDirect(const Napi::CallbackInfo &info)
|
|
91
|
+
{
|
|
92
|
+
Napi::Env env = info.Env();
|
|
93
|
+
|
|
94
|
+
if (info.Length() < 1 || !info[0].IsObject())
|
|
95
|
+
{
|
|
96
|
+
Napi::TypeError::New(env, "Expected an object as argument").ThrowAsJavaScriptException();
|
|
97
|
+
return env.Null();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
Napi::Object options = info[0].As<Napi::Object>();
|
|
101
|
+
|
|
102
|
+
if (!options.Has("printerName") || !options.Has("data"))
|
|
103
|
+
{
|
|
104
|
+
Napi::TypeError::New(env, "Object must have 'printerName' and 'data' properties").ThrowAsJavaScriptException();
|
|
105
|
+
return env.Null();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!options.Get("printerName").IsString())
|
|
109
|
+
{
|
|
110
|
+
Napi::TypeError::New(env, "printerName must be a string").ThrowAsJavaScriptException();
|
|
111
|
+
return env.Null();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Napi::Value data = options.Get("data");
|
|
115
|
+
if (!data.IsString() && !data.IsBuffer())
|
|
116
|
+
{
|
|
117
|
+
Napi::TypeError::New(env, "data must be a string or Buffer").ThrowAsJavaScriptException();
|
|
118
|
+
return env.Null();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
std::string printerName = options.Get("printerName").As<Napi::String>().Utf8Value();
|
|
122
|
+
std::vector<uint8_t> printData;
|
|
123
|
+
|
|
124
|
+
if (data.IsString())
|
|
125
|
+
{
|
|
126
|
+
std::string strData = data.As<Napi::String>().Utf8Value();
|
|
127
|
+
printData.assign(strData.begin(), strData.end());
|
|
128
|
+
}
|
|
129
|
+
else
|
|
130
|
+
{
|
|
131
|
+
Napi::Buffer<uint8_t> buffer = data.As<Napi::Buffer<uint8_t>>();
|
|
132
|
+
printData.assign(buffer.Data(), buffer.Data() + buffer.Length());
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
std::string dataType = "RAW";
|
|
136
|
+
if (options.Has("dataType") && options.Get("dataType").IsString())
|
|
137
|
+
{
|
|
138
|
+
dataType = options.Get("dataType").As<Napi::String>().Utf8Value();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
|
|
142
|
+
|
|
143
|
+
auto callback = Napi::Function::New(env, [deferred](const Napi::CallbackInfo &info)
|
|
144
|
+
{
|
|
145
|
+
if (info[0].IsNull()) {
|
|
146
|
+
deferred.Resolve(info[1]);
|
|
147
|
+
} else {
|
|
148
|
+
deferred.Reject(info[0].As<Napi::Error>().Value());
|
|
149
|
+
}
|
|
150
|
+
return info.Env().Undefined(); });
|
|
151
|
+
|
|
152
|
+
auto worker = new PrinterWorker(
|
|
153
|
+
callback,
|
|
154
|
+
[printerName, printData, dataType](PrinterWorker *worker)
|
|
155
|
+
{
|
|
156
|
+
bool success = worker->GetPrinter()->PrintDirect(printerName, printData, dataType);
|
|
157
|
+
worker->SetSuccess(true); // Indica que é um resultado do PrintDirect
|
|
158
|
+
PrinterInfo result;
|
|
159
|
+
result.name = printerName;
|
|
160
|
+
result.status = success ? "success" : "failed";
|
|
161
|
+
worker->SetPrinterResult(result);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
worker->Queue();
|
|
165
|
+
return deferred.Promise();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
Napi::Value GetPrinters(const Napi::CallbackInfo &info)
|
|
169
|
+
{
|
|
170
|
+
Napi::Env env = info.Env();
|
|
171
|
+
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
|
|
172
|
+
|
|
173
|
+
auto callback = Napi::Function::New(env, [deferred](const Napi::CallbackInfo &info)
|
|
174
|
+
{
|
|
175
|
+
if (info[0].IsNull()) {
|
|
176
|
+
deferred.Resolve(info[1]);
|
|
177
|
+
} else {
|
|
178
|
+
deferred.Reject(info[0].As<Napi::Error>().Value());
|
|
179
|
+
}
|
|
180
|
+
return info.Env().Undefined(); });
|
|
181
|
+
|
|
182
|
+
auto worker = new PrinterWorker(
|
|
183
|
+
callback,
|
|
184
|
+
[](PrinterWorker *worker)
|
|
185
|
+
{
|
|
186
|
+
auto printers = worker->GetPrinter()->GetPrinters();
|
|
187
|
+
worker->SetPrintersResult(printers);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
worker->Queue();
|
|
191
|
+
return deferred.Promise();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
Napi::Value GetSystemDefaultPrinter(const Napi::CallbackInfo &info)
|
|
195
|
+
{
|
|
196
|
+
Napi::Env env = info.Env();
|
|
197
|
+
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
|
|
198
|
+
|
|
199
|
+
auto callback = Napi::Function::New(env, [deferred](const Napi::CallbackInfo &info)
|
|
200
|
+
{
|
|
201
|
+
if (info[0].IsNull()) {
|
|
202
|
+
deferred.Resolve(info[1]);
|
|
203
|
+
} else {
|
|
204
|
+
deferred.Reject(info[0].As<Napi::Error>().Value());
|
|
205
|
+
}
|
|
206
|
+
return info.Env().Undefined(); });
|
|
207
|
+
|
|
208
|
+
auto worker = new PrinterWorker(
|
|
209
|
+
callback,
|
|
210
|
+
[](PrinterWorker *worker)
|
|
211
|
+
{
|
|
212
|
+
auto printer = worker->GetPrinter()->GetSystemDefaultPrinter();
|
|
213
|
+
worker->SetPrinterResult(printer);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
worker->Queue();
|
|
217
|
+
return deferred.Promise();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
Napi::Value GetStatusPrinter(const Napi::CallbackInfo &info)
|
|
221
|
+
{
|
|
222
|
+
Napi::Env env = info.Env();
|
|
223
|
+
|
|
224
|
+
if (info.Length() < 1 || !info[0].IsObject())
|
|
225
|
+
{
|
|
226
|
+
Napi::TypeError::New(env, "Expected an object as argument").ThrowAsJavaScriptException();
|
|
227
|
+
return env.Null();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
Napi::Object options = info[0].As<Napi::Object>();
|
|
231
|
+
|
|
232
|
+
Napi::Array propertyNames = options.GetPropertyNames();
|
|
233
|
+
for (uint32_t i = 0; i < propertyNames.Length(); i++)
|
|
234
|
+
{
|
|
235
|
+
propertyNames.Get(i).As<Napi::String>();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!options.Has("printerName"))
|
|
239
|
+
{
|
|
240
|
+
Napi::TypeError::New(env, "Object must have 'printerName' property").ThrowAsJavaScriptException();
|
|
241
|
+
return env.Null();
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (!options.Get("printerName").IsString())
|
|
245
|
+
{
|
|
246
|
+
Napi::TypeError::New(env, "printerName must be a string").ThrowAsJavaScriptException();
|
|
247
|
+
return env.Null();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
std::string printerName = options.Get("printerName").As<Napi::String>().Utf8Value();
|
|
251
|
+
Napi::Promise::Deferred deferred = Napi::Promise::Deferred::New(env);
|
|
252
|
+
|
|
253
|
+
auto callback = Napi::Function::New(env, [deferred](const Napi::CallbackInfo &info)
|
|
254
|
+
{
|
|
255
|
+
if (info[0].IsNull()) {
|
|
256
|
+
deferred.Resolve(info[1]);
|
|
257
|
+
} else {
|
|
258
|
+
deferred.Reject(info[0].As<Napi::Error>().Value());
|
|
259
|
+
}
|
|
260
|
+
return info.Env().Undefined(); });
|
|
261
|
+
|
|
262
|
+
auto worker = new PrinterWorker(
|
|
263
|
+
callback,
|
|
264
|
+
[printerName](PrinterWorker *worker)
|
|
265
|
+
{
|
|
266
|
+
auto printer = worker->GetPrinter()->GetStatusPrinter(printerName);
|
|
267
|
+
worker->SetPrinterResult(printer);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
worker->Queue();
|
|
271
|
+
return deferred.Promise();
|
|
272
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include "printer_factory.h"
|
|
2
|
+
|
|
3
|
+
#ifdef _WIN32
|
|
4
|
+
#include "windows_printer.h"
|
|
5
|
+
#elif defined(__APPLE__)
|
|
6
|
+
#include "mac_printer.h"
|
|
7
|
+
#else
|
|
8
|
+
#include "linux_printer.h"
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
std::unique_ptr<PrinterInterface> PrinterFactory::Create()
|
|
12
|
+
{
|
|
13
|
+
#ifdef _WIN32
|
|
14
|
+
return std::make_unique<WindowsPrinter>();
|
|
15
|
+
#elif defined(__APPLE__)
|
|
16
|
+
return std::make_unique<MacPrinter>();
|
|
17
|
+
#else
|
|
18
|
+
return std::make_unique<LinuxPrinter>();
|
|
19
|
+
#endif
|
|
20
|
+
}
|