Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chain rendering #10

Open
Ph-St opened this issue May 8, 2024 · 8 comments
Open

Chain rendering #10

Ph-St opened this issue May 8, 2024 · 8 comments

Comments

@Ph-St
Copy link

Ph-St commented May 8, 2024

Following up on issue #9, I tried to implement a chain_renderer. Here it is:

#!/usr/bin/python3

# Since all available 3rd party renderer tools for remarkable have issues, it is useful to run them in a chain.
#
# In the configuration, renderer commands can be defined that will be used in the order they are listed. Each command must be able to be called as "command infile outfile"

import sys
import os.path
import subprocess


renderer_list = ["./render_rmrl.py", "./render_maxio.py", "./render_fail.py"] # Add all renderers in the order in which they should be employed. render_fail.py will output a PDF with an error message; it can be added to the list to make sure further documents are being processed.
    

if __name__ == "__main__":
    args = sys.argv[1:]
    assert len(args) == 2, "usage: render_chain.py infile outfile"

    infile = args[0]
    outfile = args[1]

    for command in renderer_list:
        status, _ = subprocess.getstatusoutput(f"{command} \"{infile}\" \"{outfile}\"")
        
        if status == 0:
            break
    
    exit(status)

I also wrote a dummy renderer (render_fail.py) that is called last in the chain to make sure further documents are being processed. Here it is:

#!/usr/bin/python3

# This is a dummy renderer. It creates a pdf file with an error message. It can be used to make sure that other files get processed after an error.

import sys
import os.path
import subprocess
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4

def generate_pdf(outfile):
    c = canvas.Canvas(outfile, pagesize=A4)
    c.drawString(50, 750, "This file could not be rendered.")
    c.showPage()
    c.save()


if __name__ == "__main__":
    args = sys.argv[1:]
    assert len(args) == 2, "usage: render_fail.py infile outfile"

    infile = args[0]
    outfile = args[1]

    status = generate_pdf(outfile)
    exit(status)

For completeness, here is render_rmrl.py again:

#!/usr/bin/python3

# This method uses the third-party renderer rmrl to render reMarkable documents locally on the computer.
# It downloads the raw reMarkable files to the computer and renders them locally.
#
# It requires the python module rmrl (https://github.com/rschroll/rmrl/) and SSH access to the reMarkable (to download the raw files), but no USB connection.
#
# It fails in some cases.
#
# To use a different third-party renderer, wrap it in a script with call signature like this one!

import sys
import os.path
import subprocess
from rmrl import render

def render_rmrl(input, output):
    stream = render(input)
    with open(output, "wb") as out_file:
        out_file.write(stream.read())
    


if __name__ == "__main__":
    args = sys.argv[1:]
    assert len(args) == 2, "usage: render_rmrl.py infile outfile"

    infile = args[0]
    outfile = args[1]

    status = render_rmrl(infile, outfile)
    
    exit(status)
@hersle
Copy link
Owner

hersle commented May 10, 2024

Thanks, these are nice additions!

Do you think it makes sense to move the chain rendering logic inside the main script? I'm thinking that the --renderer argument could be expanded to take a list of renderers that will be used to attempt to render each document, in order. For example, ./rmirro.py --renderers render_rmrl.py render_maxio.py render_fail.py would be equivalent to your chain renderer. That would prevent "hard-coding" the list of renderers into a script, and perhaps make it a little easier for users to change.

I think the default should still be --renderers render_usb.py for ease of use, stability and predictability. My first thought is that the chain rendering logic should throw an error/warning after trying the last renderer and output nothing. If one wants to change that behavior and output a "dummy file", one can elegantly include your failing renderer like --renderers render_rmrl.py render_fail.py. Do you think that is sensible behavior?

@Ph-St
Copy link
Author

Ph-St commented May 13, 2024

I agree with both points! I think it would be much better if the renderers could be specified in parameters instead of hard-coded in the chain-renderer and your proposed standard behavior also makes a lot of sense. Thanks for incorporating these changes!

@hersle
Copy link
Owner

hersle commented May 24, 2024

You can now do e.g. ./rmirro.py --renderers render_fail.py render_usb.py.

@hersle
Copy link
Owner

hersle commented May 24, 2024

I also added your rmrl renderer. Thanks!

@hersle hersle closed this as completed May 24, 2024
@Ph-St
Copy link
Author

Ph-St commented May 25, 2024

Brilliant, many thanks for incorporating the new features!

@Ph-St
Copy link
Author

Ph-St commented May 25, 2024

I just tried it out and perhaps I'm not using it right, but when I run

./rmirro.py remarkable --renderers render_rmrl.py render_maxio.py render_fail.py

the script just stops on the first occurrence where render_rmrl.py and render_maxio.py can't render the document. That's in effect the same outcome as before, whereas the idea of render_fail.py was to note the failed rendering (in my case by producing a PDF that said so) and pass a success status back to the main script in order to allow the script to continue running. I guess the simplest way to achieve that would be to change

exit(1) # fail

to

exit(0) # fail

and perhaps give a more verbose error message?

Cheers!

@hersle
Copy link
Owner

hersle commented Jun 9, 2024

Thanks, I see what you mean, and I like the intention of producing placeholder PDFs for documents that fail to render. But I am a little concerned that the placeholder documents in some unfortunate scenario are registered as "proper documents" that are synced back to the RM from the PC and overwrites the actual documents on the RM.

@hersle hersle reopened this Jun 9, 2024
@Ph-St
Copy link
Author

Ph-St commented Jun 10, 2024

Ah, that's a good point. Well, the placeholder pdfs were just meant as a record of which files failed, so I suppose that a proper summary at the end of an rmirro run, in which all files that couldn't be rendered are listed, would do the job as well. And if that is implemented, then perhaps render_fail is not even necessary anymore, but could be replaced by a parameter that defines whether rmirro should stop as soon as a document cannot be rendered or whether it should continue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants