Get file mode transmission working for unmodified PNG
This commit is contained in:
parent
ce4c71c465
commit
5562a4d52f
@ -159,11 +159,6 @@ func on_initialize() (string, error) {
|
|||||||
cc.SetAction(graphics.GRT_action_delete).SetDelete(graphics.GRT_free_visible)
|
cc.SetAction(graphics.GRT_action_delete).SetDelete(graphics.GRT_free_visible)
|
||||||
cc.WriteWithPayloadToLoop(lp, nil)
|
cc.WriteWithPayloadToLoop(lp, nil)
|
||||||
}
|
}
|
||||||
if opts.TransferMode != "detect" {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
query_in_flight = true
|
|
||||||
lp.AddTimer(time.Duration(opts.DetectionTimeout*float64(time.Second)), false, on_detect_timeout)
|
lp.AddTimer(time.Duration(opts.DetectionTimeout*float64(time.Second)), false, on_detect_timeout)
|
||||||
g := func(t graphics.GRT_t, payload string) uint32 {
|
g := func(t graphics.GRT_t, payload string) uint32 {
|
||||||
iid += 1
|
iid += 1
|
||||||
@ -181,9 +176,13 @@ func on_initialize() (string, error) {
|
|||||||
go run_worker()
|
go run_worker()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if opts.TransferMode != "detect" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
query_in_flight = true
|
||||||
direct_query_id = g(graphics.GRT_transmission_direct, "123")
|
direct_query_id = g(graphics.GRT_transmission_direct, "123")
|
||||||
tf, err := graphics.MakeTemp()
|
tf, err := graphics.CreateTempInRAM()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
file_query_id = g(graphics.GRT_transmission_tempfile, tf.Name())
|
file_query_id = g(graphics.GRT_transmission_tempfile, tf.Name())
|
||||||
temp_files_to_delete = append(temp_files_to_delete, tf.Name())
|
temp_files_to_delete = append(temp_files_to_delete, tf.Name())
|
||||||
@ -397,6 +396,10 @@ func main(cmd *cli.Command, o *Options, args []string) (rc int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if opts.Hold {
|
if opts.Hold {
|
||||||
|
fmt.Print("\r")
|
||||||
|
if opts.Place != "" {
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
tui.HoldTillEnter(false)
|
tui.HoldTillEnter(false)
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
|||||||
@ -147,7 +147,8 @@ type image_data struct {
|
|||||||
format_uppercase string
|
format_uppercase string
|
||||||
available_width, available_height int
|
available_width, available_height int
|
||||||
needs_scaling, needs_conversion bool
|
needs_scaling, needs_conversion bool
|
||||||
frames []image_frame
|
frames []*image_frame
|
||||||
|
image_number uint32
|
||||||
|
|
||||||
// for error reporting
|
// for error reporting
|
||||||
err error
|
err error
|
||||||
@ -155,7 +156,7 @@ type image_data struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func set_basic_metadata(imgd *image_data) {
|
func set_basic_metadata(imgd *image_data) {
|
||||||
imgd.frames = make([]image_frame, 0, 32)
|
imgd.frames = make([]*image_frame, 0, 32)
|
||||||
imgd.available_width = int(screen_size.WidthPx)
|
imgd.available_width = int(screen_size.WidthPx)
|
||||||
imgd.available_height = 10 * imgd.canvas_height
|
imgd.available_height = 10 * imgd.canvas_height
|
||||||
if place != nil {
|
if place != nil {
|
||||||
@ -179,7 +180,8 @@ func report_error(source_name, msg string, err error) {
|
|||||||
|
|
||||||
func make_output_from_input(imgd *image_data, f *opened_input) {
|
func make_output_from_input(imgd *image_data, f *opened_input) {
|
||||||
bb, ok := f.file.(*BytesBuf)
|
bb, ok := f.file.(*BytesBuf)
|
||||||
frame := &imgd.frames[0]
|
frame := image_frame{}
|
||||||
|
imgd.frames = append(imgd.frames, &frame)
|
||||||
frame.width = imgd.canvas_width
|
frame.width = imgd.canvas_width
|
||||||
frame.height = imgd.canvas_height
|
frame.height = imgd.canvas_height
|
||||||
if ok {
|
if ok {
|
||||||
|
|||||||
@ -3,32 +3,57 @@
|
|||||||
package icat
|
package icat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"kitty/tools/tui/graphics"
|
"kitty/tools/tui/graphics"
|
||||||
|
"kitty/tools/utils"
|
||||||
"kitty/tools/utils/shm"
|
"kitty/tools/utils/shm"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
|
|
||||||
func gc_for_image(imgd *image_data) *graphics.GraphicsCommand {
|
func gc_for_image(imgd *image_data, data_size, frame_num int, frame *image_frame) *graphics.GraphicsCommand {
|
||||||
|
gc := graphics.GraphicsCommand{}
|
||||||
|
gc.SetDataSize(uint64(data_size)).SetAction(graphics.GRT_action_transmit_and_display)
|
||||||
|
gc.SetDataWidth(uint64(frame.width)).SetDataHeight(uint64(frame.height))
|
||||||
|
gc.SetQuiet(graphics.GRT_quiet_silent)
|
||||||
|
if z_index != 0 {
|
||||||
|
gc.SetZIndex(z_index)
|
||||||
|
}
|
||||||
|
if imgd.image_number != 0 {
|
||||||
|
gc.SetImageNumber(imgd.image_number)
|
||||||
|
}
|
||||||
|
switch imgd.format_uppercase {
|
||||||
|
case "PNG":
|
||||||
|
gc.SetFormat(graphics.GRT_format_png)
|
||||||
|
default:
|
||||||
|
gc.SetFormat(graphics.GRT_format_rgb)
|
||||||
|
case "RGBA":
|
||||||
|
gc.SetFormat(graphics.GRT_format_rgba)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &gc
|
||||||
}
|
}
|
||||||
|
|
||||||
func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) error {
|
func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) (err error) {
|
||||||
var data_size int
|
var data_size int
|
||||||
|
var mmap shm.MMap
|
||||||
if frame.in_memory_bytes == nil {
|
if frame.in_memory_bytes == nil {
|
||||||
f, err := os.Open(frame.filename)
|
f, err := os.Open(frame.filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Failed to open image data output file: %s with error: %w", frame.filename, err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
sz, _ := f.Seek(0, io.SeekEnd)
|
sz, _ := f.Seek(0, io.SeekEnd)
|
||||||
f.Seek(0, io.SeekStart)
|
f.Seek(0, io.SeekStart)
|
||||||
mmap, err := shm.CreateTemp("icat-*", uint64(sz))
|
mmap, err = shm.CreateTemp("icat-*", uint64(sz))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Failed to create a SHM file for transmission: %w", err)
|
||||||
}
|
}
|
||||||
defer mmap.Close()
|
defer mmap.Close()
|
||||||
dest := mmap.Slice()
|
dest := mmap.Slice()
|
||||||
@ -40,24 +65,81 @@ func transmit_shm(imgd *image_data, frame_num int, frame *image_frame) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
mmap.Unlink()
|
mmap.Unlink()
|
||||||
return err
|
return fmt.Errorf("Failed to read data from image output data file: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data_size = len(mmap.Slice()) - len(dest)
|
data_size = len(mmap.Slice()) - len(dest)
|
||||||
} else {
|
} else {
|
||||||
mmap, err := shm.CreateTemp("icat-*", uint64(len(frame.in_memory_bytes)))
|
mmap, err = shm.CreateTemp("icat-*", uint64(len(frame.in_memory_bytes)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("Failed to create a SHM file for transmission: %w", err)
|
||||||
}
|
}
|
||||||
defer mmap.Close()
|
defer mmap.Close()
|
||||||
data_size = copy(mmap.Slice(), frame.in_memory_bytes)
|
data_size = copy(mmap.Slice(), frame.in_memory_bytes)
|
||||||
}
|
}
|
||||||
|
gc := gc_for_image(imgd, data_size, frame_num, frame)
|
||||||
|
gc.SetTransmission(graphics.GRT_transmission_sharedmem)
|
||||||
|
gc.WriteWithPayloadToLoop(lp, utils.UnsafeStringToBytes(mmap.Name()))
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func transmit_file(imgd *image_data, frame_num int, frame *image_frame) error {
|
func transmit_file(imgd *image_data, frame_num int, frame *image_frame) (err error) {
|
||||||
|
var data_size int
|
||||||
|
is_temp := false
|
||||||
|
fname := ""
|
||||||
|
if frame.in_memory_bytes == nil {
|
||||||
|
is_temp = frame.filename_is_temporary
|
||||||
|
fname, err = filepath.Abs(frame.filename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to convert image data output file: %s to absolute path with error: %w", frame.filename, err)
|
||||||
|
}
|
||||||
|
frame.filename = "" // so it isnt deleted in cleanup
|
||||||
|
s, err := os.Stat(fname)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to stat() image data output file: %s with error: %w", fname, err)
|
||||||
|
}
|
||||||
|
data_size = int(s.Size())
|
||||||
|
} else {
|
||||||
|
data_size = len(frame.in_memory_bytes)
|
||||||
|
f, err := graphics.CreateTempInRAM()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to create a temp file for image data transmission: %w", err)
|
||||||
|
}
|
||||||
|
_, err = bytes.NewBuffer(frame.in_memory_bytes).WriteTo(f)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to write image data to temp file for transmission: %w", err)
|
||||||
|
}
|
||||||
|
is_temp = true
|
||||||
|
fname = f.Name()
|
||||||
|
}
|
||||||
|
gc := gc_for_image(imgd, data_size, frame_num, frame)
|
||||||
|
if is_temp {
|
||||||
|
gc.SetTransmission(graphics.GRT_transmission_tempfile)
|
||||||
|
} else {
|
||||||
|
gc.SetTransmission(graphics.GRT_transmission_file)
|
||||||
|
}
|
||||||
|
gc.WriteWithPayloadToLoop(lp, utils.UnsafeStringToBytes(fname))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func transmit_stream(imgd *image_data, frame_num int, frame *image_frame) error {
|
func transmit_stream(imgd *image_data, frame_num int, frame *image_frame) (err error) {
|
||||||
|
data := frame.in_memory_bytes
|
||||||
|
if data == nil {
|
||||||
|
f, err := os.Open(frame.filename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to open image data output file: %s with error: %w", frame.filename, err)
|
||||||
|
}
|
||||||
|
data, err = io.ReadAll(f)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed to read data from image output data file: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gc := gc_for_image(imgd, len(data), frame_num, frame)
|
||||||
|
gc.WriteWithPayloadToLoop(lp, data)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func transmit_image(imgd *image_data) {
|
func transmit_image(imgd *image_data) {
|
||||||
@ -79,7 +161,6 @@ func transmit_image(imgd *image_data) {
|
|||||||
f = transmit_shm
|
f = transmit_shm
|
||||||
case "stream":
|
case "stream":
|
||||||
f = transmit_stream
|
f = transmit_stream
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if f == nil && transfer_by_memory == supported && imgd.frames[0].in_memory_bytes != nil {
|
if f == nil && transfer_by_memory == supported && imgd.frames[0].in_memory_bytes != nil {
|
||||||
@ -91,8 +172,11 @@ func transmit_image(imgd *image_data) {
|
|||||||
if f == nil {
|
if f == nil {
|
||||||
f = transmit_stream
|
f = transmit_stream
|
||||||
}
|
}
|
||||||
|
if len(imgd.frames) > 1 {
|
||||||
|
imgd.image_number = rand.Uint32()
|
||||||
|
}
|
||||||
for frame_num, frame := range imgd.frames {
|
for frame_num, frame := range imgd.frames {
|
||||||
err := f(imgd, frame_num, &frame)
|
err := f(imgd, frame_num, frame)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
print_error("Failed to transmit %s with error: %v", imgd.source_name, err)
|
print_error("Failed to transmit %s with error: %v", imgd.source_name, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,14 +14,25 @@ import (
|
|||||||
|
|
||||||
"kitty/tools/tui/loop"
|
"kitty/tools/tui/loop"
|
||||||
"kitty/tools/utils"
|
"kitty/tools/utils"
|
||||||
|
"kitty/tools/utils/shm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = fmt.Print
|
var _ = fmt.Print
|
||||||
|
|
||||||
func MakeTemp() (*os.File, error) {
|
func CreateTemp() (*os.File, error) {
|
||||||
return os.CreateTemp("", "tty-graphics-protocol-*")
|
return os.CreateTemp("", "tty-graphics-protocol-*")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateTempInRAM() (*os.File, error) {
|
||||||
|
if shm.SHM_DIR != "" {
|
||||||
|
f, err := os.CreateTemp(shm.SHM_DIR, "tty-graphics-protocol-*")
|
||||||
|
if err == nil {
|
||||||
|
return f, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CreateTemp()
|
||||||
|
}
|
||||||
|
|
||||||
// Enums {{{
|
// Enums {{{
|
||||||
type GRT_a int
|
type GRT_a int
|
||||||
|
|
||||||
@ -523,7 +534,7 @@ func (self *GraphicsCommand) AsAPC(payload []byte) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *GraphicsCommand) WriteWithPayloadTo(o io.StringWriter, payload []byte) (err error) {
|
func (self *GraphicsCommand) WriteWithPayloadTo(o io.StringWriter, payload []byte) (err error) {
|
||||||
const compression_threshold = 1024
|
const compression_threshold = 2048
|
||||||
if len(payload) == 0 {
|
if len(payload) == 0 {
|
||||||
return self.serialize_to(o, "")
|
return self.serialize_to(o, "")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,3 +4,4 @@ package shm
|
|||||||
|
|
||||||
const SHM_NAME_MAX = 30
|
const SHM_NAME_MAX = 30
|
||||||
const SHM_REQUIRED_PREFIX = ""
|
const SHM_REQUIRED_PREFIX = ""
|
||||||
|
const SHM_DIR = ""
|
||||||
|
|||||||
@ -4,3 +4,4 @@ package shm
|
|||||||
|
|
||||||
const SHM_NAME_MAX = 1023
|
const SHM_NAME_MAX = 1023
|
||||||
const SHM_REQUIRED_PREFIX = "/"
|
const SHM_REQUIRED_PREFIX = "/"
|
||||||
|
const SHM_DIR = ""
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user