pi3d / pi3d_demos

Demos and support files for pi3d (3D graphics python package for the raspberry pi)
Other
71 stars 33 forks source link

Interaction Functionality Help (Skip, Rewind, Videos, Sound) #63

Open paytah232 opened 3 years ago

paytah232 commented 3 years ago

Hi. I'm hoping this is the right avenue to do this; I need some help configuring my photoframe2020. I believe I read through the config and didn't see any of the above features (but I could be totally wrong). Are the following things possible to be done? I am running a rpi 3 with a touch screen/speakers.

  1. Skip/Rewind: Being a touchscreen, is there an option to have a buttons (hidden) that take up the entire left/right of the screen that correspond to go back to the last picture / skip this picture respectively.
  2. Videos: Does this system Natively support video playback; if so, is there a way to mute any audio by default, or perhaps ignore video files
  3. Kill Switch: Holding the touch screen down for an extended period of time will cause the program to quit, and show the desktop (I'm thinking a 5 second+ press).

Any help with these questions would be greatly appreciated. Love the work that has gone into this so far!

paddywwoof commented 3 years ago

Hi, we've started to consolidate all the effort on this demo here. But the the touchscreen issue has certainly cropped up before https://github.com/tipam/pi3d/issues/247 and we ought to think a bit more about making it easy to link in. Essentially you need touchscreen software running on your Pi so that the operating system will treat touches as mouse location and left button down/up signals. Then you need to have a loop running (on the old version that's the Display.loop_running() loop - in the new version you would need to put it into the interface_keyboard file, I will do some tests here and let you know the best way) There are pi3d.Mouse methods for getting location and button info so you can call next(), back(), stop()

Videos are excluded though we did discuss possible ways to make switching to a video player more elegant.

paytah232 commented 3 years ago

Thanks for that update @paddywwoof. I'll have to have a look to see if I can figure it out when next I get a chance. If you work it out earlier, definitely let me know. I am also running on an older version, because I updated to the new one and got an error.

paddywwoof commented 3 years ago

Hi, I will make some suggestions for code snippets to get the mouse click and link to the key actions on the basis of old version.

I would like to know what problems you had with the new version. There are probably lots of issues that we need to sort out!

Paddy

paytah232 commented 3 years ago

Hi Paddy,

So I am running the old version (not sure which version though) using a service, with this command: ExecStart=/usr/bin/python3 /home/pi/pi3d_demos/PictureFrame2020.py -v=10 -t=True -b=True -w=2 -s=0.0

I get the following error, but it all works as expected and I get a slideshow: glGetError 0x500

When I run the latest version using this command: python3 /home/pi/pi3d_demos_new/PictureFrame2020.py -v=10 -t=True -b=True -w=2 -s=0.0

I get this error:

Traceback (most recent call last):
  File "/home/pi/pi3d_demos_new/PictureFrame2020.py", line 595, in <module>
    textblock.set_text(text_format=final_string, wrap=config.TEXT_WIDTH)
TypeError: set_text() got an unexpected keyword argument 'wrap'

I'd be happy to use the new version, but I don't really have any clue where to start debugging for the above error.

Cheers, Peter

paddywwoof commented 3 years ago

Ah OK. That looks like an error because it's wanting a newer version of pi3d. That glGetError has been cleaned up in the latest couple of versions too.

With the newer version from github.com/helgeerbe/picframe you should be able to git install the whole thing and it will pull in the dependency for the latest pi3d (plus others). I would follow Wolfgang's instructions here: https://www.thedigitalpictureframe.com/how-to-add-crossfading-slide-transitions-to-your-digital-picture-frame-using-pi3d/#Installing_PictureFrame_on_your_Raspberry_Pi

It depends on whether you're using a Pi3 or Pi4 (which needs sudo) but basically you can just do

pip3 install picframe

