NikitaIvanovV / ctpv

Image previews for lf file manager
https://www.nikitaivanov.com/man1/ctpv
MIT License
264 stars 24 forks source link

Connect ueberzug's stdout to ctpv's stdout #41

Open jstkdng opened 1 year ago

jstkdng commented 1 year ago

Hello, I've recently started working in a replacement for Ueberzug after its demise. ueberzugpp

It works OOB with ctpv and other software that previously used og ueberzug. But one feature that I added that wasn't in OG Ueberzug doesn't work, that being sixel output.

In ranger, sixel output works with some changes, particularly, connecting ueberzug's stdout to python's.

        self.process = Popen(['ueberzug', 'layer', '--silent'],
                             stderr=PIPE, stdout=sys.stdout.buffer,
                             cwd=self.working_dir,  universal_newlines=True)

(sample of sixel output working on wezterm/sixel) image

sadly, the same can't be said for lf, as no output is being generated.

image

it works on alacritty/x11 image

One way to fix this is to connect ctpv's (or is this an lf issue?) stdout to ueberzugpp's. I tried to do it on my own but you understand this codebase more than I do.

I'd be grateful if you could make this changes as they would keep compatibility with OG ueberzug and also add support for ueberzugpp.

NikitaIvanovV commented 1 year ago

Thanks for opening the issue!

Ueberzug worked by running a background process that draws stuff on top of windows. And your program is a drop-in replacement (meaning it apparantly has the same binary name). So I'm not sure how it's possible determine that ctpv is about to run your version of ueberzug that has sixel support, which means that now it must run your program directly instead of sending a message to a background ueberzug instance.

Maybe a solution would be to install ueberzugpp symlink that points to the binary? In this case ctpv would just check if the ueberzugpp symlink exists and determine that the user has your version of the program.

By the way, we already can view files with sixel via chafa. But adding support for your program as well could be useful too.

jstkdng commented 1 year ago

ueberzugpp works the same way as ueberzug, you spawn it and send json commands. I see no need no differentiate them unless you plan to replace ueberzug with ueberzugpp. Linking stdout to regular ueberzug and ueberzugpp would work the same, you'd just have to spawn the binary with the --silent flag.

By the way, we already can view files with sixel via chafa.

yeah, chafa's great. Too bad it doesn't implement X11 displaying.

NikitaIvanovV commented 1 year ago

At the moment, ctpv runs a "server" program in backgroud to handle ueberzug. So, when lf requests a new preview, it calls ctpv, which sends a command to a FIFO file. The ctpv server that is running in background receives it and redirects it to Ueberzug.

I'm not sure how to redirect Ueberzug output back to ctpv in this situation. Use a socket instead of a FIFO file? Seems complicated to do right.

jstkdng commented 1 year ago

how are you handling chafa? Chafa also needs it's stdout redirected for it to correctly display the image.

NikitaIvanovV commented 1 year ago

Chafa is a simple program: you call it, it prints stuff, you send it to lf. But ueberzug is a little different because it needs to be kept running in the background for the preview to show up. It complicates things a lot. As I explained in the previous reply, I need to run a seperate "server" ctpv background process that handles ueberzug and sends data to it. By the way, this is why you need this line in your lf config when you setup ctpv:

&ctpv -s $id

It starts this server process.

Here I'm talking about the old ueberzug and how I made it work with ctpv. Maybe yours is somehow different?

jstkdng commented 1 year ago

I see, that is required for the OG ueberzug setup in which you have to send commands through stdin. Ueberzugpp has another way to receive commands though, that being through a unix socket. That maybe could simplify how you handle ueberzug (?. Just spawn it, send commands through the socket when required and send SIGTERM at the end.

The socket is located in /tmp and is named /tmp/ueberzugpp-${PID}.socket PID being ueberzugpp's socket.

That'd mean supporting my version altogether though. I'd say it is worth it as chafa's sixel implementation has lower quality compared to libsixel's. I also plan to add chafa support in cases in which nothing can be used, like a wayland terminal with no sixel or kitty, or the tty.