spoolprint 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a2f4545b0e4027268e5bbea35a3035fc2fc2ccdb62ec0965cd6b2b876be28824
4
+ data.tar.gz: 2948b28e7b18a59d0ad34dcaa435c570f340b1122e69aba1e392409501f28da6
5
+ SHA512:
6
+ metadata.gz: e18186ec2decc3ab8403ad882c275dda627c527c5ca3af819ee9bea8186101ad9ca67aa57f2f4e1b9c19d704700fb68a138faba0fbfc0767d143cd9cfb194517
7
+ data.tar.gz: 93316b19d646dd32b6bbd2a5d36b97377367a989d96a9483f7feefae75c04e577dca158c6c063db3daed7bd7c88a7af9e659ef9e01dc050aaaed71e7877c118d
@@ -0,0 +1,30 @@
1
+ name: Rubygems
2
+
3
+ on:
4
+ release
5
+
6
+ jobs:
7
+ build:
8
+ name: Build + Publish
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: read
12
+ packages: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: Set up Ruby 2.6
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.6.x
20
+
21
+ - name: Publish to RubyGems
22
+ run: |
23
+ mkdir -p $HOME/.gem
24
+ touch $HOME/.gem/credentials
25
+ chmod 0600 $HOME/.gem/credentials
26
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
27
+ gem build *.gemspec
28
+ gem push *.gem
29
+ env:
30
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task default: :test
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+
3
+ have_library("winspool")
4
+ create_makefile("spoolprint")
@@ -0,0 +1,147 @@
1
+ #include <winsock2.h>
2
+ #include <ws2tcpip.h>
3
+ #include <mswsock.h>
4
+ #include <ruby.h>
5
+
6
+ #define PANJANG_NAMA 1024
7
+ // #define PANJANG_JUKIR_AWAL 2;
8
+
9
+ typedef struct {
10
+ SOCKET hantar;
11
+ struct sockaddr_in addr;
12
+ FD_SET jukir;
13
+ SOCKET* akhirSentuh;
14
+ SOCKET* bergulir;
15
+ // size_t panjang_lantai;
16
+ } server_ket, *serv_ket;
17
+
18
+ void server_free(void* keterangan) {
19
+ serv_ket serv = keterangan;
20
+ while(serv->akhirSentuh != serv->jukir.fd_array) {
21
+ closesocket(*serv->akhirSentuh--);
22
+ }
23
+ FD_ZERO(&serv->jukir);
24
+ closesocket(serv->hantar);
25
+ free(serv);
26
+ }
27
+
28
+ size_t server_size(const void* keterangan) {
29
+ return sizeof(server_ket);
30
+ }
31
+
32
+ static const rb_data_type_t server_type = {
33
+ .wrap_struct_name = "server",
34
+ .function = {
35
+ .dmark = NULL,
36
+ .dfree = server_free,
37
+ .dsize = server_size
38
+ },
39
+ .data = NULL,
40
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
41
+ };
42
+
43
+ VALUE server_alloc(VALUE self) {
44
+ char nama[PANJANG_NAMA];
45
+ serv_ket keterangan;
46
+ struct hostent* host;
47
+ struct in_addr* ipAddr;
48
+
49
+ gethostname(nama, PANJANG_NAMA);
50
+ host = gethostbyname(nama);
51
+ ipAddr = host->h_addr;
52
+
53
+ keterangan = malloc(sizeof(server_ket));
54
+ memset(keterangan, 0, sizeof(server_ket));
55
+ keterangan->hantar = socket(AF_INET, SOCK_STREAM, 0);
56
+ keterangan->addr.sin_family = AF_INET;
57
+ keterangan->addr.sin_addr.s_addr = ipAddr->s_addr;
58
+ //keterangan->jukir = malloc(sizeof(FD_SET * PANJANG_JUKIR_AWAL);
59
+ keterangan->akhirSentuh = keterangan->jukir.fd_array;
60
+ keterangan->bergulir = keterangan->akhirSentuh;
61
+ // keterangan->panjang_pelanggan = PANJANG_JUKIR_AWAL;
62
+ return TypedData_Wrap_Struct(self, &server_type, keterangan);
63
+ }
64
+
65
+ #define MUAT_DATA(var) TypedData_Get_Struct(self, server_ket, \
66
+ &server_type, var)
67
+
68
+ VALUE server_init(VALUE self, VALUE port) {
69
+ serv_ket ket;
70
+ u_long mode = 1;
71
+
72
+ MUAT_DATA(ket);
73
+ ket->addr.sin_port = htons(FIX2INT(port));
74
+ bind(ket->hantar, (struct sockaddr*)&ket->addr, sizeof(struct sockaddr_in));
75
+ listen(ket->hantar, 20);
76
+ ioctlsocket(ket->hantar, FIONBIO, &mode);
77
+ return Qnil;
78
+ }
79
+
80
+ VALUE server_recvpoll(VALUE self) {
81
+ VALUE resp;
82
+ serv_ket ket;
83
+ struct sockaddr_in pelanggan;
84
+ struct timeval tm;
85
+ SOCKET pelangganFd;
86
+ byte flag;
87
+ int sisa, panjang;
88
+ FD_SET siap_dibaca;
89
+
90
+ MUAT_DATA(ket);
91
+ rb_need_block();
92
+
93
+ memcpy(&siap_dibaca, &ket->jukir, sizeof(FD_SET));
94
+ timerclear(&tm);
95
+ sisa = select(siap_dibaca.fd_count, &siap_dibaca, NULL, NULL, &tm);
96
+ for (size_t i = 0; i < sisa; i++) {
97
+ ket->bergulir = siap_dibaca.fd_array + i;
98
+ pelangganFd = *ket->bergulir;
99
+ read(pelangganFd, &flag, 1);
100
+ if (flag != 0x9f) {
101
+ sisa = 0;
102
+ resp = rb_yield(rb_str_new_frozen(rb_str_new2((char*)&flag)));
103
+ write(pelangganFd, RSTRING_PTR(resp), RSTRING_LEN(resp));
104
+ } else {
105
+ closesocket(pelangganFd);
106
+ *ket->bergulir = *ket->akhirSentuh;
107
+ ket->akhirSentuh--;
108
+ ket->jukir.fd_count--;
109
+ }
110
+ }
111
+
112
+ memset(&pelanggan, 0, sizeof(pelanggan));
113
+ panjang = sizeof(pelanggan);
114
+ pelangganFd = accept(ket->hantar, (struct sockaddr*)&pelanggan, &panjang);
115
+ if (pelangganFd != -1) {
116
+ ket->akhirSentuh++;
117
+ *ket->akhirSentuh = pelangganFd;
118
+ ket->jukir.fd_count++;
119
+ }
120
+ }
121
+
122
+ VALUE server_readdriver(VALUE self, VALUE panjang) {
123
+ serv_ket ket;
124
+ MUAT_DATA(ket);
125
+ char* pandang;
126
+ int panj, panjDap;
127
+ VALUE dapat;
128
+
129
+ panj = FIX2INT(panjang);
130
+ pandang = malloc(panj);
131
+ panjDap = read(ket->bergulir, pandang, panj);
132
+ dapat = rb_str_new(pandang, panjDap);
133
+ free(pandang);
134
+ return dapat;
135
+ }
136
+
137
+ void Init_server(VALUE wrap) {
138
+ VALUE cServer = rb_define_class_under(wrap, "Server", rb_cObject);
139
+ rb_define_alloc_func(cServer, server_alloc);
140
+ rb_define_method(cServer, "initialize", server_init, 1);
141
+ rb_define_method(cServer, "receiver_poll", server_recvpoll, 0);
142
+ rb_define_method(cServer, "read_driver", server_readdriver, 0);
143
+ // atexit(Finalize_server);
144
+ }
145
+
146
+ void Finalize_server() {
147
+ }
@@ -0,0 +1,30 @@
1
+ #include <windows.h>
2
+ #include <winspool.h>
3
+ #include <stdio.h>
4
+
5
+ int spoolprint_dalam(char* namaJob, byte* resi, size_t panjang)
6
+ {
7
+ CHAR namaPrinter[1024];
8
+ DWORD ukuran;
9
+
10
+ *namaPrinter = 0;
11
+ ukuran = 1024;
12
+ GetDefaultPrinter((LPSTR)namaPrinter, (LPDWORD)&ukuran);
13
+
14
+ DOC_INFO_1 docInfo;
15
+ HANDLE kendali;
16
+ DWORD tertulis;
17
+
18
+ ZeroMemory(&docInfo, sizeof(docInfo));
19
+ docInfo.pDocName = namaJob;
20
+ docInfo.pDatatype = "RAW";
21
+
22
+ OpenPrinter(namaPrinter, &kendali, NULL);
23
+ StartDocPrinter(kendali, 1, (LPBYTE)&docInfo);
24
+ StartPagePrinter(kendali);
25
+ WritePrinter(kendali, resi, panjang, &tertulis);
26
+ EndPagePrinter(kendali);
27
+ EndDocPrinter(kendali);
28
+ ClosePrinter(kendali);
29
+ return tertulis;
30
+ }
@@ -0,0 +1,117 @@
1
+ #include <ruby.h>
2
+ #include <stdlib.h>
3
+
4
+ #define ASAL_NAMA_DOC "Resi Toko"
5
+ #define PANJANG_TEKS 4096
6
+ #define NAMA_JOB_MAX 255
7
+
8
+ extern int spoolprint_dalam(char*, void*, size_t);
9
+
10
+ typedef struct {
11
+ char teks[PANJANG_TEKS];
12
+ byte panjangNamaJob;
13
+ char* tumpuan;
14
+ void* sambungan;
15
+ } spoolprint_keterangan, *sp_ket;
16
+
17
+ void spoolprint_free(void* keterangan) {
18
+ sp_ket sambungan;
19
+ while (keterangan != NULL) {
20
+ sambungan = ((sp_ket)keterangan)->sambungan;
21
+ free(keterangan);
22
+ keterangan = sambungan;
23
+ }
24
+ }
25
+
26
+ size_t spoolprint_size(const void* keterangan) {
27
+ return sizeof(spoolprint_keterangan);
28
+ }
29
+
30
+ static const rb_data_type_t spoolprint_type = {
31
+ .wrap_struct_name = "spoolprint",
32
+ .function = {
33
+ .dmark = NULL,
34
+ .dfree = spoolprint_free,
35
+ .dsize = spoolprint_size
36
+ },
37
+ .data = NULL,
38
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
39
+ };
40
+
41
+ #define MUAT_DATA(var) TypedData_Get_Struct(self, spoolprint_keterangan, \
42
+ &spoolprint_type, var)
43
+
44
+ VALUE spoolprint_alloc(VALUE self) {
45
+ sp_ket keterangan = malloc(sizeof(spoolprint_keterangan));
46
+ memset(keterangan, 0, sizeof(spoolprint_keterangan));
47
+ keterangan->tumpuan = keterangan->teks;
48
+ return TypedData_Wrap_Struct(self, &spoolprint_type, keterangan);
49
+ }
50
+
51
+ VALUE spoolprintInit(int argc, VALUE* argv, VALUE self) {
52
+ VALUE namaDoc;
53
+ sp_ket ket;
54
+ char* nama = "\0";
55
+ size_t tempuh = 0;
56
+ MUAT_DATA(ket);
57
+
58
+ rb_scan_args(argc, argv, "01", &namaDoc);
59
+ if (argc > 0) {
60
+ Check_Type(namaDoc, RUBY_T_STRING);
61
+ nama = RSTRING_PTR(namaDoc);
62
+ }
63
+
64
+ while(*nama != 0 && ++tempuh < NAMA_JOB_MAX) {
65
+ *ket->tumpuan++ = *nama++;
66
+ }
67
+ ket->panjangNamaJob = ket->tumpuan - ket->teks;
68
+ *ket->tumpuan++ = 0;
69
+ }
70
+
71
+ VALUE spoolprintCetak(VALUE self) {
72
+ char *nDoc = ASAL_NAMA_DOC, *dicetak;
73
+ size_t panjang;
74
+ sp_ket ket;
75
+ MUAT_DATA(ket);
76
+
77
+ if (ket->panjangNamaJob > 0) {
78
+ nDoc = ket->teks;
79
+ dicetak = ket->teks + ket->panjangNamaJob + 2;
80
+ } else {
81
+ dicetak = ket->teks + 1;
82
+ }
83
+
84
+ if (*dicetak != 0x1b || *(dicetak + 1) != 0x40) return Qnil;
85
+ panjang = ket->tumpuan - dicetak;
86
+ return INT2FIX(spoolprint_dalam(nDoc, dicetak, panjang));
87
+ }
88
+
89
+ VALUE spoolprintRaw(VALUE self, VALUE raw) {
90
+ char* jukir;
91
+ size_t panjang;
92
+ sp_ket ket;
93
+
94
+ MUAT_DATA(ket);
95
+ Check_Type(raw, RUBY_T_STRING);
96
+ jukir = RSTRING_PTR(raw);
97
+ panjang = RSTRING_LEN(raw);
98
+
99
+ if (ket->tumpuan - ket->teks + panjang < PANJANG_TEKS) {
100
+ while (panjang--) *ket->tumpuan++ = *jukir++;
101
+ return Qtrue;
102
+ } else {
103
+ return Qfalse;
104
+ }
105
+ }
106
+
107
+ extern void Init_server(VALUE);
108
+
109
+ void Init_spoolprint() {
110
+ VALUE mSpoolprint = rb_define_module("Spoolprint");
111
+ VALUE cSpoolPrint = rb_define_class_under(mSpoolprint, "SpoolPrint", rb_cObject);
112
+ rb_define_alloc_func(cSpoolPrint, spoolprint_alloc);
113
+ rb_define_method(cSpoolPrint, "initialize", spoolprintInit, -1);
114
+ rb_define_method(cSpoolPrint, "taruh_raw", spoolprintRaw, 1);
115
+ rb_define_method(cSpoolPrint, "cetak", spoolprintCetak, 0);
116
+ Init_server(mSpoolprint);
117
+ }
@@ -0,0 +1,53 @@
1
+ module Spoolprint
2
+ class ReceiverManager
3
+ FLAG_SUCCESS = [0x80, 0x00].collect(&:chr).join
4
+
5
+ class RemoteServer
6
+ def initialize(meth)
7
+ @meth = meth
8
+ end
9
+
10
+ def use(length)
11
+ return @meth.call(length)
12
+ end
13
+ end
14
+
15
+ class Request
16
+ attr_accessor :flag, :length, :message
17
+
18
+ def perfect?
19
+ return false if length.nil?
20
+ return false if length.zero?
21
+ return false if message.nil?
22
+ return false if message.empty?
23
+ return true
24
+ end
25
+
26
+ def self.urai(flag)
27
+ instance = self.new
28
+ if flag == 0x93
29
+ instance.flag = flag
30
+ instance.length = yield(1)
31
+ instance.message = yield(instance.length)
32
+ end
33
+ return instance
34
+ end
35
+ end
36
+
37
+ class Response
38
+ attr_accessor :success, :for_print
39
+ end
40
+
41
+ def initialize(remote_meth)
42
+ @remote = RemoteServer.new(remote_meth)
43
+ end
44
+
45
+ def make_response(req_raw)
46
+ req = Request.urai(req_raw) { |length| @remote.use(length) }
47
+ resp = Response.new
48
+ resp.success = FLAG_SUCCESS
49
+ resp.for_print = req.message
50
+ return resp
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,39 @@
1
+ require "spoolprint/server/receiver_manager"
2
+
3
+ module Spoolprint
4
+ class ServerReceipt < Server
5
+ ASAL_SERVER_PORT = 7776
6
+
7
+ def initialize(spool)
8
+ super(ASAL_SERVER_PORT)
9
+ @spool = spool
10
+ @manager = ReceiverManager.new(method(:read_driver))
11
+ @server_zone = Thread.new { server_bergulir }
12
+ @bergulir = false
13
+ end
14
+
15
+ def start
16
+ @bergulir = true
17
+ @server_zone.run if @server_zone.stop?
18
+ end
19
+
20
+ def stop
21
+ @bergulir = false
22
+ end
23
+
24
+ private
25
+ def server_bergulir
26
+ while true
27
+ @bergulir ? server_receive : Thread.stop
28
+ end
29
+ end
30
+
31
+ def server_receive
32
+ receiver_poll do |r|
33
+ resp = @manager.make_response(r)
34
+ @spool << resp.for_print
35
+ next resp.success
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Spoolprint
2
+ VERSION = "1.0.0"
3
+ end
data/lib/spoolprint.rb ADDED
@@ -0,0 +1,37 @@
1
+ require 'spoolprint.so'
2
+ require 'escpos'
3
+ require 'spoolprint/server_receipt'
4
+
5
+ module Spoolprint
6
+ class ReceiptPrintEasy < Escpos::Printer
7
+ attr_reader :interface
8
+
9
+ def initialize(job = nil)
10
+ super()
11
+ @interface = create_interface(job)
12
+ @server = ServerReceipt.new(self)
13
+ end
14
+
15
+ def start_server
16
+ @server.start
17
+ end
18
+
19
+ def stop_server
20
+ @server.stop
21
+ end
22
+
23
+ def to_escpos
24
+ @interface.taruh_raw(super)
25
+ return @interface.cetak
26
+ end
27
+
28
+ private
29
+ def create_interface(job)
30
+ if (job.nil?)
31
+ return SpoolPrint.new
32
+ else
33
+ return SpoolPrint.new(job)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../lib/spoolprint/version', __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "spoolprint"
5
+ s.version = Spoolprint::VERSION
6
+ s.license = "MIT"
7
+ s.authors = ["Reckordp"]
8
+ s.summary = "Library for printing to Esc/Eps printer"
9
+ s.description = "Ruby/Spoolprint provides way to connecting printer on Windows"
10
+ s.email = "paksaambil@gmail.com"
11
+ s.homepage = "https://github.com/Reckordp/spoolprint"
12
+ s.add_dependency(%q(escpos), [">= 0"])
13
+ s.require_paths = ["lib"]
14
+ s.date = "2022-09-08"
15
+ s.files = `git ls-files`.split($\)
16
+ s.extensions = "ext/native/extconf.rb"
17
+ end
@@ -0,0 +1,5 @@
1
+ require 'spoolprint'
2
+
3
+ receipt = Spoolprint::ReceiptPrintEasy.new
4
+ receipt << "Z" + Escpos.sequence(Escpos::CTL_LF)
5
+ receipt.to_escpos
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spoolprint
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Reckordp
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: escpos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: Ruby/Spoolprint provides way to connecting printer on Windows
28
+ email: paksaambil@gmail.com
29
+ executables: []
30
+ extensions:
31
+ - ext/native/extconf.rb
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/.rubygems.yml"
35
+ - Rakefile
36
+ - ext/native/extconf.rb
37
+ - ext/native/server.c
38
+ - ext/native/spool_print_dalam.c
39
+ - ext/native/spoolprint.c
40
+ - lib/spoolprint.rb
41
+ - lib/spoolprint/server/receiver_manager.rb
42
+ - lib/spoolprint/server_receipt.rb
43
+ - lib/spoolprint/version.rb
44
+ - spoolprint.gemspec
45
+ - test/test_print.rb
46
+ homepage: https://github.com/Reckordp/spoolprint
47
+ licenses:
48
+ - MIT
49
+ metadata: {}
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubygems_version: 3.0.3.1
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Library for printing to Esc/Eps printer
69
+ test_files: []