ruby binding 追加
- FFI gem (libptouch)、exe ptouch-print-png(PNG のみ) - ステータス 32 バイトを Hash に展開(parse_status / status_hash) - CMake: libptouch 共有ライブラリ(ptouch_shared) - RuboCop、gemspec(homepage / source_code_uri) Made-with: Cursor
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,8 @@
|
|||||||
build/
|
build/
|
||||||
|
|
||||||
|
ruby/*.gem
|
||||||
|
ruby/.rubocop_cache/
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
*.a
|
*.a
|
||||||
ptouch-print
|
ptouch-print
|
||||||
|
|||||||
@@ -22,14 +22,24 @@ configure_file(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(ptouch STATIC src/libptouch.c)
|
add_library(ptouch STATIC src/libptouch.c)
|
||||||
|
add_library(ptouch_shared SHARED src/libptouch.c)
|
||||||
|
set_target_properties(ptouch_shared PROPERTIES OUTPUT_NAME ptouch
|
||||||
|
SOVERSION ${PROJECT_VERSION_MAJOR})
|
||||||
target_include_directories(ptouch PUBLIC
|
target_include_directories(ptouch PUBLIC
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||||
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||||
)
|
)
|
||||||
|
target_include_directories(ptouch_shared PUBLIC
|
||||||
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
|
||||||
|
"$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>"
|
||||||
|
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
|
||||||
|
)
|
||||||
target_link_libraries(ptouch PRIVATE PkgConfig::LIBUSB PNG::PNG)
|
target_link_libraries(ptouch PRIVATE PkgConfig::LIBUSB PNG::PNG)
|
||||||
|
target_link_libraries(ptouch_shared PRIVATE PkgConfig::LIBUSB PNG::PNG)
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
target_compile_options(ptouch PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(ptouch PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
|
target_compile_options(ptouch_shared PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(ptouch-print src/cli/main.c)
|
add_executable(ptouch-print src/cli/main.c)
|
||||||
@@ -40,6 +50,8 @@ if(NOT MSVC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
install(TARGETS ptouch ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
install(TARGETS ptouch ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
install(TARGETS ptouch_shared LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
install(TARGETS ptouch-print RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
install(TARGETS ptouch-print RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
install(FILES
|
install(FILES
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/include/libptouch.h"
|
"${CMAKE_CURRENT_SOURCE_DIR}/include/libptouch.h"
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ Brother P-touch シリーズ向けのラベル印刷用 **C コアライブラ
|
|||||||
| `src/libptouch.c` | ライブラリ本体(スタブ) |
|
| `src/libptouch.c` | ライブラリ本体(スタブ) |
|
||||||
| `src/cli/main.c` | `ptouch-print` エントリ |
|
| `src/cli/main.c` | `ptouch-print` エントリ |
|
||||||
| `samples/` | 試験用サンプル画像の置き場(PNG 等) |
|
| `samples/` | 試験用サンプル画像の置き場(PNG 等) |
|
||||||
|
| `ruby/` | Ruby FFI gem(`libptouch`)・コマンド `ptouch-print-png`(PNG のみ)— `ruby/README.md` |
|
||||||
| `reference/` | 仕様・参考資料(例: ラスター PDF) |
|
| `reference/` | 仕様・参考資料(例: ラスター PDF) |
|
||||||
|
|
||||||
## ビルド
|
## ビルド
|
||||||
@@ -28,8 +29,13 @@ cmake --build build
|
|||||||
成果物(`build/` 以下):
|
成果物(`build/` 以下):
|
||||||
|
|
||||||
- `libptouch.a` — 静的ライブラリ
|
- `libptouch.a` — 静的ライブラリ
|
||||||
|
- `libptouch.so` — 共有ライブラリ(Ruby FFI 用)
|
||||||
- `ptouch-print` — CLI
|
- `ptouch-print` — CLI
|
||||||
|
|
||||||
|
### Ruby gem
|
||||||
|
|
||||||
|
共有ライブラリをビルドしたうえで、`ruby/` で `bundle install` → `gem build libptouch.gemspec` など(手順は `ruby/README.md`)。
|
||||||
|
|
||||||
## CLI の使い方(雛形)
|
## CLI の使い方(雛形)
|
||||||
|
|
||||||
**PNG**(拡張子 `.png` または PNG シグネチャ)の場合は幅・高さは画像から取得します。任意で `-t`(0–255)で二値化しきい値を指定できます。
|
**PNG**(拡張子 `.png` または PNG シグネチャ)の場合は幅・高さは画像から取得します。任意で `-t`(0–255)で二値化しきい値を指定できます。
|
||||||
|
|||||||
66
ruby/.rubocop.yml
Normal file
66
ruby/.rubocop.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# RuboCop — libptouch gem
|
||||||
|
# https://docs.rubocop.org/
|
||||||
|
|
||||||
|
AllCops:
|
||||||
|
TargetRubyVersion: 3.0
|
||||||
|
NewCops: enable
|
||||||
|
SuggestExtensions: false
|
||||||
|
Exclude:
|
||||||
|
- "vendor/**/*"
|
||||||
|
- ".bundle/**/*"
|
||||||
|
|
||||||
|
Layout/LineLength:
|
||||||
|
Max: 120
|
||||||
|
|
||||||
|
Layout/MultilineMethodCallIndentation:
|
||||||
|
EnforcedStyle: indented_relative_to_receiver
|
||||||
|
|
||||||
|
Lint/RedundantCopDisableDirective:
|
||||||
|
Severity: convention
|
||||||
|
|
||||||
|
# ステータスデコードはデータテーブル中心で行数・複雑度が大きくなりがち
|
||||||
|
Metrics/AbcSize:
|
||||||
|
Max: 60
|
||||||
|
|
||||||
|
Metrics/BlockLength:
|
||||||
|
Max: 35
|
||||||
|
Exclude:
|
||||||
|
- "**/*.gemspec"
|
||||||
|
|
||||||
|
Metrics/MethodLength:
|
||||||
|
Max: 40
|
||||||
|
|
||||||
|
Metrics/ModuleLength:
|
||||||
|
Max: 220
|
||||||
|
|
||||||
|
Metrics/ParameterLists:
|
||||||
|
Max: 6
|
||||||
|
|
||||||
|
Naming/MethodParameterName:
|
||||||
|
AllowedNames:
|
||||||
|
- "b"
|
||||||
|
- "w"
|
||||||
|
|
||||||
|
Style/Documentation:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/DoubleNegation:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
# optional な環境変数の参照に fetch は不向きなことが多い
|
||||||
|
Style/FetchEnvVar:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/FrozenStringLiteralComment:
|
||||||
|
EnforcedStyle: always
|
||||||
|
|
||||||
|
# FFI の %i[] / %w[] はそのままの方が読みやすい
|
||||||
|
Style/SymbolArray:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/WordArray:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
Style/StringLiterals:
|
||||||
|
EnforcedStyle: double_quotes
|
||||||
|
ConsistentQuotesInMultiline: true
|
||||||
9
ruby/Gemfile
Normal file
9
ruby/Gemfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gemspec
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
gem "rubocop", "~> 1.69", require: false
|
||||||
|
end
|
||||||
99
ruby/Gemfile.lock
Normal file
99
ruby/Gemfile.lock
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
PATH
|
||||||
|
remote: .
|
||||||
|
specs:
|
||||||
|
libptouch (1.0.0)
|
||||||
|
ffi (~> 1.15)
|
||||||
|
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
ast (2.4.3)
|
||||||
|
ffi (1.17.4)
|
||||||
|
ffi (1.17.4-aarch64-linux-gnu)
|
||||||
|
ffi (1.17.4-aarch64-linux-musl)
|
||||||
|
ffi (1.17.4-arm-linux-gnu)
|
||||||
|
ffi (1.17.4-arm-linux-musl)
|
||||||
|
ffi (1.17.4-arm64-darwin)
|
||||||
|
ffi (1.17.4-x86-linux-gnu)
|
||||||
|
ffi (1.17.4-x86-linux-musl)
|
||||||
|
ffi (1.17.4-x86_64-darwin)
|
||||||
|
ffi (1.17.4-x86_64-linux-gnu)
|
||||||
|
ffi (1.17.4-x86_64-linux-musl)
|
||||||
|
json (2.19.3)
|
||||||
|
language_server-protocol (3.17.0.5)
|
||||||
|
lint_roller (1.1.0)
|
||||||
|
parallel (2.0.1)
|
||||||
|
parser (3.3.11.1)
|
||||||
|
ast (~> 2.4.1)
|
||||||
|
racc
|
||||||
|
prism (1.9.0)
|
||||||
|
racc (1.8.1)
|
||||||
|
rainbow (3.1.1)
|
||||||
|
regexp_parser (2.12.0)
|
||||||
|
rubocop (1.86.1)
|
||||||
|
json (~> 2.3)
|
||||||
|
language_server-protocol (~> 3.17.0.2)
|
||||||
|
lint_roller (~> 1.1.0)
|
||||||
|
parallel (>= 1.10)
|
||||||
|
parser (>= 3.3.0.2)
|
||||||
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
regexp_parser (>= 2.9.3, < 3.0)
|
||||||
|
rubocop-ast (>= 1.49.0, < 2.0)
|
||||||
|
ruby-progressbar (~> 1.7)
|
||||||
|
unicode-display_width (>= 2.4.0, < 4.0)
|
||||||
|
rubocop-ast (1.49.1)
|
||||||
|
parser (>= 3.3.7.2)
|
||||||
|
prism (~> 1.7)
|
||||||
|
ruby-progressbar (1.13.0)
|
||||||
|
unicode-display_width (3.2.0)
|
||||||
|
unicode-emoji (~> 4.1)
|
||||||
|
unicode-emoji (4.2.0)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
aarch64-linux-gnu
|
||||||
|
aarch64-linux-musl
|
||||||
|
arm-linux-gnu
|
||||||
|
arm-linux-musl
|
||||||
|
arm64-darwin
|
||||||
|
ruby
|
||||||
|
x86-linux-gnu
|
||||||
|
x86-linux-musl
|
||||||
|
x86_64-darwin
|
||||||
|
x86_64-linux-gnu
|
||||||
|
x86_64-linux-musl
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
libptouch!
|
||||||
|
rubocop (~> 1.69)
|
||||||
|
|
||||||
|
CHECKSUMS
|
||||||
|
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
|
||||||
|
ffi (1.17.4) sha256=bcd1642e06f0d16fc9e09ac6d49c3a7298b9789bcb58127302f934e437d60acf
|
||||||
|
ffi (1.17.4-aarch64-linux-gnu) sha256=b208f06f91ffd8f5e1193da3cae3d2ccfc27fc36fba577baf698d26d91c080df
|
||||||
|
ffi (1.17.4-aarch64-linux-musl) sha256=9286b7a615f2676245283aef0a0a3b475ae3aae2bb5448baace630bb77b91f39
|
||||||
|
ffi (1.17.4-arm-linux-gnu) sha256=d6dbddf7cb77bf955411af5f187a65b8cd378cb003c15c05697f5feee1cb1564
|
||||||
|
ffi (1.17.4-arm-linux-musl) sha256=9d4838ded0465bef6e2426935f6bcc93134b6616785a84ffd2a3d82bc3cf6f95
|
||||||
|
ffi (1.17.4-arm64-darwin) sha256=19071aaf1419251b0a46852abf960e77330a3b334d13a4ab51d58b31a937001b
|
||||||
|
ffi (1.17.4-x86-linux-gnu) sha256=38e150df5f4ca555e25beca4090823ae09657bceded154e3c52f8631c1ed72cf
|
||||||
|
ffi (1.17.4-x86-linux-musl) sha256=fbeec0fc7c795bcf86f623bb18d31ea1820f7bd580e1703a3d3740d527437809
|
||||||
|
ffi (1.17.4-x86_64-darwin) sha256=aa70390523cf3235096cf64962b709b4cfbd5c082a2cb2ae714eb0fe2ccda496
|
||||||
|
ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
|
||||||
|
ffi (1.17.4-x86_64-linux-musl) sha256=3fdf9888483de005f8ef8d1cf2d3b20d86626af206cbf780f6a6a12439a9c49e
|
||||||
|
json (2.19.3) sha256=289b0bb53052a1fa8c34ab33cc750b659ba14a5c45f3fcf4b18762dc67c78646
|
||||||
|
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
|
||||||
|
libptouch (1.0.0)
|
||||||
|
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
|
||||||
|
parallel (2.0.1) sha256=337782d3e39f4121e67563bf91dd8ece67f48923d90698614773a0ec9a5b2c7d
|
||||||
|
parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54
|
||||||
|
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
||||||
|
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
||||||
|
rainbow (3.1.1) sha256=039491aa3a89f42efa1d6dec2fc4e62ede96eb6acd95e52f1ad581182b79bc6a
|
||||||
|
regexp_parser (2.12.0) sha256=35a916a1d63190ab5c9009457136ae5f3c0c7512d60291d0d1378ba18ce08ebb
|
||||||
|
rubocop (1.86.1) sha256=44415f3f01d01a21e01132248d2fd0867572475b566ca188a0a42133a08d4531
|
||||||
|
rubocop-ast (1.49.1) sha256=4412f3ee70f6fe4546cc489548e0f6fcf76cafcfa80fa03af67098ffed755035
|
||||||
|
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
||||||
|
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
|
||||||
|
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
4.0.6
|
||||||
78
ruby/README.md
Normal file
78
ruby/README.md
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# libptouch(Ruby gem)
|
||||||
|
|
||||||
|
[ptouch_label](../) の **libptouch** を [ffi](https://github.com/ffi/ffi) 経由で使うための Gem です。
|
||||||
|
|
||||||
|
## 前提
|
||||||
|
|
||||||
|
1. リポジトリルートで共有ライブラリをビルドする(`libptouch.so` が `build/` に生成されます)。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cmake -S .. -B ../build
|
||||||
|
cmake --build ../build
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Ruby 3.0 以上と `ffi` gem。
|
||||||
|
|
||||||
|
## インストール(開発時)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ruby
|
||||||
|
bundle install # または gem install ffi
|
||||||
|
bundle exec rubocop # 任意: スタイルチェック(.rubocop.yml)
|
||||||
|
gem build libptouch.gemspec
|
||||||
|
gem install ./libptouch-1.0.0.gem
|
||||||
|
```
|
||||||
|
|
||||||
|
ビルド済みの `../build/libptouch.so` を自動で読みに行きます。別のパスにある場合は環境変数で指定できます。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export LIBPTOUCH_LIB=/usr/local/lib/libptouch.so
|
||||||
|
```
|
||||||
|
|
||||||
|
(`cmake --install` で共有ライブラリをインストールした場合は、通常は `libptouch` 名でローダが解決します。)
|
||||||
|
|
||||||
|
## コマンド `ptouch-print-png`(PNG のみ)
|
||||||
|
|
||||||
|
C の `ptouch-print` と同様の流れですが、**PNG 入力のみ**(`-w`/`-H` や 1bit ラスターは扱いません)。`gem install` 後は PATH に `ptouch-print-png` が入ります。
|
||||||
|
|
||||||
|
開発ツリーからそのまま試す例:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bundle exec ruby -I lib exe/ptouch-print-png --help
|
||||||
|
bundle exec ruby -I lib exe/ptouch-print-png -n -f ../samples/your.png
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用例
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
require "libptouch"
|
||||||
|
|
||||||
|
Libptouch::Context.new.tap do |ctx|
|
||||||
|
ctx.open_usb
|
||||||
|
p ctx.status_bytes.bytesize # => 32
|
||||||
|
p ctx.status_hash[:tape_kind] # => {:code=>..., :label=>"ラミネートテープ"} など
|
||||||
|
p ctx.status_hash[:status_kind] # => 状態(ステータス種類)
|
||||||
|
ensure
|
||||||
|
ctx.dispose
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
生の 32 バイトだけある場合は `Libptouch.parse_status(raw)` で同じ Hash 形式に展開できます(中身は `libptouch_status_fprint` と同じ区分)。
|
||||||
|
|
||||||
|
PNG からラスターへ:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
ctx = Libptouch::Context.new
|
||||||
|
data, w, h = ctx.png_file_to_raster("/path/to/label.png")
|
||||||
|
ctx.open_usb
|
||||||
|
ctx.print_raster(data, width_dots: w, height_dots: h, margin_mm: 0)
|
||||||
|
ctx.dispose
|
||||||
|
```
|
||||||
|
|
||||||
|
## API の範囲
|
||||||
|
|
||||||
|
- 実行ファイル `ptouch-print-png` … PNG のみ(`-f`, `-t`, `-n`, `-S`, `-V`, `-h`)。ステータスは JSON(`status_bytes` を `parse_status` したもの、`raw_bytes` 除く)
|
||||||
|
- `Libptouch::Context` … `open_usb` / `open_usb_vid_pid` / `close` / `dispose`
|
||||||
|
- `check_raster` / `print_raster` / `png_file_to_raster` / `status_bytes` / `status_hash`
|
||||||
|
- `Libptouch.parse_status(raw)` … 32 バイトを Hash に展開(機種・テープ幅・**テープ種類**・色・**状態(status_kind)**・エラービット・`raw_hex` など)
|
||||||
|
- C の `libptouch_status_fprint`(`FILE *`)は FFI からはバインドしていません。テキスト出力の代わりに `parse_status` / `status_hash` を使ってください。
|
||||||
6
ruby/exe/ptouch-print-png
Executable file
6
ruby/exe/ptouch-print-png
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "libptouch/cli/png_print"
|
||||||
|
|
||||||
|
exit Libptouch::Cli::PngPrint.run(ARGV)
|
||||||
28
ruby/lib/libptouch.rb
Normal file
28
ruby/lib/libptouch.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Ruby FFI bindings for libptouch (Brother P-touch raster printing).
|
||||||
|
#
|
||||||
|
# Author: knb
|
||||||
|
# Email: knb@artif.org
|
||||||
|
|
||||||
|
require_relative "libptouch/version"
|
||||||
|
require_relative "libptouch/error"
|
||||||
|
require_relative "libptouch/binding"
|
||||||
|
require_relative "libptouch/status_hash"
|
||||||
|
require_relative "libptouch/context"
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
ERR_NOMEM = 1
|
||||||
|
ERR_ARG = 2
|
||||||
|
ERR_USB = 3
|
||||||
|
ERR_IO = 4
|
||||||
|
ERR_UNSUPPORTED = 5
|
||||||
|
ERR_NOT_FOUND = 6
|
||||||
|
ERR_IMAGE = 7
|
||||||
|
|
||||||
|
USB_VID_BROTHER = 0x04f9
|
||||||
|
USB_PID_PTP900W = 0x2085
|
||||||
|
|
||||||
|
STATUS_LENGTH = 32
|
||||||
|
PNG_DEFAULT_THRESHOLD = 128
|
||||||
|
end
|
||||||
49
ruby/lib/libptouch/binding.rb
Normal file
49
ruby/lib/libptouch/binding.rb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "ffi"
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
module Binding
|
||||||
|
extend FFI::Library
|
||||||
|
|
||||||
|
def self.library_files
|
||||||
|
list = []
|
||||||
|
env = ENV["LIBPTOUCH_LIB"]
|
||||||
|
list << env if env && !env.empty?
|
||||||
|
base = File.expand_path("../../..", __dir__)
|
||||||
|
%w[libptouch.so libptouch.dylib].each do |name|
|
||||||
|
path = File.join(base, "build", name)
|
||||||
|
list << path if File.file?(path)
|
||||||
|
end
|
||||||
|
list << "libptouch"
|
||||||
|
list
|
||||||
|
end
|
||||||
|
|
||||||
|
ffi_lib library_files
|
||||||
|
|
||||||
|
class RasterParams < FFI::Struct
|
||||||
|
layout :width_dots, :uint32,
|
||||||
|
:height_dots, :uint32,
|
||||||
|
:margin_mm, :uint8,
|
||||||
|
:_pad, [:uint8, 3]
|
||||||
|
end
|
||||||
|
|
||||||
|
class PngOptions < FFI::Struct
|
||||||
|
layout :threshold, :uint8
|
||||||
|
end
|
||||||
|
|
||||||
|
attach_function :libptouch_create, [], :pointer
|
||||||
|
attach_function :libptouch_destroy, [:pointer], :void
|
||||||
|
attach_function :libptouch_strerror, [:pointer], :string
|
||||||
|
attach_function :libptouch_last_error, [:pointer], :int
|
||||||
|
attach_function :libptouch_open_usb, [:pointer], :int
|
||||||
|
attach_function :libptouch_open_usb_vid_pid, %i[pointer uint16 uint16], :int
|
||||||
|
attach_function :libptouch_close, [:pointer], :void
|
||||||
|
attach_function :libptouch_check_raster, %i[pointer pointer size_t pointer], :int
|
||||||
|
attach_function :libptouch_print_raster, %i[pointer pointer size_t pointer], :int
|
||||||
|
attach_function :libptouch_png_file_to_raster,
|
||||||
|
%i[pointer string pointer pointer pointer pointer], :int
|
||||||
|
attach_function :libptouch_free_raster, [:pointer], :void
|
||||||
|
attach_function :libptouch_get_status, %i[pointer pointer], :int
|
||||||
|
end
|
||||||
|
end
|
||||||
182
ruby/lib/libptouch/cli/png_print.rb
Normal file
182
ruby/lib/libptouch/cli/png_print.rb
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require "json"
|
||||||
|
require "optparse"
|
||||||
|
|
||||||
|
require "libptouch"
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
module Cli
|
||||||
|
# PNG のみを扱う ptouch-print 相当の CLI(1bit ラスター経路なし)。
|
||||||
|
module PngPrint
|
||||||
|
module_function
|
||||||
|
|
||||||
|
def run(argv)
|
||||||
|
opts = parse(argv)
|
||||||
|
return 2 if opts.nil?
|
||||||
|
|
||||||
|
return run_version if opts[:version]
|
||||||
|
return run_help if opts[:help]
|
||||||
|
|
||||||
|
if opts[:status]
|
||||||
|
warn_unused_file_options(opts)
|
||||||
|
return run_status
|
||||||
|
end
|
||||||
|
|
||||||
|
return usage_error("-f is required (or use --status)") if opts[:file].to_s.empty?
|
||||||
|
|
||||||
|
path = opts[:file]
|
||||||
|
return usage_error("not a PNG file: #{path}") unless png_file?(path)
|
||||||
|
|
||||||
|
run_print(path, opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def png_file?(path)
|
||||||
|
return true if path.downcase.end_with?(".png")
|
||||||
|
|
||||||
|
File.open(path, "rb") do |f|
|
||||||
|
sig = f.read(8)
|
||||||
|
sig == "\x89PNG\r\n\x1a\n".b
|
||||||
|
end
|
||||||
|
rescue Errno::ENOENT, Errno::EACCES => e
|
||||||
|
warn "open #{path}: #{e.message}"
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse(argv)
|
||||||
|
o = {
|
||||||
|
file: nil,
|
||||||
|
threshold: nil,
|
||||||
|
dry_run: false,
|
||||||
|
status: false,
|
||||||
|
version: false,
|
||||||
|
help: false
|
||||||
|
}
|
||||||
|
parser = OptionParser.new do |p|
|
||||||
|
p.banner = usage_banner
|
||||||
|
p.separator ""
|
||||||
|
p.on("-f", "--file PATH", "入力 PNG ファイル") { |v| o[:file] = v }
|
||||||
|
p.on("-t", "--threshold N", Integer,
|
||||||
|
"二値化しきい値 0–255(既定 #{Libptouch::PNG_DEFAULT_THRESHOLD})") do |v|
|
||||||
|
o[:threshold] = v
|
||||||
|
end
|
||||||
|
p.on("-n", "--dry-run", "読み込みと検証のみ(USB なし)") { o[:dry_run] = true }
|
||||||
|
p.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") { o[:status] = true }
|
||||||
|
p.on("-V", "--version", "バージョンを表示して終了") { o[:version] = true }
|
||||||
|
p.on("-h", "--help", "このヘルプ") { o[:help] = true }
|
||||||
|
end
|
||||||
|
parser.parse!(argv)
|
||||||
|
|
||||||
|
unless o[:threshold].nil? || (0..255).cover?(o[:threshold])
|
||||||
|
warn "-t must be 0..255"
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
o
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage_banner
|
||||||
|
<<~BANNER
|
||||||
|
Usage: ptouch-print-png [options]
|
||||||
|
|
||||||
|
PNG のみ対応。幅・高さは画像から取得します(-w/-H はありません)。
|
||||||
|
--status のときは -f は不要です。
|
||||||
|
BANNER
|
||||||
|
end
|
||||||
|
|
||||||
|
def warn_unused_file_options(opts)
|
||||||
|
return unless opts[:file] || opts[:dry_run] || !opts[:threshold].nil?
|
||||||
|
|
||||||
|
warn "warning: options other than --status are ignored"
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_version
|
||||||
|
puts "ptouch-print-png #{Libptouch::VERSION}"
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_help
|
||||||
|
puts usage_banner
|
||||||
|
puts ""
|
||||||
|
puts parser_help_text
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
def parser_help_text
|
||||||
|
o = {
|
||||||
|
file: nil,
|
||||||
|
threshold: nil,
|
||||||
|
dry_run: false,
|
||||||
|
status: false,
|
||||||
|
version: false,
|
||||||
|
help: false
|
||||||
|
}
|
||||||
|
p = OptionParser.new do |parser|
|
||||||
|
parser.banner = "ptouch-print-png [options]"
|
||||||
|
parser.on("-f", "--file PATH", "入力 PNG ファイル") { |v| o[:file] = v }
|
||||||
|
parser.on("-t", "--threshold N", Integer,
|
||||||
|
"二値化しきい値 0–255(既定 #{Libptouch::PNG_DEFAULT_THRESHOLD})") do |v|
|
||||||
|
o[:threshold] = v
|
||||||
|
end
|
||||||
|
parser.on("-n", "--dry-run", "読み込みと検証のみ(USB なし)") { o[:dry_run] = true }
|
||||||
|
parser.on("-S", "--status", "USB プリンタのステータスを JSON で表示して終了") { o[:status] = true }
|
||||||
|
parser.on("-V", "--version", "バージョンを表示して終了") { o[:version] = true }
|
||||||
|
parser.on("-h", "--help", "このヘルプ") { o[:help] = true }
|
||||||
|
end
|
||||||
|
p.help
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_status
|
||||||
|
ctx = nil
|
||||||
|
begin
|
||||||
|
ctx = Libptouch::Context.new
|
||||||
|
ctx.open_usb
|
||||||
|
h = Libptouch.parse_status(ctx.status_bytes)
|
||||||
|
h.delete(:raw_bytes)
|
||||||
|
puts JSON.pretty_generate(h)
|
||||||
|
0
|
||||||
|
rescue Libptouch::Error => e
|
||||||
|
warn "get_status: #{e.message}"
|
||||||
|
1
|
||||||
|
ensure
|
||||||
|
ctx&.dispose
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_print(path, opts)
|
||||||
|
ctx = nil
|
||||||
|
begin
|
||||||
|
ctx = Libptouch::Context.new
|
||||||
|
threshold = opts[:threshold]
|
||||||
|
data, width, height = if threshold.nil?
|
||||||
|
ctx.png_file_to_raster(path)
|
||||||
|
else
|
||||||
|
ctx.png_file_to_raster(path, threshold: threshold)
|
||||||
|
end
|
||||||
|
|
||||||
|
ctx.check_raster(data, width_dots: width, height_dots: height)
|
||||||
|
|
||||||
|
if opts[:dry_run]
|
||||||
|
puts "dry-run OK: #{data.bytesize} bytes, #{width}x#{height} dots"
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
ctx.open_usb
|
||||||
|
ctx.print_raster(data, width_dots: width, height_dots: height)
|
||||||
|
0
|
||||||
|
rescue Libptouch::Error => e
|
||||||
|
warn e.message
|
||||||
|
1
|
||||||
|
ensure
|
||||||
|
ctx&.dispose
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage_error(msg)
|
||||||
|
warn msg
|
||||||
|
warn "(try ptouch-print-png --help)"
|
||||||
|
2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
106
ruby/lib/libptouch/context.rb
Normal file
106
ruby/lib/libptouch/context.rb
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
class Context
|
||||||
|
OK = 0
|
||||||
|
|
||||||
|
attr_reader :native
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@native = Binding.libptouch_create
|
||||||
|
raise Libptouch::Error.new(0, "libptouch_create failed") if @native.null?
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_message
|
||||||
|
Binding.libptouch_strerror(@native)
|
||||||
|
end
|
||||||
|
|
||||||
|
def last_error_code
|
||||||
|
Binding.libptouch_last_error(@native)
|
||||||
|
end
|
||||||
|
|
||||||
|
def raise_on_error(code)
|
||||||
|
return if code == OK
|
||||||
|
|
||||||
|
msg = Binding.libptouch_strerror(@native)
|
||||||
|
raise Libptouch::Error.new(code, msg)
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_usb
|
||||||
|
raise_on_error(Binding.libptouch_open_usb(@native))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_usb_vid_pid(vid, pid)
|
||||||
|
raise_on_error(Binding.libptouch_open_usb_vid_pid(@native, vid, pid))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
Binding.libptouch_close(@native) if @native && !@native.null?
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def dispose
|
||||||
|
close
|
||||||
|
Binding.libptouch_destroy(@native) if @native && !@native.null?
|
||||||
|
@native = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_raster(data, width_dots:, height_dots:, margin_mm: 0)
|
||||||
|
params = Binding::RasterParams.new
|
||||||
|
params[:width_dots] = width_dots
|
||||||
|
params[:height_dots] = height_dots
|
||||||
|
params[:margin_mm] = margin_mm
|
||||||
|
buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
|
||||||
|
buf.put_bytes(0, data)
|
||||||
|
raise_on_error(Binding.libptouch_check_raster(@native, buf, data.bytesize,
|
||||||
|
params.pointer))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_raster(data, width_dots:, height_dots:, margin_mm: 0)
|
||||||
|
params = Binding::RasterParams.new
|
||||||
|
params[:width_dots] = width_dots
|
||||||
|
params[:height_dots] = height_dots
|
||||||
|
params[:margin_mm] = margin_mm
|
||||||
|
buf = FFI::MemoryPointer.new(:uint8, data.bytesize)
|
||||||
|
buf.put_bytes(0, data)
|
||||||
|
raise_on_error(Binding.libptouch_print_raster(@native, buf, data.bytesize,
|
||||||
|
params.pointer))
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def png_file_to_raster(path, threshold: nil)
|
||||||
|
opt_ptr = nil
|
||||||
|
unless threshold.nil?
|
||||||
|
o = Binding::PngOptions.new
|
||||||
|
o[:threshold] = threshold
|
||||||
|
opt_ptr = o.pointer
|
||||||
|
end
|
||||||
|
out_pp = FFI::MemoryPointer.new(:pointer)
|
||||||
|
out_len = FFI::MemoryPointer.new(:size_t)
|
||||||
|
out_params = Binding::RasterParams.new
|
||||||
|
raise_on_error(Binding.libptouch_png_file_to_raster(
|
||||||
|
@native, path, opt_ptr, out_pp, out_len, out_params.pointer
|
||||||
|
))
|
||||||
|
raw = out_pp.read_pointer
|
||||||
|
raise Libptouch::Error.new(OK, "null raster from PNG") if raw.null?
|
||||||
|
|
||||||
|
len = out_len.read_size_t
|
||||||
|
bytes = raw.read_bytes(len)
|
||||||
|
Binding.libptouch_free_raster(raw)
|
||||||
|
[bytes, out_params[:width_dots], out_params[:height_dots]]
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_bytes
|
||||||
|
buf = FFI::MemoryPointer.new(:uint8, STATUS_LENGTH)
|
||||||
|
raise_on_error(Binding.libptouch_get_status(@native, buf))
|
||||||
|
buf.read_bytes(STATUS_LENGTH)
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_hash
|
||||||
|
Libptouch.parse_status(status_bytes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
12
ruby/lib/libptouch/error.rb
Normal file
12
ruby/lib/libptouch/error.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
class Error < StandardError
|
||||||
|
attr_reader :code
|
||||||
|
|
||||||
|
def initialize(code, message = nil)
|
||||||
|
@code = code
|
||||||
|
super(message || "libptouch error #{code}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
197
ruby/lib/libptouch/status_hash.rb
Normal file
197
ruby/lib/libptouch/status_hash.rb
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
# 32 バイトのステータス応答を Hash に展開する(C の libptouch_status_fprint と同じ区分)。
|
||||||
|
module StatusHash
|
||||||
|
class << self
|
||||||
|
def decode(raw)
|
||||||
|
unless raw.bytesize == STATUS_LENGTH
|
||||||
|
raise ArgumentError,
|
||||||
|
"expected #{STATUS_LENGTH} bytes, got #{raw.bytesize}"
|
||||||
|
end
|
||||||
|
|
||||||
|
s = raw.bytes
|
||||||
|
|
||||||
|
{
|
||||||
|
header_ok: s[0] == 0x80 && s[1] == 0x20,
|
||||||
|
header: [s[0], s[1]],
|
||||||
|
brother_code: s[2],
|
||||||
|
brother_code_char: s[2] >= 32 && s[2] < 127 ? s[2].chr(Encoding::ASCII_8BIT) : nil,
|
||||||
|
model: model_entry(s[4]),
|
||||||
|
region_code: s[5],
|
||||||
|
region_char: s[5] >= 32 && s[5] < 127 ? s[5].chr(Encoding::ASCII_8BIT) : nil,
|
||||||
|
battery: labeled(BATTERY, s[6]),
|
||||||
|
extended_error: extended_error_entry(s[7]),
|
||||||
|
error_info1: error_info1(s[8]),
|
||||||
|
error_info2: error_info2(s[9]),
|
||||||
|
media_width: media_width_entry(s[10], s[17]),
|
||||||
|
tape_kind: labeled(MEDIA_KIND, s[11]),
|
||||||
|
color_count: s[12],
|
||||||
|
font_jp: s[13],
|
||||||
|
font: s[14],
|
||||||
|
mode: s[15],
|
||||||
|
density: s[16],
|
||||||
|
status_kind: labeled(STATUS_KIND, s[18]),
|
||||||
|
phase_type: s[19],
|
||||||
|
phase_number: [s[20], s[21]],
|
||||||
|
notification_number: s[22],
|
||||||
|
extended_section_bytes: s[23],
|
||||||
|
tape_color: labeled(TAPE_COLOR, s[24]),
|
||||||
|
text_color: s[25],
|
||||||
|
raw_hex: raw.unpack1("H*"),
|
||||||
|
raw_bytes: s.dup
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def model_entry(code)
|
||||||
|
{
|
||||||
|
code: code,
|
||||||
|
name: MODEL_NAMES[code],
|
||||||
|
ascii_char: code >= 32 && code < 127 ? code.chr(Encoding::ASCII_8BIT) : nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def labeled(table, byte)
|
||||||
|
{
|
||||||
|
code: byte,
|
||||||
|
label: table[byte]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def extended_error_entry(byte)
|
||||||
|
h = { code: byte, label: EXTENDED_ERROR[byte] }
|
||||||
|
h[:none] = true if byte.zero?
|
||||||
|
h
|
||||||
|
end
|
||||||
|
|
||||||
|
def media_width_entry(w, len_byte)
|
||||||
|
entry = labeled(MEDIA_WIDTH, w)
|
||||||
|
if w == 0x15 && len_byte != 0
|
||||||
|
entry[:media_length_code] = len_byte
|
||||||
|
entry[:media_length_note_mm] = len_byte
|
||||||
|
end
|
||||||
|
entry
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_info1(b)
|
||||||
|
{
|
||||||
|
raw: b,
|
||||||
|
media_missing: !!(b & 0x01),
|
||||||
|
media_end: !!(b & 0x02),
|
||||||
|
cutter_jam: !!(b & 0x04),
|
||||||
|
battery_weak: !!(b & 0x08),
|
||||||
|
high_voltage_adapter: !!(b & 0x40)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def error_info2(b)
|
||||||
|
{
|
||||||
|
raw: b,
|
||||||
|
media_mismatch: !!(b & 0x01),
|
||||||
|
comm_error: !!(b & 0x04),
|
||||||
|
comm_buffer_full: !!(b & 0x08),
|
||||||
|
cover_open: !!(b & 0x10),
|
||||||
|
heat_error: !!(b & 0x20),
|
||||||
|
tip_detection_error: !!(b & 0x40),
|
||||||
|
system_error: !!(b & 0x80)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MODEL_NAMES = {
|
||||||
|
0x6F => "PT-P900W",
|
||||||
|
0x70 => "PT-P950NW",
|
||||||
|
0x71 => "PT-P900",
|
||||||
|
0x78 => "PT-P910BT"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
MEDIA_WIDTH = {
|
||||||
|
0x00 => "テープなし / 未装着",
|
||||||
|
0x04 => "3.5 mm",
|
||||||
|
0x06 => "6 mm",
|
||||||
|
0x09 => "9 mm",
|
||||||
|
0x0C => "12 mm",
|
||||||
|
0x12 => "18 mm",
|
||||||
|
0x18 => "24 mm",
|
||||||
|
0x24 => "36 mm",
|
||||||
|
0x15 => "FLe 21 mm 幅(長さはメディア長バイト参照)"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
MEDIA_KIND = {
|
||||||
|
0x00 => "テープなし",
|
||||||
|
0x01 => "ラミネートテープ",
|
||||||
|
0x03 => "ノンラミネートテープ",
|
||||||
|
0x04 => "ファブリックテープ",
|
||||||
|
0x11 => "ヒートシュリンクチューブ (HS 2:1)",
|
||||||
|
0x13 => "FLe テープ",
|
||||||
|
0x14 => "フレキシブルIDテープ",
|
||||||
|
0x15 => "サテンテープ",
|
||||||
|
0x17 => "ヒートシュリンクチューブ (HS 3:1)",
|
||||||
|
0xFF => "非対応テープ"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
BATTERY = {
|
||||||
|
0x00 => "フル",
|
||||||
|
0x01 => "ハーフ",
|
||||||
|
0x02 => "ロー",
|
||||||
|
0x03 => "要充電",
|
||||||
|
0x04 => "AC アダプター使用中",
|
||||||
|
0xFF => "不明"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
TAPE_COLOR = {
|
||||||
|
0x01 => "白 (White)",
|
||||||
|
0x02 => "その他 (Other)",
|
||||||
|
0x03 => "透明 (Clear)",
|
||||||
|
0x04 => "赤 (Red)",
|
||||||
|
0x05 => "青 (Blue)",
|
||||||
|
0x06 => "黄 (Yellow)",
|
||||||
|
0x07 => "緑 (Green)",
|
||||||
|
0x08 => "黒 (Black)",
|
||||||
|
0x09 => "透明(文字白)",
|
||||||
|
0x20 => "白(マット) (Matte White)",
|
||||||
|
0x21 => "透明(マット) (Matte Clear)",
|
||||||
|
0x22 => "銀(マット) (Matte Silver)",
|
||||||
|
0x23 => "金(サテン) (Satin Gold)",
|
||||||
|
0x24 => "銀(サテン) (Satin Silver)",
|
||||||
|
0x30 => "青(D)",
|
||||||
|
0x31 => "赤(D)",
|
||||||
|
0x40 => "オレンジ(蛍光)",
|
||||||
|
0x41 => "黄(蛍光)",
|
||||||
|
0x50 => "ピンク(S)",
|
||||||
|
0x51 => "グレー(S)",
|
||||||
|
0x52 => "グリーン(S)",
|
||||||
|
0x60 => "イエロー(F)",
|
||||||
|
0x61 => "ピンク(F)",
|
||||||
|
0x62 => "ブルー(F)",
|
||||||
|
0x70 => "白(チューブ)",
|
||||||
|
0x90 => "白(フレキ)",
|
||||||
|
0x91 => "黄(フレキ)",
|
||||||
|
0xF0 => "クリーニング",
|
||||||
|
0xF1 => "ステンシル",
|
||||||
|
0xFF => "非対応"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
STATUS_KIND = {
|
||||||
|
0x00 => "印刷終了",
|
||||||
|
0x01 => "エラー発生",
|
||||||
|
0x02 => "IF モード終了",
|
||||||
|
0x03 => "パワーオフ(未使用扱い)",
|
||||||
|
0x04 => "通知",
|
||||||
|
0x05 => "フェーズ変更"
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
EXTENDED_ERROR = {
|
||||||
|
0x10 => "FLE のテープエンド",
|
||||||
|
0x1D => "高解像度/ドラフト印刷エラー",
|
||||||
|
0x1E => "アダプター抜き挿しエラー",
|
||||||
|
0x21 => "非対応メディアエラー"
|
||||||
|
}.freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.parse_status(raw)
|
||||||
|
StatusHash.decode(raw)
|
||||||
|
end
|
||||||
|
end
|
||||||
5
ruby/lib/libptouch/version.rb
Normal file
5
ruby/lib/libptouch/version.rb
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Libptouch
|
||||||
|
VERSION = "1.0.0"
|
||||||
|
end
|
||||||
31
ruby/libptouch.gemspec
Normal file
31
ruby/libptouch.gemspec
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
lib = File.expand_path("lib", __dir__)
|
||||||
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
require "libptouch/version"
|
||||||
|
|
||||||
|
Gem::Specification.new do |spec|
|
||||||
|
spec.name = "libptouch"
|
||||||
|
spec.version = Libptouch::VERSION
|
||||||
|
spec.authors = ["knb"]
|
||||||
|
spec.email = ["knb@artif.org"]
|
||||||
|
|
||||||
|
spec.summary = "FFI bindings for libptouch (Brother P-touch USB raster printing)"
|
||||||
|
spec.description = [
|
||||||
|
"Ruby wrapper around the ptouch_label C library libptouch.",
|
||||||
|
"Requires libptouch shared library (libusb, libpng)."
|
||||||
|
].join(" ")
|
||||||
|
spec.license = "MIT"
|
||||||
|
spec.required_ruby_version = ">= 3.0"
|
||||||
|
repo = "https://gitea.artif.org/knb/ptouch_label"
|
||||||
|
spec.homepage = repo
|
||||||
|
spec.metadata["source_code_uri"] = repo
|
||||||
|
spec.metadata["rubygems_mfa_required"] = "true"
|
||||||
|
|
||||||
|
spec.files = Dir.chdir(__dir__) { Dir["lib/**/*.rb", "exe/*", "README.md"] }
|
||||||
|
spec.bindir = "exe"
|
||||||
|
spec.executables = ["ptouch-print-png"]
|
||||||
|
spec.require_paths = ["lib"]
|
||||||
|
|
||||||
|
spec.add_dependency "ffi", "~> 1.15"
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user