(but follow Wolfgang's instructions) It shouldn't tread on the toes of anything you already have installed, even if you do the picframe -i . it will put things into a directory `/home/pi/picframe_data' and all your existing slideshow stuff should carry on working. However this will update to the latest pi3d etc. and, if the new picframe version works OK, there are other advantages. If I fix up the touchscreen for the new system it will then work on your setup if you manage to get it to work.

Paddy

paddywwoof commented 3 years ago

Peter, Did you install the latest version. Here is a sketch of how to use the mouse (touchscreen) input. Because the keyboard and http interfaces have their own python threaded loops the shutdown of all the loops in a controlled way is a bit precarious so that needs working on. I think the MQTT will be fine running at the same time. I am imagining that you installed using pip3 then ran picframe with the -i argument to set it up, and configured the configuration.yaml file.

To run with the touchscreen system you need to put this in a folder which I will assume is /home/pi/picframe_data then run it with

ExecStart=/usr/bin/python3 /home/pi/picframe_data/touchscreen_start.py /home/pi/picframe_data/config/configuration.yaml

In the above case the code below would be in file /home/pi/picframe_data/touchscreen_start.py

import logging
import sys
import time
import threading

import pi3d

from picframe import model, viewer_display, controller, interface_kbd, interface_http, __version__

LONG_PRESS = 5.0

def looper(c, mouse):
    keep_running = True
    button_down_tm = time.time() + 1000000.0
    while keep_running:
        buttons = mouse.button_status()
        tm = time.time()
        if buttons == mouse.LEFT_BUTTON: # button is down
            if tm < button_down_tm: # just pressed this loop
                button_down_tm = tm # remember time pressed
            elif (tm - button_down_tm) > LONG_PRESS: # shutdown
                c.stop()
                keep_running = False
        elif tm > button_down_tm: # button up event
            (mx, _my) = mouse.position()
            if mx < 0:
                c.back()
            else:
                c.next()
            button_down_tm = tm + 1000000.0
        time.sleep(0.1)

def main():
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)
    logger = logging.getLogger("start.py")
    logger.info('starting %s', sys.argv)

    if len(sys.argv) > 1:
        m = model.Model(sys.argv[1])
    else:
        m = model.Model()

    v = viewer_display.ViewerDisplay(m.get_viewer_config())
    c = controller.Controller(m, v)
    c.start()

    mqtt_config = m.get_mqtt_config()
    if mqtt_config['use_mqtt']:
        from picframe import interface_mqtt
        mqtt = interface_mqtt.InterfaceMQTT(c, mqtt_config)
        mqtt.start()

    model_config = m.get_model_config()

    mouse = pi3d.Mouse()
    mouse.start()
    t = threading.Thread(target=looper, args=(c, mouse))
    t.start()

    c.loop()

if __name__=="__main__": 
    main()
paytah232 commented 3 years ago

Hi Paddy, I reinstalled using wolfgangs instructions. I ran your code as above and got this on the command line:

I had to create the service under the root user for some reason but it runs. It was hard for me to tell if the system is working or not as it seems to be quite laggy. I added some print statements to your code as below so I could check the presses were registering:

if buttons == mouse.LEFT_BUTTON: # button is down
            if tm < button_down_tm: # just pressed this loop
                button_down_tm = tm # remember time pressed
                print("button down")
            elif (tm - button_down_tm) > LONG_PRESS: # shutdown
                print("long press")
                c.stop()
                keep_running = False
        elif tm > button_down_tm: # button up event
            (mx, _my) = mouse.position()
            if mx < 0:
                print("back")
                c.back()
            else:
                print("next")
                c.next()
            button_down_tm = tm + 1000000.0
        time.sleep(0.1)

The results were as follows:

python3 /home/pi/picframe_data/touchscreen_start.py
INFO:start.py:starting ['/home/pi/picframe_data/touchscreen_start.py']
INFO:model.Model:Open config file: /home/pi/picframe_data/config/configuration.yaml:
button down
next
button down
next
button down
next
button down
next
button down
next
button down
next
button down
next
button down
long press

So I am able to see that the touchscreen is detecting presses, however no matter where I press I only ever get a next click. Long press is possible, but doesn't work and cause the system to freeze. I was also unable to tell if the next presses actually worked, because it wasn't like I could tell the images were switching straight away. Thoughts?

paddywwoof commented 3 years ago

I'm out at moment but realize I should have checked it a bit more! Try printing ("next", mx) you might need to compare with display width / 2

paddywwoof commented 3 years ago

Peter, back now. The code I posted needs a couple of extra lines i.e.

import logging
import sys
import time
import threading
sys.path.insert(1, "/home/patrick/python/pi3d")
import pi3d

from picframe import model, viewer_display, controller, interface_kbd, interface_http, __version__

LONG_PRESS = 5.0

def looper(c, mouse):
    keep_running = True
    button_down_tm = time.time() + 1000000.0
    # This is hacking into "private" variables so really not ideal
    # if this functionality set up correctly this would be returned by a method
    MID = c._Controller__viewer._ViewerDisplay__display.width // 2 # <<<<<<<<<< find mid point
    while keep_running:
        buttons = mouse.button_status()
        tm = time.time()
        if buttons == mouse.LEFT_BUTTON: # button is down
            if tm < button_down_tm: # just pressed this loop
                button_down_tm = tm # remember time pressed
            elif (tm - button_down_tm) > LONG_PRESS: # shutdown
                c.stop()
                keep_running = False
        elif tm > button_down_tm: # button up event
            (mx, _my) = mouse.position()
            if mx < MID: # <<<<<<<<<<<<<<<<<<<<<<< if left of mid point
                c.back()
            else:
                c.next()
            button_down_tm = tm + 1000000.0
        time.sleep(0.1)

def main():
    logging.basicConfig(stream=sys.stdout, level=logging.INFO)
    logger = logging.getLogger("start.py")
    logger.info('starting %s', sys.argv)

    if len(sys.argv) > 1:
        m = model.Model(sys.argv[1])
    else:
        m = model.Model()

    v = viewer_display.ViewerDisplay(m.get_viewer_config())
    c = controller.Controller(m, v)
    c.start()

    mqtt_config = m.get_mqtt_config()
    if mqtt_config['use_mqtt']:
        from picframe import interface_mqtt
        mqtt = interface_mqtt.InterfaceMQTT(c, mqtt_config)
        mqtt.start()

    model_config = m.get_model_config()

    mouse = pi3d.Mouse(restrict=True) #<<<<<<<<<<<<<<<<<<<<<< restrict (poss not relevant for touch screens but better restricted)
    mouse.start()
    t = threading.Thread(target=looper, args=(c, mouse))
    t.start()

    c.loop()

if __name__=="__main__": 
    main()

Anyway, well done for getting the new code set up and working - I hope it wasn't too much of a trauma!

Paddy

PS having to run the service as root doesn't sound good - unless you are running on Pi4 in which case it's necessary. Often that happens if a dependency was installed as root. Can you run it from the command line via ssh?

The hanging after long press might be because you have http or keyboard enabled (if that is the case try without - I will try to figure out how to control the shutdown of all the various loops so it doesn't hang)

PPS when you try to start it using systemctl and it doesn't work you can run journalctl afterwards and it might give you some specific errors so you know exactly what went wrong.