added my Recipes
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
SUMMARY = "Add support of 3d Cube application on Demo Launcher"
|
||||
HOMEPAGE = "wiki.st.com"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
|
||||
|
||||
DEPENDS = "weston-cube demo-launcher"
|
||||
|
||||
PV = "3.0"
|
||||
SRC_URI = " \
|
||||
file://100-3d-cube.yaml \
|
||||
file://101-3d-cube-shader.yaml \
|
||||
file://105-3d-cube-picture-shader.yaml \
|
||||
file://110-3d-cube-video.yaml \
|
||||
file://111-3d-cube-video-shader.yaml \
|
||||
file://115-3d_cube_camera.yaml \
|
||||
file://116-3d_cube_camera_shader.yaml \
|
||||
file://120-3d-cube-pictures-shader.yaml \
|
||||
file://launch_cube_3D_1_picture_shader.sh \
|
||||
file://launch_cube_3D_3_pictures_shader.sh \
|
||||
file://launch_cube_3D_camera.sh \
|
||||
file://launch_cube_3D_camera_shader.sh \
|
||||
file://launch_cube_3D_color.sh \
|
||||
file://launch_cube_3D_color_shader.sh \
|
||||
file://launch_cube_3D_video.sh \
|
||||
file://launch_cube_3D_video_shader.sh \
|
||||
file://ST153_cube_purple.png \
|
||||
\
|
||||
file://040-3d_cube.yaml \
|
||||
file://launch_cube_3D.sh \
|
||||
"
|
||||
|
||||
do_configure[noexec] = "1"
|
||||
do_compile[noexec] = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${prefix}/local/demo/application/3d-cube/bin
|
||||
install -d ${D}${prefix}/local/demo/application/3d-cube/pictures
|
||||
install -d ${D}${prefix}/local/demo/application/3d-cube-extra/bin
|
||||
install -d ${D}${prefix}/local/demo/application/3d-cube-extra/pictures
|
||||
|
||||
# install yaml file
|
||||
install -m 0644 ${WORKDIR}/*.yaml ${D}${prefix}/local/demo/application/
|
||||
# install bin
|
||||
install -m 0755 ${WORKDIR}/*.sh ${D}${prefix}/local/demo/application/3d-cube-extra/bin
|
||||
install -m 0755 ${WORKDIR}/launch_cube_3D.sh ${D}${prefix}/local/demo/application/3d-cube/bin
|
||||
|
||||
# install pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/3d-cube-extra/pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/3d-cube/pictures
|
||||
}
|
||||
|
||||
PACKAGES += "${PN}-extra"
|
||||
FILES:${PN} = " \
|
||||
${prefix}/local/demo/application/3d-cube \
|
||||
${prefix}/local/demo/application/040-3d_cube.yaml \
|
||||
"
|
||||
RDEPENDS:${PN} = "weston-cube demo-launcher"
|
||||
|
||||
FILES:${PN}-extra = " \
|
||||
${prefix}/local/demo/application/3d-cube-extra \
|
||||
${prefix}/local/demo/application/100-3d-cube.yaml \
|
||||
${prefix}/local/demo/application/101-3d-cube-shader.yaml \
|
||||
${prefix}/local/demo/application/105-3d-cube-picture-shader.yaml \
|
||||
${prefix}/local/demo/application/110-3d-cube-video.yaml \
|
||||
${prefix}/local/demo/application/111-3d-cube-video-shader.yaml \
|
||||
${prefix}/local/demo/application/115-3d_cube_camera.yaml \
|
||||
${prefix}/local/demo/application/116-3d_cube_camera_shader.yaml \
|
||||
${prefix}/local/demo/application/120-3d-cube-pictures-shader.yaml \
|
||||
"
|
||||
RDEPENDS:${PN}-extra = "${PN} weston-cube demo-launcher"
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Pict
|
||||
Description: GPU
|
||||
Icon: application/3d-cube/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube/bin/launch_cube_3D.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Color
|
||||
Description: GPU
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_color.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Color
|
||||
Description: GPU Shader
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_color_shader.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Pict
|
||||
Description: GPU shader
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_1_picture_shader.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Video
|
||||
Description: GPU
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_video.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Video
|
||||
Description: GPU shader
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_video_shader.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Cam
|
||||
Description: GPU
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_camera.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Cam
|
||||
Description: GPU & shader
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_camera_shader.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: 3D Picts
|
||||
Description: GPU shader
|
||||
Icon: application/3d-cube-extra/pictures/ST153_cube_purple.png
|
||||
Board:
|
||||
List: stm32mp157
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
File: /dev/galcore
|
||||
Msg_false: No GCNANO GPU STACK capabilities to run 3D GPU demo
|
||||
Start: application/3d-cube-extra/bin/launch_cube_3D_3_pictures_shader.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
# with one picture
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -1 /usr/local/demo/pictures/ST20578_Label_OpenSTlinux_V.png -f
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -1 /usr/local/demo/pictures/ST20578_Label_OpenSTlinux_V.png -f -a
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -3 /usr/local/demo/pictures/ST13028_Linux_picto_13.png /usr/local/demo/pictures/ST4439_ST_logo.png /usr/local/demo/pictures/ST20578_Label_OpenSTlinux_V.png -f -a
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
if v4l2-ctl -d /dev/video0 -D > /dev/null 2>&1
|
||||
then
|
||||
printf "Video present and "
|
||||
if fuser /dev/video0 > /dev/null 2>&1
|
||||
then
|
||||
printf '%s\n' "device in use"
|
||||
else
|
||||
printf '%s\n' "device available"
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -v /dev/video0 -f
|
||||
fi
|
||||
else
|
||||
printf "Video not present\n"
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -3 /usr/local/demo/pictures/ST13028_Linux_picto_13.png /usr/local/demo/pictures/ST4439_ST_logo.png /usr/local/demo/pictures/ST20578_Label_OpenSTlinux_V.png -f
|
||||
fi
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
if v4l2-ctl -d /dev/video0 -D > /dev/null 2>&1
|
||||
then
|
||||
printf "Video present and "
|
||||
if fuser /dev/video0 > /dev/null 2>&1
|
||||
then
|
||||
printf '%s\n' "device in use"
|
||||
else
|
||||
printf '%s\n' "device available"
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -v /dev/video0 -f -a
|
||||
fi
|
||||
else
|
||||
printf "Video not present\n"
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -3 /usr/local/demo/pictures/ST13028_Linux_picto_13.png /usr/local/demo/pictures/ST4439_ST_logo.png /usr/local/demo/pictures/ST20578_Label_OpenSTlinux_V.png -f -a
|
||||
fi
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -f
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex -f -a
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex --video=/usr/local/demo/media/ST2297_visionv3.webm -f
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
/usr/local/demo/bin/weston-st-egl-cube-tex --video=/usr/local/demo/media/ST2297_visionv3.webm -f -a
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
SUMMARY = "Add support of audio bluetooth speaker on Demo Launcher"
|
||||
HOMEPAGE = "wiki.st.com"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
|
||||
|
||||
DEPENDS = "demo-launcher"
|
||||
|
||||
PV = "2.1"
|
||||
|
||||
SRC_URI = " \
|
||||
file://060-bluetooth_audio_output.yaml \
|
||||
file://bluetooth_audio.py \
|
||||
file://wrap_blctl.py \
|
||||
file://__init__.py \
|
||||
file://ST11012_bluetooth_speaker_light_green.png \
|
||||
file://check_ble.sh \
|
||||
"
|
||||
|
||||
do_configure[noexec] = "1"
|
||||
do_compile[noexec] = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${prefix}/local/demo/application/bluetooth/bin
|
||||
install -d ${D}${prefix}/local/demo/application/bluetooth/pictures
|
||||
|
||||
# install yaml file
|
||||
install -m 0644 ${WORKDIR}/*.yaml ${D}${prefix}/local/demo/application/
|
||||
# install pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/bluetooth/pictures
|
||||
# python script
|
||||
install -m 0755 ${WORKDIR}/*.py ${D}${prefix}/local/demo/application/bluetooth/
|
||||
# install check script
|
||||
install -m 0755 ${WORKDIR}/*.sh ${D}${prefix}/local/demo/application/bluetooth/bin/
|
||||
}
|
||||
RDEPENDS:${PN} += "python3-core python3-pexpect python3-pickle python3-pygobject gtk+3 demo-launcher"
|
||||
FILES:${PN} += "${prefix}/local/demo/application/"
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: Bluetooth
|
||||
Description: speaker
|
||||
Icon: application/bluetooth/pictures/ST11012_bluetooth_speaker_light_green.png
|
||||
Type: python
|
||||
Board:
|
||||
List: all
|
||||
Python:
|
||||
Exist:
|
||||
Command: /usr/local/demo/application/bluetooth/bin/check_ble.sh
|
||||
Msg_false: Please connect a bluetooth controller on the board
|
||||
Module: application.bluetooth.bluetooth_audio
|
||||
Action:
|
||||
button_release_event: python_start
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1 @@
|
||||
#print('Importing bluetooth __init__')
|
||||
@@ -0,0 +1,596 @@
|
||||
#!/usr/bin/python3
|
||||
# Copyright (c) 2019 STMicroelectronics. All rights reserved.
|
||||
#
|
||||
# This software component is licensed by ST under BSD 3-Clause license,
|
||||
# the "License"; You may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at:
|
||||
# opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
|
||||
import re
|
||||
import os
|
||||
import subprocess
|
||||
import pexpect
|
||||
from time import sleep, time
|
||||
|
||||
try:
|
||||
from application.bluetooth.wrap_blctl import wrapper_blctl as Bluetoothctl
|
||||
except ModuleNotFoundError:
|
||||
from wrap_blctl import wrapper_blctl as Bluetoothctl
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
SUBMODULE_PATH = "application/bluetooth"
|
||||
DEMO_PATH = "/usr/local/demo"
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
ICON_SIZE_1080 = 260
|
||||
ICON_SIZE_720 = 180
|
||||
ICON_SIZE_480 = 128
|
||||
ICON_SIZE_272 = 48
|
||||
|
||||
TREELIST_HEIGHT_1080 = 500
|
||||
TREELIST_HEIGHT_720 = 400
|
||||
TREELIST_HEIGHT_480 = 160
|
||||
TREELIST_HEIGHT_272 = 68
|
||||
|
||||
# return format:
|
||||
# [ icon_size, font_size, treelist_height, button_height ]
|
||||
SIZES_ID_ICON_SIZE = 0
|
||||
SIZES_ID_FONT_SIZE = 1
|
||||
SIZES_ID_TREELIST_HEIGHT = 2
|
||||
SIZES_ID_BUTTON_HEIGHT = 3
|
||||
def get_sizes_from_screen_size(width, height):
|
||||
minsize = min(width, height)
|
||||
icon_size = None
|
||||
font_size = None
|
||||
treelist_height = None
|
||||
button_height = None
|
||||
if minsize == 720:
|
||||
icon_size = ICON_SIZE_720
|
||||
font_size = 25
|
||||
treelist_height = TREELIST_HEIGHT_720
|
||||
button_height = 60
|
||||
elif minsize == 480:
|
||||
icon_size = ICON_SIZE_480
|
||||
font_size = 20
|
||||
treelist_height = TREELIST_HEIGHT_480
|
||||
button_height = 60
|
||||
elif minsize == 272:
|
||||
icon_size = ICON_SIZE_272
|
||||
font_size = 15
|
||||
treelist_height = TREELIST_HEIGHT_272
|
||||
button_height = 25
|
||||
elif minsize == 600:
|
||||
icon_size = ICON_SIZE_720
|
||||
font_size = 15
|
||||
treelist_height = TREELIST_HEIGHT_720
|
||||
button_height = 60
|
||||
elif minsize >= 1080:
|
||||
icon_size = ICON_SIZE_1080
|
||||
font_size = 32
|
||||
treelist_height = TREELIST_HEIGHT_1080
|
||||
button_height = 80
|
||||
return [icon_size, font_size, treelist_height, button_height]
|
||||
|
||||
def get_treelist_height_from_screen_size(width, height):
|
||||
minsize = min(width, height)
|
||||
if minsize == 720:
|
||||
return TREELIST_HEIGHT_720
|
||||
elif minsize == 480:
|
||||
return TREELIST_HEIGHT_480
|
||||
elif minsize == 272:
|
||||
return TREELIST_HEIGHT_272
|
||||
elif minsize == 600:
|
||||
return ICON_SIZE_1080
|
||||
elif minsize >= 1080:
|
||||
return ICON_SIZE_1080
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
SCAN_DURATION_IN_S = 15
|
||||
|
||||
regexps_audio = [
|
||||
re.compile(r"00001108-(?P<Headset>.+)$"),
|
||||
re.compile(r"0000110b-(?P<AudioSink>.+)$"),
|
||||
]
|
||||
|
||||
re_connected = re.compile(r"Connected:(?P<Connected>.+)$")
|
||||
|
||||
re_paired = re.compile(r"Paired:(?P<Paired>.+)$")
|
||||
|
||||
Item_info_dev = ['Headset', 'AudioSink', 'Connected', 'Paired']
|
||||
|
||||
regexps_devinfo = [
|
||||
re.compile(r"00001108-(?P<Headset>.+)$"),
|
||||
re.compile(r"0000110b-(?P<AudioSink>.+)$"),
|
||||
re.compile(r"Connected:(?P<Connected>.+)$"),
|
||||
re.compile(r"Paired:(?P<Paired>.+)$"),
|
||||
]
|
||||
########################################
|
||||
#pactl (pulseaudio controller) wrapper
|
||||
########################################
|
||||
#for parse_sinks
|
||||
re_sink = re.compile(r"^Sink #(?P<Ident>.+)$")
|
||||
re_prop_sink = [
|
||||
re.compile(r"State:(?P<State>.+)$"),
|
||||
re.compile(r"Description:\s+(?P<Name>.+)$")
|
||||
]
|
||||
|
||||
#for parse_streams
|
||||
re_stream = re.compile(r"^Sink Input #(?P<Ident>.+)$")
|
||||
re_prop_stream = [
|
||||
re.compile(r"Sink:\s+(?P<Sink>.+)$"),
|
||||
re.compile(r"media\.name\s=\s(?P<Name>.+)$")
|
||||
]
|
||||
# id_str : ident of the stream, id_sink : ident of the sink
|
||||
def audiosink_set(id_str, id_sink):
|
||||
print("audiosink_set ")
|
||||
#print("id_str : %d", id_str)
|
||||
#print("id_sink : %d", id_sink)
|
||||
cmd = ["/usr/bin/pactl", "move-sink-input", id_str, id_sink]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res = proc.stdout.read().decode('utf-8')
|
||||
return res
|
||||
|
||||
def scan_streams():
|
||||
cmd = ["/usr/bin/pactl", "list", "sink-inputs"]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res = proc.stdout.read().decode('utf-8')
|
||||
return res
|
||||
|
||||
def parse_streams(streams):
|
||||
streams_lines = streams.split('\n')
|
||||
l_streams = []
|
||||
for line in streams_lines:
|
||||
line = line.strip()
|
||||
elt = re_stream.search(line)
|
||||
if elt is not None:
|
||||
l_streams.append(elt.groupdict())
|
||||
continue
|
||||
for reg in re_prop_stream:
|
||||
res = reg.search(line)
|
||||
if res is not None:
|
||||
l_streams[-1].update(res.groupdict())
|
||||
return l_streams
|
||||
|
||||
|
||||
def scan_sinks():
|
||||
cmd = ["/usr/bin/pactl", "list", "sinks"]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res = proc.stdout.read().decode('utf-8')
|
||||
return res
|
||||
|
||||
def parse_sinks(sinks):
|
||||
sinks_lines=sinks.split('\n')
|
||||
l_sinks =[]
|
||||
for line in sinks_lines:
|
||||
line = line.strip()
|
||||
elt = re_sink.search(line)
|
||||
if elt is not None:
|
||||
l_sinks.append(elt.groupdict())
|
||||
continue
|
||||
for reg in re_prop_sink:
|
||||
res = reg.search(line)
|
||||
if res is not None:
|
||||
l_sinks[-1].update(res.groupdict())
|
||||
return l_sinks
|
||||
|
||||
|
||||
|
||||
def status_playback(self):
|
||||
sink_ident = []
|
||||
stream_ident = None
|
||||
|
||||
list_sinks = scan_sinks()
|
||||
sinks = parse_sinks(list_sinks)
|
||||
#print("refresh label_audio\n")
|
||||
#print(sinks)
|
||||
mess_bt = ""
|
||||
if sinks != []:
|
||||
for sk in sinks:
|
||||
for bt_dev_conn in self.list_dev_connect:
|
||||
if sk['Name'] == bt_dev_conn['name']:
|
||||
if mess_bt != "":
|
||||
mess_bt = mess_bt + "\n"
|
||||
mess_bt = mess_bt + "The audio BT device " + sk['Name'] + " is connected"
|
||||
sink_ident.append({'name': sk['Name'], 'ident': sk['Ident']})
|
||||
|
||||
if mess_bt == "":
|
||||
mess_bt = "Device not connected"
|
||||
|
||||
self.label_audio.set_markup("<span font='20' color='#000000'>%s</span>" % mess_bt)
|
||||
self.label_audio.set_justify(Gtk.Justification.LEFT)
|
||||
self.label_audio.set_line_wrap(True)
|
||||
return [stream_ident, sink_ident]
|
||||
|
||||
|
||||
def get_device_info(bl, macadr):
|
||||
#print("get_device_info")
|
||||
info_dev = bl.blctl_info(macadr)
|
||||
dict_info = {}
|
||||
for elt in Item_info_dev:
|
||||
dict_info[elt] = ''
|
||||
for reelt in regexps_devinfo:
|
||||
for elt in info_dev:
|
||||
result = reelt.search(elt)
|
||||
if result is not None:
|
||||
dict_info.update(result.groupdict())
|
||||
break
|
||||
return(dict_info)
|
||||
|
||||
|
||||
def list_devices(self, paired = False):
|
||||
#print("list_devices")
|
||||
if self.locked_devices == False:
|
||||
self.locked_devices = True
|
||||
self.bluetooth_liststore.clear()
|
||||
self.current_devs=[]
|
||||
i=0
|
||||
if paired == True:
|
||||
devs = self.bl.blctl_paired_devices()
|
||||
else:
|
||||
devs = self.bl.blctl_devices()
|
||||
for elt in devs:
|
||||
elt_info = get_device_info(self.bl, elt['mac_address'])
|
||||
#print("name===" , elt['name'].encode('utf-8').strip())
|
||||
if elt['name'] == "RSSI is nil":
|
||||
continue
|
||||
if elt['name'] == "TxPower is nil":
|
||||
continue
|
||||
#do not list device without real name
|
||||
if elt['mac_address'].replace(':','') != elt['name'].replace('-',''):
|
||||
i=i+1
|
||||
self.current_devs.append(elt['mac_address'])
|
||||
#print(elt_info)
|
||||
l_elt = []
|
||||
l_elt.append(i)
|
||||
l_elt.append(elt['name'])
|
||||
l_elt.append(elt_info['Connected'])
|
||||
if elt_info['Headset'] != '' or elt_info['AudioSink'] != '':
|
||||
l_elt.append('yes')
|
||||
else:
|
||||
l_elt.append('no')
|
||||
|
||||
if elt_info['Connected'] == " yes":
|
||||
if elt not in self.list_dev_connect:
|
||||
self.list_dev_connect.insert(0,elt)
|
||||
self.bl.set_prompt(elt['name'])
|
||||
self.bluetooth_liststore.append(l_elt)
|
||||
|
||||
self.locked_devices = False
|
||||
|
||||
|
||||
def device_connected(bl, macadr):
|
||||
info_dev=bl.blctl_info(macadr)
|
||||
if info_dev is not None:
|
||||
for elt in info_dev:
|
||||
result = re_connected.search(elt)
|
||||
if result is not None:
|
||||
l_info_dev = result.groupdict()
|
||||
if l_info_dev["Connected"] == " yes":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def device_paired(bl, macadr):
|
||||
info_dev=bl.blctl_info(macadr)
|
||||
if info_dev is not None:
|
||||
for elt in info_dev:
|
||||
result = re_paired.search(elt)
|
||||
if result is not None:
|
||||
l_info_dev = result.groupdict()
|
||||
if l_info_dev["Paired"] == " yes":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def device_audio(bl, macadr):
|
||||
info_dev=bl.blctl_info(macadr)
|
||||
for reelt in regexps_audio:
|
||||
for elt in info_dev:
|
||||
result = reelt.search(elt)
|
||||
if result is not None:
|
||||
return True
|
||||
return False
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
def gtk_style():
|
||||
css = b"""
|
||||
|
||||
.widget .grid .label {
|
||||
background-color: rgba (31%, 32%, 32%, 0.9);
|
||||
}
|
||||
.textview {
|
||||
color: gray;
|
||||
}
|
||||
.label {
|
||||
color: black;
|
||||
}
|
||||
.switch {
|
||||
min-height: 44px;
|
||||
}
|
||||
"""
|
||||
style_provider = Gtk.CssProvider()
|
||||
style_provider.load_from_data(css)
|
||||
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gdk.Screen.get_default(),
|
||||
style_provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
|
||||
|
||||
class BluetoothWindow(Gtk.Dialog):
|
||||
def __init__(self, parent):
|
||||
Gtk.Dialog.__init__(self, "Wifi", parent, 0)
|
||||
self.maximize()
|
||||
self.set_decorated(False)
|
||||
|
||||
gtk_style()
|
||||
try:
|
||||
display = Gdk.Display.get_default()
|
||||
monitor = display.get_primary_monitor()
|
||||
geometry = monitor.get_geometry()
|
||||
scale_factor = monitor.get_scale_factor()
|
||||
self.screen_width = scale_factor * geometry.width
|
||||
self.screen_height = scale_factor * geometry.height
|
||||
except:
|
||||
self.screen_width = self.get_screen().get_width()
|
||||
self.screen_height = self.get_screen().get_height()
|
||||
self.treelist_height = get_treelist_height_from_screen_size(self.screen_width, self.screen_height)
|
||||
sizes = get_sizes_from_screen_size(self.screen_width, self.screen_height)
|
||||
self.font_size = sizes[SIZES_ID_FONT_SIZE]
|
||||
self.button_height = sizes[SIZES_ID_BUTTON_HEIGHT]
|
||||
|
||||
self.connect("button-release-event", self.on_page_press_event)
|
||||
mainvbox = self.get_content_area()
|
||||
|
||||
self.dev_selected = {'mac_address':'', 'name':''}
|
||||
self.audio_bt_sink = []
|
||||
self.list_dev_connect = []
|
||||
self.current_devs = []
|
||||
self.locked_devices = False
|
||||
self.scan_done = False
|
||||
self.previous_click_time=0
|
||||
|
||||
self.page_bluetooth = Gtk.VBox()
|
||||
self.page_bluetooth.set_border_width(15)
|
||||
|
||||
self.title = Gtk.Label()
|
||||
self.title.set_markup("<span font='%d' color='#00000000'>Connect bluetooth headset</span>" % (self.font_size+5))
|
||||
self.page_bluetooth.add(self.title)
|
||||
|
||||
self.ButtonBox = Gtk.HBox(homogeneous=True)
|
||||
|
||||
self.lb_button_scan = Gtk.Label()
|
||||
self.lb_button_scan.set_markup("<span font='%d'>start scan</span>" % self.font_size)
|
||||
self.button_scan = Gtk.Button()
|
||||
self.button_scan.set_property("height-request", self.button_height)
|
||||
self.button_scan.add(self.lb_button_scan)
|
||||
self.button_scan.connect("clicked", self.on_selection_scan_clicked)
|
||||
self.ButtonBox.add(self.button_scan)
|
||||
|
||||
self.lb_button_connect = Gtk.Label()
|
||||
self.lb_button_connect.set_markup("<span font='%d' color='#88888888'>connect</span>" % self.font_size)
|
||||
self.button_connect = Gtk.Button()
|
||||
self.button_connect.add(self.lb_button_connect)
|
||||
self.button_connect.connect("clicked", self.on_selection_connect_clicked)
|
||||
self.ButtonBox.add(self.button_connect)
|
||||
|
||||
self.page_bluetooth.add(self.ButtonBox)
|
||||
|
||||
self.progress_vbox = Gtk.VBox()
|
||||
self.scan_progress = Gtk.ProgressBar()
|
||||
self.scan_progress.set_fraction(0.0)
|
||||
self.progress_vbox.pack_start(self.scan_progress, False, False, 3)
|
||||
self.page_bluetooth.add(self.progress_vbox)
|
||||
|
||||
self.tree_list_vbox = Gtk.VBox(homogeneous=True)
|
||||
|
||||
self.bluetooth_liststore = Gtk.ListStore(int, str, str, str)
|
||||
self.bluetooth_treeview = Gtk.TreeView(self.bluetooth_liststore)
|
||||
|
||||
l_col = ["n°", "name", "connected", "Audio"]
|
||||
for i, column_title in enumerate(l_col):
|
||||
renderer = Gtk.CellRendererText()
|
||||
renderer.set_property('font', "%d" % self.font_size)
|
||||
column = Gtk.TreeViewColumn(column_title, renderer, text=i)
|
||||
self.bluetooth_treeview.append_column(column)
|
||||
self.bluetooth_treeview.get_selection().connect("changed", self.on_changed)
|
||||
|
||||
self.scroll_treelist = Gtk.ScrolledWindow()
|
||||
self.scroll_treelist.set_vexpand(False)
|
||||
self.scroll_treelist.set_hexpand(False)
|
||||
self.scroll_treelist.set_property("min-content-height", self.treelist_height)
|
||||
self.scroll_treelist.add(self.bluetooth_treeview)
|
||||
self.tree_list_vbox.pack_start(self.scroll_treelist, True, True, 3)
|
||||
|
||||
self.page_bluetooth.add(self.tree_list_vbox)
|
||||
|
||||
self.label_audio = Gtk.Label()
|
||||
self.label_audio.set_markup("<span font='%d' color='#FFFFFFFF'> </span>" % self.font_size)
|
||||
self.label_audio.set_justify(Gtk.Justification.LEFT)
|
||||
self.label_audio.set_line_wrap(True)
|
||||
self.page_bluetooth.add(self.label_audio)
|
||||
|
||||
mainvbox.pack_start(self.page_bluetooth, False, True, 3)
|
||||
self.show_all()
|
||||
|
||||
# enable bluetooth
|
||||
os.system('su -c \"hciconfig hci0 up\"')
|
||||
#self.bluetooth_state = os.system('hciconfig hci0 up')
|
||||
self.bl = Bluetoothctl()
|
||||
|
||||
list_devices(self, paired=True)
|
||||
self.audio_bt_sink = status_playback(self)
|
||||
|
||||
|
||||
def display_message(self, message):
|
||||
dialog = Gtk.Dialog("Error", self, 0, (Gtk.STOCK_OK, Gtk.ResponseType.OK))
|
||||
dialog.set_decorated(False)
|
||||
width, height = self.get_size()
|
||||
dialog.set_default_size(width, height)
|
||||
rgba = Gdk.RGBA(0.31, 0.32, 0.31, 0.8)
|
||||
dialog.override_background_color(0,rgba)
|
||||
|
||||
label0 = Gtk.Label() #for padding
|
||||
|
||||
label1 = Gtk.Label()
|
||||
label1.set_markup(message)
|
||||
label1.set_justify(Gtk.Justification.CENTER)
|
||||
label1.set_line_wrap(True)
|
||||
|
||||
label2 = Gtk.Label() #for padding
|
||||
|
||||
# Create a centering alignment object
|
||||
align = Gtk.Alignment()
|
||||
align.set(0.5, 0, 0, 0)
|
||||
|
||||
dialog.vbox.pack_start(label0, True, False, 0)
|
||||
dialog.vbox.pack_start(label1, True, True, 0)
|
||||
dialog.vbox.pack_start(align, True, True, 0)
|
||||
dialog.vbox.pack_start(label2, True, False, 0)
|
||||
|
||||
dialog.action_area.reparent(align)
|
||||
dialog.show_all()
|
||||
|
||||
dialog.run()
|
||||
print("INFO dialog closed")
|
||||
|
||||
dialog.destroy()
|
||||
|
||||
|
||||
def on_page_press_event(self, widget, event):
|
||||
self.click_time = time()
|
||||
#print(self.click_time - self.previous_click_time)
|
||||
# TODO : a fake click is observed, workaround hereafter
|
||||
if (self.click_time - self.previous_click_time) < 0.01:
|
||||
self.previous_click_time = self.click_time
|
||||
elif (self.click_time - self.previous_click_time) < 0.3:
|
||||
print ("BluetoothWindow double click : exit")
|
||||
self.bl.close()
|
||||
self.destroy()
|
||||
else:
|
||||
#print ("simple click")
|
||||
self.previous_click_time = self.click_time
|
||||
|
||||
|
||||
def delayed_status_playback(self, user_data):
|
||||
self.audio_bt_sink = status_playback(self)
|
||||
return False
|
||||
|
||||
def progress_timeout(self, user_data):
|
||||
new_val=self.scan_progress.get_fraction() + 0.01
|
||||
if new_val > 1:
|
||||
self.scan_progress.set_fraction(0.0)
|
||||
self.bl.blctl_scan_off()
|
||||
self.lb_button_scan.set_markup("<span font='%d'>start scan</span>" % self.font_size)
|
||||
self.scan_done = True
|
||||
self.update_display()
|
||||
return False
|
||||
|
||||
self.scan_progress.set_fraction(new_val)
|
||||
self.scan_progress.set_text(str(new_val*100) + " % completed")
|
||||
return True
|
||||
|
||||
def on_changed(self, selection):
|
||||
(model, iter) = selection.get_selected()
|
||||
#print("on_changed")
|
||||
if iter is not None:
|
||||
self.audio_bt_sink = status_playback(self)
|
||||
#print(self.audio_bt_sink)
|
||||
self.dev_selected.update({'mac_address':self.current_devs[model[iter][0]-1], 'name':model[iter][1]})
|
||||
if model[iter][2] == " yes":
|
||||
self.lb_button_connect.set_markup("<span font='%d'>disconnect</span>" % self.font_size)
|
||||
else:
|
||||
if self.label_audio.get_text() == "Device not connected":
|
||||
self.lb_button_connect.set_markup("<span font='%d'>connect</span>" % self.font_size)
|
||||
else:
|
||||
self.lb_button_connect.set_markup("<span font='%d' color='#88888888'>connect</span>" % self.font_size)
|
||||
return True
|
||||
|
||||
def connect_process(self, dev):
|
||||
if device_connected(self.bl, dev['mac_address']):
|
||||
self.lb_button_connect.set_markup("<span font='%d'>disconnect</span>" % self.font_size)
|
||||
self.update_display()
|
||||
else:
|
||||
connect_res=self.bl.blctl_connect(dev['mac_address'])
|
||||
if connect_res == True:
|
||||
self.lb_button_connect.set_markup("<span font='%d' color='#88888888'>disconnect</span>" % self.font_size)
|
||||
self.update_display()
|
||||
# refresh status_playback after 2,5s because pulseaudio takes some time to update its status
|
||||
timer_update_dev = GLib.timeout_add(2500, self.delayed_status_playback, None)
|
||||
#In some cases, 2.5s is still not enough
|
||||
timer_update_dev = GLib.timeout_add(4000, self.delayed_status_playback, None)
|
||||
|
||||
def on_selection_connect_clicked(self, widget):
|
||||
if self.dev_selected['mac_address'] != '':
|
||||
device = self.dev_selected
|
||||
if self.lb_button_connect.get_text() == "connect":
|
||||
if self.label_audio.get_text() == "Device not connected":
|
||||
self.bl.set_prompt(device['name'])
|
||||
if device_paired(self.bl, device['mac_address']) == False:
|
||||
pairing_res=self.bl.blctl_pair(device['mac_address'])
|
||||
if pairing_res == 0:
|
||||
self.bl.blctl_session.send("no\n")
|
||||
else:
|
||||
if pairing_res == 1:
|
||||
sleep(5)
|
||||
self.connect_process(device)
|
||||
else:
|
||||
self.connect_process(device)
|
||||
else:
|
||||
print("[WARNING] A BT device is already connected :\ndisconnect it before connecting a new device\n")
|
||||
self.display_message("<span font='15' color='#000000'>A BT device is already connected :\nPlease disconnect it before connecting a new device\n</span>")
|
||||
else:
|
||||
connect_res=self.bl.blctl_disconnect(device['mac_address'])
|
||||
self.lb_button_connect.set_markup("<span font='%d' color='#88888888'>connect</span>" % self.font_size)
|
||||
self.update_display()
|
||||
else:
|
||||
print("[WARNING] Select the BT device to connect\n")
|
||||
self.display_message("<span font='15' color='#000000'>Please select a device in the list\n</span>")
|
||||
|
||||
def on_selection_scan_clicked(self, widget):
|
||||
if self.lb_button_scan.get_text() == "start scan":
|
||||
self.bl.blctl_scan_on()
|
||||
timer_scan = GLib.timeout_add(SCAN_DURATION_IN_S * 10, self.progress_timeout, None)
|
||||
self.lb_button_scan.set_markup("<span font='%d'>scan progress</span>"% self.font_size)
|
||||
|
||||
def update_display(self):
|
||||
if (self.scan_done == True):
|
||||
list_devices(self, False)
|
||||
else:
|
||||
list_devices(self, True)
|
||||
self.dev_selected.update({'mac_address':'', 'name':''})
|
||||
self.audio_bt_sink = status_playback(self)
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
def create_subdialogwindow(parent):
|
||||
_window = BluetoothWindow(parent)
|
||||
_window.show_all()
|
||||
response = _window.run()
|
||||
_window.destroy()
|
||||
|
||||
|
||||
# -------------------------------------------------
|
||||
# -------------------------------------------------
|
||||
# test submodule
|
||||
class TestUIWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self, title="Test Launcher")
|
||||
create_subdialogwindow(self)
|
||||
self.show_all()
|
||||
|
||||
if __name__ == "__main__":
|
||||
win = TestUIWindow()
|
||||
win.connect("delete-event", Gtk.main_quit)
|
||||
win.show_all()
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
script -qc "su -c 'hciconfig hci0 up || echo ko > /tmp/ble'"
|
||||
|
||||
if [ -e /tmp/ble ]; then
|
||||
rm -f /tmp/ble
|
||||
exit 1;
|
||||
else
|
||||
exit 0;
|
||||
fi
|
||||
@@ -0,0 +1,196 @@
|
||||
import time
|
||||
import pexpect
|
||||
import sys
|
||||
import re
|
||||
import pickle
|
||||
|
||||
##############################
|
||||
# bluetoothctl tool wrapper
|
||||
##############################
|
||||
|
||||
__all__ = ["wrapper_blctl"]
|
||||
|
||||
|
||||
device = re.compile(r"Device\s(?P<mac_address>([0-9 A-F][0-9 A-F]:){5}[0-9 A-F][0-9 A-F])(?P<name>.+)$")
|
||||
|
||||
re_device_notvalid = [
|
||||
re.compile(r"CHG"),
|
||||
re.compile(r"NEW"),
|
||||
re.compile(r"DEL")
|
||||
]
|
||||
|
||||
def read_prompt():
|
||||
try:
|
||||
f = open('/tmp/list_prompt', 'rb')
|
||||
except IOError as e:
|
||||
print("Cant not open the file : /tmp/list_prompt\n")
|
||||
return None
|
||||
else:
|
||||
s = pickle.load(f)
|
||||
f.close()
|
||||
return s
|
||||
|
||||
def write_prompt(prt):
|
||||
with open('/tmp/list_prompt', 'wb') as f:
|
||||
pickle.dump(prt,f)
|
||||
|
||||
|
||||
class blctl_error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class wrapper_blctl:
|
||||
|
||||
def __init__(self):
|
||||
self.blctl_session = pexpect.spawn("bluetoothctl", echo = False, maxread = 3000)
|
||||
|
||||
#no prompt expected because a BT device can be connected automatically
|
||||
prompt_expect = self.blctl_session.expect([pexpect.EOF, pexpect.TIMEOUT], timeout = 1)
|
||||
str_out = str(self.blctl_session.before,"utf-8")
|
||||
l_out = str_out.split("\r\n")
|
||||
|
||||
self.prompt = read_prompt()
|
||||
if self.prompt == None:
|
||||
self.prompt= ["\[bluetooth\]", pexpect.EOF]
|
||||
#print(self.prompt)
|
||||
|
||||
#execute a bluetoothctl command and return the result as a list of lines
|
||||
#no status cmd expected
|
||||
def blctl_command(self, command, pause = 0):
|
||||
#print("blctl_command : " + command)
|
||||
self.blctl_session.send(command + "\n")
|
||||
time.sleep(pause)
|
||||
|
||||
prompt_expect = self.blctl_session.expect(self.prompt)
|
||||
|
||||
if (prompt_expect > (len(self.prompt) - 1) or (prompt_expect < 0)):
|
||||
raise blctl_error("The bluetoothctl command " + command + " failed")
|
||||
|
||||
str_output = str(self.blctl_session.before,"utf-8")
|
||||
output_array = str_output.split("\r\n")
|
||||
|
||||
return output_array
|
||||
|
||||
#execute a bluetoothctl command with status expected
|
||||
def blctl_command_with_status(self, command, status_expected, pause = 0):
|
||||
print("blctl_command_with_status : " + command + "\n")
|
||||
status = status_expected
|
||||
status.extend([pexpect.EOF])
|
||||
#print("prompt_status : %s\n", status)
|
||||
|
||||
self.blctl_session.send(command + "\n")
|
||||
time.sleep(pause)
|
||||
|
||||
res = self.blctl_session.expect(status)
|
||||
|
||||
return res
|
||||
|
||||
def close(self):
|
||||
write_prompt(self.prompt)
|
||||
self.blctl_session.close()
|
||||
|
||||
#build the list of bluetoothctl prompts
|
||||
def set_prompt(self, prompt):
|
||||
prpt = "\["+prompt+"\]"
|
||||
if prpt not in self.prompt:
|
||||
self.prompt.insert(0, prpt)
|
||||
|
||||
#bluetoothctl command : scan on
|
||||
def blctl_scan_on(self):
|
||||
try:
|
||||
cmd_res = self.blctl_command("scan on")
|
||||
except blctl_error as ex:
|
||||
print(ex)
|
||||
return None
|
||||
|
||||
#bluetoothctl command : scan off
|
||||
def blctl_scan_off(self):
|
||||
try:
|
||||
cmd_res = self.blctl_command("scan off")
|
||||
except blctl_error as ex:
|
||||
print(ex)
|
||||
return None
|
||||
|
||||
#make a dic (mac_address, name) from result of bluetoothctl command devices
|
||||
def parse_info(self, device_info):
|
||||
dev = {}
|
||||
info_isnot_valid = None
|
||||
for reg in re_device_notvalid:
|
||||
info_isnot_valid = reg.search(device_info)
|
||||
if info_isnot_valid is not None:
|
||||
break
|
||||
|
||||
if info_isnot_valid is None:
|
||||
result = device.search(device_info)
|
||||
if result is not None:
|
||||
dev = result.groupdict()
|
||||
name_tmp = dev['name'].strip()
|
||||
dev['name'] = name_tmp
|
||||
return dev
|
||||
|
||||
#bluetoothctl command : devices
|
||||
#return a list of dic {mac_address, name}
|
||||
def blctl_devices(self):
|
||||
try:
|
||||
cmd_res = self.blctl_command("devices")
|
||||
except blctl_error as ex:
|
||||
print(ex)
|
||||
return None
|
||||
else:
|
||||
list_devices = []
|
||||
for line in cmd_res:
|
||||
device = self.parse_info(line)
|
||||
if device:
|
||||
list_devices.append(device)
|
||||
|
||||
return list_devices
|
||||
|
||||
#bluetoothctl command : paired-devices
|
||||
#return a list of dic {mac_address, name}
|
||||
def blctl_paired_devices(self):
|
||||
try:
|
||||
cmd_res = self.blctl_command("paired-devices")
|
||||
except blctl_error as ex:
|
||||
print(ex)
|
||||
return None
|
||||
else:
|
||||
list_devices = []
|
||||
for line in cmd_res:
|
||||
device = self.parse_info(line)
|
||||
if device:
|
||||
list_devices.append(device)
|
||||
|
||||
return list_devices
|
||||
|
||||
#bluetoothctl command : info <mac_address>
|
||||
def blctl_info(self, mac_address):
|
||||
try:
|
||||
cmd_res = self.blctl_command("info " + mac_address)
|
||||
except blctl_error as ex:
|
||||
print(ex)
|
||||
return None
|
||||
else:
|
||||
return cmd_res
|
||||
|
||||
#bluetoothctl command : pair <mac_address>
|
||||
def blctl_pair(self, mac_address):
|
||||
cmd_res = self.blctl_command_with_status("pair " + mac_address, ["confirmation", "Pairing successful", "not available", "Failed to pair"], pause=4)
|
||||
return cmd_res
|
||||
|
||||
#bluetoothctl command : connect <mac_address>
|
||||
def blctl_connect(self, mac_address):
|
||||
cmd_res = self.blctl_command_with_status("connect " + mac_address, ["Failed to connect", "Connection successful"], pause=2)
|
||||
passed = True if cmd_res == 1 else False
|
||||
return passed
|
||||
|
||||
#bluetoothctl command : disconnect <mac_address>
|
||||
def blctl_disconnect(self, mac_address):
|
||||
cmd_res = self.blctl_command_with_status("disconnect " + mac_address, ["Failed to disconnect", "Successful disconnected"], pause=2)
|
||||
passed = True if cmd_res == 1 else False
|
||||
return passed
|
||||
|
||||
#bluetoothctl command : remove <mac_address>
|
||||
def blctl_remove(self, mac_address):
|
||||
cmd_res = self.blctl_command_with_status("remove " + mac_address, ["not available", "Failed to remove", "Device has been removed"], pause=3)
|
||||
passed = True if cmd_res == 2 else False
|
||||
return passed
|
||||
@@ -0,0 +1,38 @@
|
||||
SUMMARY = "Add support of camera preview on Demo Launcher"
|
||||
HOMEPAGE = "wiki.st.com"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
|
||||
|
||||
DEPENDS = "demo-launcher event-gtk-player wayland-utils"
|
||||
|
||||
PV = "2.0"
|
||||
|
||||
SRC_URI = " \
|
||||
file://launch_camera_preview.sh \
|
||||
file://stop_camera.sh \
|
||||
file://edge_InvertLuma.fs \
|
||||
file://ST1077_webcam_dark_blue.png \
|
||||
file://010-camera.yaml \
|
||||
file://check_camera_preview.sh \
|
||||
"
|
||||
|
||||
do_configure[noexec] = "1"
|
||||
do_compile[noexec] = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${prefix}/local/demo/application/camera/bin
|
||||
install -d ${D}${prefix}/local/demo/application/camera/pictures
|
||||
install -d ${D}${prefix}/local/demo/application/camera/shaders
|
||||
|
||||
# install yaml file
|
||||
install -m 0644 ${WORKDIR}/*.yaml ${D}${prefix}/local/demo/application/
|
||||
# install pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/camera/pictures
|
||||
# script
|
||||
install -m 0755 ${WORKDIR}/*.sh ${D}${prefix}/local/demo/application/camera/bin
|
||||
# shaders
|
||||
install -m 0644 ${WORKDIR}/*.fs ${D}${prefix}/local/demo/application/camera/shaders
|
||||
}
|
||||
|
||||
FILES:${PN} += "${prefix}/local/demo/application/"
|
||||
RDEPENDS:${PN} += "event-gtk-player demo-launcher"
|
||||
@@ -0,0 +1,17 @@
|
||||
Application:
|
||||
Name: Camera
|
||||
Description: preview
|
||||
Icon: application/camera/pictures/ST1077_webcam_dark_blue.png
|
||||
Board:
|
||||
List: all
|
||||
Type: script
|
||||
Script:
|
||||
Exist:
|
||||
Command: /usr/local/demo/application/camera/bin/check_camera_preview.sh
|
||||
Msg_false: Webcam or camera is not connected
|
||||
Start: application/camera/bin/launch_camera_preview.sh
|
||||
Action:
|
||||
button_release_event: script_management
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
@@ -0,0 +1,46 @@
|
||||
#!/bin/sh
|
||||
|
||||
is_dcmipp_present() {
|
||||
DCMIPP_PRESENT="NOTFOUND"
|
||||
# on disco board gc2145 or ov5640 camera can be present on csi connector
|
||||
for video in $(find /sys/class/video4linux -name "video*" -type l);
|
||||
do
|
||||
if [ "$(cat $video/name)" = "dcmipp_dump_capture" ]; then
|
||||
for sub in $(find /sys/class/video4linux -name "v4l-subdev*" -type l);
|
||||
do
|
||||
subdev_name=$(tr -d '\0' < $sub/name | awk '{print $1}')
|
||||
if [ "$subdev_name" = "gc2145" ] || [ "$subdev_name" = "ov5640" ]; then
|
||||
DCMIPP_PRESENT="FOUND"
|
||||
return
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_webcam_device() {
|
||||
WEBCAM_found="NOTFOUND"
|
||||
for video in $(find /sys/class/video4linux -name "video*" -type l | sort);
|
||||
do
|
||||
if [ ! "$(cat $video/name)" = "dcmipp_dump_capture" ]; then
|
||||
WEBCAM_found="FOUND"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ------------------------------
|
||||
# main
|
||||
# ------------------------------
|
||||
|
||||
# camera detection
|
||||
# detect if we have a gc2145 or ov5640 plugged and associated to dcmipp
|
||||
is_dcmipp_present
|
||||
if [ "$DCMIPP_PRESENT" = "FOUND" ]; then
|
||||
exit 0
|
||||
fi
|
||||
get_webcam_device
|
||||
if [ "$WEBCAM_found" = "FOUND" ]; then
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Original shader from: https://www.shadertoy.com/view/MdGXDy
|
||||
*
|
||||
* Automatically converted by st-to-gstsh script
|
||||
* See: https://github.com/jolivain/gst-shadertoy
|
||||
*/
|
||||
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
||||
// gst-glshader uniforms
|
||||
uniform float time;
|
||||
uniform float width;
|
||||
uniform float height;
|
||||
uniform sampler2D tex;
|
||||
|
||||
// shadertoy globals
|
||||
float iGlobalTime = 0.0;
|
||||
float iTime = 0.0;
|
||||
vec3 iResolution = vec3(0.0);
|
||||
vec3 iMouse = vec3(0.0);
|
||||
vec4 iDate = vec4(0.0);
|
||||
|
||||
#define iChannel0 tex
|
||||
#define texture(t,c) texture2D(t,c)
|
||||
#if (__VERSION__ < 300)
|
||||
# define textureLod(s, uv, l) texture2D(s, uv)
|
||||
#endif
|
||||
|
||||
// Protect gst-glshader names
|
||||
#define time gstemu_time
|
||||
#define width gstemu_width
|
||||
#define height gstemu_height
|
||||
|
||||
// --------[ Original ShaderToy begins here ]---------- //
|
||||
const float gamma = 2.2;
|
||||
|
||||
float gamma2linear( float v )
|
||||
{
|
||||
return pow( v, gamma );
|
||||
}
|
||||
|
||||
float linear2gamma( float v )
|
||||
{
|
||||
return pow( v, 1./gamma );
|
||||
}
|
||||
|
||||
float min3( float a, float b, float c )
|
||||
{
|
||||
return min( min( a, b ), c );
|
||||
}
|
||||
|
||||
float max3( float a, float b, float c )
|
||||
{
|
||||
return max( max( a, b ), c );
|
||||
}
|
||||
|
||||
vec3 rgb2hsv(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
vec3 convertRGBtoHSL( vec3 col )
|
||||
{
|
||||
float red = col.r;
|
||||
float green = col.g;
|
||||
float blue = col.b;
|
||||
|
||||
float minc = min3( col.r, col.g, col.b );
|
||||
float maxc = max3( col.r, col.g, col.b );
|
||||
float delta = maxc - minc;
|
||||
|
||||
float lum = (minc + maxc) * 0.5;
|
||||
float sat = 0.0;
|
||||
float hue = 0.0;
|
||||
|
||||
if (lum > 0.0 && lum < 1.0) {
|
||||
float mul = (lum < 0.5) ? (lum) : (1.0-lum);
|
||||
sat = delta / (mul * 2.0);
|
||||
}
|
||||
|
||||
vec3 masks = vec3(
|
||||
(maxc == red && maxc != green) ? 1.0 : 0.0,
|
||||
(maxc == green && maxc != blue) ? 1.0 : 0.0,
|
||||
(maxc == blue && maxc != red) ? 1.0 : 0.0
|
||||
);
|
||||
|
||||
vec3 adds = vec3(
|
||||
((green - blue ) / delta),
|
||||
2.0 + ((blue - red ) / delta),
|
||||
4.0 + ((red - green) / delta)
|
||||
);
|
||||
|
||||
float deltaGtz = (delta > 0.0) ? 1.0 : 0.0;
|
||||
|
||||
hue += dot( adds, masks );
|
||||
hue *= deltaGtz;
|
||||
hue /= 6.0;
|
||||
|
||||
if (hue < 0.0)
|
||||
hue += 1.0;
|
||||
|
||||
return vec3( hue, sat, lum );
|
||||
}
|
||||
|
||||
vec3 convertHSLtoRGB( vec3 col )
|
||||
{
|
||||
const float onethird = 1.0 / 3.0;
|
||||
const float twothird = 2.0 / 3.0;
|
||||
const float rcpsixth = 6.0;
|
||||
|
||||
float hue = col.x;
|
||||
float sat = col.y;
|
||||
float lum = col.z;
|
||||
|
||||
vec3 xt = vec3(
|
||||
rcpsixth * (hue - twothird),
|
||||
0.0,
|
||||
rcpsixth * (1.0 - hue)
|
||||
);
|
||||
|
||||
if (hue < twothird) {
|
||||
xt.r = 0.0;
|
||||
xt.g = rcpsixth * (twothird - hue);
|
||||
xt.b = rcpsixth * (hue - onethird);
|
||||
}
|
||||
|
||||
if (hue < onethird) {
|
||||
xt.r = rcpsixth * (onethird - hue);
|
||||
xt.g = rcpsixth * hue;
|
||||
xt.b = 0.0;
|
||||
}
|
||||
|
||||
xt = min( xt, 1.0 );
|
||||
|
||||
float sat2 = 2.0 * sat;
|
||||
float satinv = 1.0 - sat;
|
||||
float luminv = 1.0 - lum;
|
||||
float lum2m1 = (2.0 * lum) - 1.0;
|
||||
vec3 ct = (sat2 * xt) + satinv;
|
||||
|
||||
vec3 rgb;
|
||||
if (lum >= 0.5)
|
||||
rgb = (luminv * ct) + lum2m1;
|
||||
else rgb = lum * ct;
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec3 sample = texture( iChannel0, uv ).rgb;
|
||||
|
||||
vec3 s2 = convertRGBtoHSL( sample );
|
||||
|
||||
//s2.b = gamma2linear( s2.b );
|
||||
s2.b = ( s2.b * -1.0 ) + 1.0;
|
||||
//s2.b = linear2gamma( s2.b );
|
||||
|
||||
vec3 s3 = convertHSLtoRGB( s2 );
|
||||
fragColor = vec4(s3, 1.0);
|
||||
}
|
||||
// --------[ Original ShaderToy ends here ]---------- //
|
||||
|
||||
#undef time
|
||||
#undef width
|
||||
#undef height
|
||||
|
||||
void main(void)
|
||||
{
|
||||
iResolution = vec3(width, height, 0.0);
|
||||
iGlobalTime = time;
|
||||
iTime = time;
|
||||
iDate.w = time;
|
||||
|
||||
mainImage(gl_FragColor, gl_FragCoord.xy);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/bin/sh
|
||||
function print_debug() {
|
||||
echo "[exec]: $@"
|
||||
}
|
||||
|
||||
function pty_exec() {
|
||||
cmd=$1
|
||||
pty=$(tty > /dev/null 2>&1; echo $?)
|
||||
if [ $pty -eq 0 ]; then
|
||||
cmd=$(echo $cmd | sed "s#\"#'#g")
|
||||
event_cmd=$(echo /usr/local/demo/bin/touch-event-gtk-player -w $SCREEN_WIDTH -h $SCREEN_HEIGHT --graph \"$cmd\")
|
||||
eval $event_cmd > /dev/null 2>&1
|
||||
else
|
||||
# no pty
|
||||
echo "NO PTY"
|
||||
event_cmd=$(echo /usr/local/demo/bin/touch-event-gtk-player -w $SCREEN_WIDTH -h $SCREEN_HEIGHT --graph \'$cmd\')
|
||||
script -qc "$event_cmd" > /dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
is_dcmipp_present() {
|
||||
DCMIPP_SENSOR="NOTFOUND"
|
||||
# on disco board ov5640 camera can be present on csi connector
|
||||
for video in $(find /sys/class/video4linux -name "video*" -type l);
|
||||
do
|
||||
if [ "$(cat $video/name)" = "dcmipp_dump_capture" ]; then
|
||||
cd $video/device/
|
||||
mediadev=/dev/$(ls -d media*)
|
||||
cd -
|
||||
for sub in $(find /sys/class/video4linux -name "v4l-subdev*" -type l);
|
||||
do
|
||||
subdev_name=$(tr -d '\0' < $sub/name | awk '{print $1}')
|
||||
if [ "$subdev_name" = "gc2145" ] || [ "$subdev_name" = "ov5640" ]; then
|
||||
DCMIPP_SENSOR=$subdev_name
|
||||
V4L_DEVICE="device=/dev/$(basename $video)"
|
||||
sensorsubdev=$(tr -d '\0' < $sub/name)
|
||||
#bridge is connected to output of sensor (":0 [ENABLED" with media-ctl -p)
|
||||
bridgesubdev=$(media-ctl -d $mediadev -p -e "$sensorsubdev" | grep ":0 \[ENABLED" | awk -F\" '{print $2}')
|
||||
#interface is connected to input of postproc (":1 [ENABLED" with media-ctl -p)
|
||||
interfacesubdev=$(media-ctl -d $mediadev -p -e "dcmipp_dump_postproc" | grep ":1 \[ENABLED" | awk -F\" '{print $2}')
|
||||
if [ "$subdev_name" = "gc2145" ]; then
|
||||
sensorbuscode_constrain="BE"
|
||||
parallelbuscode="RGB565_2X8_BE"
|
||||
else
|
||||
sensorbuscode_constrain="LE"
|
||||
parallelbuscode="RGB565_2X8_LE"
|
||||
fi
|
||||
echo "media device: "$mediadev
|
||||
echo "video device: "$V4L_DEVICE
|
||||
echo "sensor subdev: " $sensorsubdev
|
||||
echo "bridge subdev: " $bridgesubdev
|
||||
echo "interface subdev: " $interfacesubdev
|
||||
|
||||
return
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
is_dcmi_present() {
|
||||
DCMI_SENSOR="NOTFOUND"
|
||||
# on disco board ov5640 camera can be present on // connector
|
||||
for video in $(find /sys/class/video4linux -name "video*" -type l);
|
||||
do
|
||||
if [ "$(cat $video/name)" = "stm32_dcmi" ]; then
|
||||
V4L_DEVICE="device=/dev/$(basename $video)"
|
||||
DCMI_SENSOR="$(basename $video)"
|
||||
echo "video DCMI device: "$V4L_DEVICE
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
get_webcam_device() {
|
||||
found="NOTFOUND"
|
||||
for video in $(find /sys/class/video4linux -name "video*" -type l | sort);
|
||||
do
|
||||
if [ "$(cat $video/name)" = "dcmipp_dump_capture" ]; then
|
||||
found="FOUND"
|
||||
else
|
||||
V4L_DEVICE="device=/dev/$(basename $video)"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# ------------------------------
|
||||
# main
|
||||
# ------------------------------
|
||||
|
||||
# graphic brackend detection
|
||||
if [ -f /etc/default/weston ] && $(grep "^OPTARGS" /etc/default/weston | grep -q "use-pixman" ) ;
|
||||
then
|
||||
echo "Without GPU"
|
||||
ADDONS="videoconvert ! queue !"
|
||||
else
|
||||
echo "With GPU"
|
||||
ADDONS=""
|
||||
fi
|
||||
|
||||
|
||||
# Detect size of screen
|
||||
SCREEN_WIDTH=$(wayland-info | grep logical_width | sed -r "s/logical_width: ([0-9]+),.*/\1/")
|
||||
SCREEN_HEIGHT=$(wayland-info | grep logical_width | sed -r "s/.*logical_height: ([0-9]+).*/\1/")
|
||||
|
||||
|
||||
# camera detection
|
||||
is_dcmipp_present
|
||||
if [ "$DCMIPP_SENSOR" != "NOTFOUND" ]; then
|
||||
WIDTH=640
|
||||
HEIGHT=480
|
||||
FPS=30
|
||||
|
||||
sensordev=$(media-ctl -d $mediadev -p -e "$sensorsubdev" | grep "node name" | awk -F\name '{print $2}')
|
||||
sensorbuscode=`v4l2-ctl --list-subdev-mbus-codes -d $sensordev | grep RGB565 | grep "$sensorbuscode_constrain" | awk -FMEDIA_BUS_FMT_ '{print $2}'| head -n 1`
|
||||
echo "sensor mbus-code: "$sensorbuscode
|
||||
print_debug media-ctl -d $mediadev --set-v4l2 "'$sensorsubdev':0[fmt:$sensorbuscode/${WIDTH}x${HEIGHT}@1/${FPS} field:none]"
|
||||
media-ctl -d $mediadev --set-v4l2 "'$sensorsubdev':0[fmt:$sensorbuscode/${WIDTH}x${HEIGHT}@1/${FPS} field:none]"
|
||||
print_debug media-ctl -d $mediadev --set-v4l2 "'$bridgesubdev':2[fmt:$sensorbuscode/${WIDTH}x${HEIGHT}]"
|
||||
media-ctl -d $mediadev --set-v4l2 "'$bridgesubdev':2[fmt:$sensorbuscode/${WIDTH}x${HEIGHT}]"
|
||||
print_debug media-ctl -d $mediadev --set-v4l2 "'$interfacesubdev':1[fmt:$parallelbuscode/${WIDTH}x${HEIGHT}]"
|
||||
media-ctl -d $mediadev --set-v4l2 "'$interfacesubdev':1[fmt:$parallelbuscode/${WIDTH}x${HEIGHT}]"
|
||||
print_debug media-ctl -d $mediadev --set-v4l2 "'dcmipp_dump_postproc':1[fmt:$parallelbuscode/${WIDTH}x${HEIGHT}]"
|
||||
media-ctl -d $mediadev --set-v4l2 "'dcmipp_dump_postproc':1[fmt:$parallelbuscode/${WIDTH}x${HEIGHT}]"
|
||||
V4L2_CAPS="video/x-raw, format=RGB16, width=$WIDTH, height=$HEIGHT"
|
||||
V4L_OPT=""
|
||||
|
||||
else
|
||||
is_dcmi_present
|
||||
if [ "$DCMI_SENSOR" != "NOTFOUND" ]; then
|
||||
COMPATIBLE_BOARD=$(cat /proc/device-tree/compatible | sed "s|st,|,|g" | cut -d ',' -f2)
|
||||
case $COMPATIBLE_BOARD in
|
||||
stm32mp15*)
|
||||
WIDTH=640
|
||||
HEIGHT=480
|
||||
;;
|
||||
*)
|
||||
WIDTH=640
|
||||
HEIGHT=480
|
||||
;;
|
||||
esac
|
||||
else
|
||||
get_webcam_device
|
||||
# suppose we have a webcam
|
||||
WIDTH=640
|
||||
HEIGHT=480
|
||||
fi
|
||||
|
||||
V4L2_CAPS="video/x-raw, width=$WIDTH, height=$HEIGHT"
|
||||
V4L_OPT="io-mode=4"
|
||||
v4l2-ctl --set-parm=30
|
||||
fi
|
||||
|
||||
|
||||
echo "Gstreamer graph:"
|
||||
GRAPH="v4l2src $V4L_DEVICE $V4L_OPT ! $V4L2_CAPS ! queue ! $ADDONS gtkwaylandsink name=gtkwsink"
|
||||
|
||||
echo " $GRAPH"
|
||||
pty_exec "$GRAPH"
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
#killall gst-launch-1.0
|
||||
killall touch-event-gtk-player
|
||||
@@ -0,0 +1,44 @@
|
||||
SUMMARY = "Add support of netdata/hotspot wifi on Demo Launcher"
|
||||
HOMEPAGE = "wiki.st.com"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
|
||||
|
||||
DEPENDS = "demo-launcher demo-hotspot-wifi qrenc"
|
||||
|
||||
PV = "2.0"
|
||||
|
||||
SRC_URI = " \
|
||||
file://000-netdata.yaml \
|
||||
file://build_qrcode.sh \
|
||||
file://__init__.py \
|
||||
file://netdata.py \
|
||||
file://netdata-icon-192x192.png \
|
||||
file://hostapd \
|
||||
file://wifi_start.sh \
|
||||
file://wifi_stop.sh \
|
||||
file://get_wlan_name.sh \
|
||||
file://get_ethernet_ip.sh \
|
||||
"
|
||||
|
||||
do_configure[noexec] = "1"
|
||||
do_compile[noexec] = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${prefix}/local/demo/application/netdata/bin
|
||||
install -d ${D}${prefix}/local/demo/application/netdata/pictures
|
||||
|
||||
# install yaml file
|
||||
install -m 0644 ${WORKDIR}/*.yaml ${D}${prefix}/local/demo/application/
|
||||
# install bin
|
||||
install -m 0755 ${WORKDIR}/*.sh ${D}${prefix}/local/demo/application/netdata/bin
|
||||
# install pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/netdata/pictures
|
||||
# python script
|
||||
install -m 0755 ${WORKDIR}/*.py ${D}${prefix}/local/demo/application/netdata/
|
||||
|
||||
# for wifi hotspot
|
||||
install -d ${D}${sysconfdir}/default
|
||||
install -m 0644 ${WORKDIR}/hostapd ${D}${sysconfdir}/default
|
||||
}
|
||||
RDEPENDS:${PN} += "python3-core python3-pygobject gtk+3 python3-threading demo-launcher demo-hotspot-wifi qrenc"
|
||||
FILES:${PN} += "${sysconfdir}/default ${prefix}/local/demo/application/"
|
||||
@@ -0,0 +1,14 @@
|
||||
Application:
|
||||
Name: netdata
|
||||
Description: perf monitor
|
||||
Icon: application/netdata/pictures/netdata-icon-192x192.png
|
||||
Type: python
|
||||
Board:
|
||||
List: all
|
||||
Python:
|
||||
Module: application.netdata.netdata
|
||||
Action:
|
||||
button_release_event: python_start
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
/usr/bin/qrencode -s 30 $1 $2 -m 1
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/sh -
|
||||
WLAN_INTERFACE=$(/usr/local/demo/application/netdata/bin/get_wlan_name.sh 2> /dev/null)
|
||||
|
||||
if [ -n "$WLAN_INTERFACE" ]; then
|
||||
LIST_ETH=$(/sbin/ip link | grep ^[1-9] | grep -v lo | grep -v "$WLAN_INTERFACE" | awk '{print $2;}' | sed "s/://")
|
||||
else
|
||||
LIST_ETH=$(/sbin/ip link | grep ^[1-9] | grep -v lo | awk '{print $2;}' | sed "s/://")
|
||||
fi
|
||||
|
||||
IP_ADDRESS=""
|
||||
for i in $LIST_ETH;
|
||||
do
|
||||
IP=$(/sbin/ip addr show $i | grep "inet " | awk '{print $2;}' | sed "s/\([0-9]*.[0-9]*.[0-9]*.[0-9]*\).*/\1/")
|
||||
if [ -n "$IP" ]; then
|
||||
IP_ADDRESS="$IP_ADDRESS http://$IP:19999"
|
||||
fi
|
||||
done
|
||||
echo $IP_ADDRESS
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh -
|
||||
/sbin/ip link show wlan0 | head -n 1 | awk '{print $2}' | tr '\n' ' ' | sed "s/: //"
|
||||
@@ -0,0 +1,2 @@
|
||||
HOSTAPD_SSID=STDemoNetwork
|
||||
HOSTAPD_PASSWD=stm32mp1
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
@@ -0,0 +1,399 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gdk
|
||||
from gi.repository import GLib
|
||||
from gi.repository import GdkPixbuf
|
||||
|
||||
import os
|
||||
import socket
|
||||
import fcntl
|
||||
import struct
|
||||
import string
|
||||
import random
|
||||
import math
|
||||
import subprocess
|
||||
from time import sleep, time
|
||||
import threading
|
||||
|
||||
SIMULATE = 0
|
||||
|
||||
ETHERNET_PREFIX="end"
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
SUBMODULE_PATH = "application/netdata"
|
||||
DEMO_PATH = "/usr/local/demo"
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
WIFI_LINUX_INTERFACE_NAME = "wlan0"
|
||||
WIFI_HOTSPOT_IP="192.168.72.1"
|
||||
|
||||
WIFI_DEFAULT_SSID="STDemoNetwork"
|
||||
WIFI_DEFAULT_PASSWD="stm32mp1"
|
||||
|
||||
if SIMULATE > 0:
|
||||
WIFI_LINUX_INTERFACE_NAME = "wlp8s0"
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
ICON_SIZE_1080 = 260
|
||||
ICON_SIZE_720 = 160
|
||||
ICON_SIZE_480 = 160
|
||||
ICON_SIZE_272 = 48
|
||||
|
||||
# return format:
|
||||
# [ icon_size, font_size ]
|
||||
SIZES_ID_ICON_SIZE = 0
|
||||
SIZES_ID_FONT_SIZE = 1
|
||||
def get_sizes_from_screen_size(width, height):
|
||||
minsize = min(width, height)
|
||||
icon_size = None
|
||||
font_size = None
|
||||
if minsize == 720:
|
||||
icon_size = ICON_SIZE_720
|
||||
font_size = 25
|
||||
elif minsize == 480:
|
||||
icon_size = ICON_SIZE_480
|
||||
font_size = 20
|
||||
elif minsize == 272:
|
||||
icon_size = ICON_SIZE_272
|
||||
font_size = 10
|
||||
elif minsize == 600:
|
||||
icon_size = ICON_SIZE_720
|
||||
font_size = 15
|
||||
elif minsize >= 1080:
|
||||
icon_size = ICON_SIZE_1080
|
||||
font_size = 32
|
||||
return [icon_size, font_size]
|
||||
|
||||
def get_icon_size_from_screen_size(width, height):
|
||||
minsize = min(width, height)
|
||||
if minsize == 720:
|
||||
return ICON_SIZE_720
|
||||
elif minsize == 480:
|
||||
return ICON_SIZE_480
|
||||
elif minsize == 272:
|
||||
return ICON_SIZE_272
|
||||
elif minsize == 600:
|
||||
return ICON_SIZE_1080
|
||||
elif minsize >= 1080:
|
||||
return ICON_SIZE_1080
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
# Get the wlan interface name
|
||||
def get_wlan_interface_name():
|
||||
cmd = ["%s/application/netdata/bin/get_wlan_name.sh" % DEMO_PATH]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res = proc.stdout.read().decode('utf-8')
|
||||
return res
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
# Get list of ip address
|
||||
def get_ip_address_list():
|
||||
cmd = ["%s/application/netdata/bin/get_ethernet_ip.sh" % DEMO_PATH]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res = proc.stdout.read().decode('utf-8')
|
||||
return res
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
# Get the ip address of board
|
||||
def get_ip_address(ifname):
|
||||
ip = "NA"
|
||||
try:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
ip = socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
0x8915, # SIOCGIFADDR
|
||||
struct.pack('256s', bytes(ifname[:15], 'utf-8'))
|
||||
)[20:24])
|
||||
except socket.error:
|
||||
pass
|
||||
return ip
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
def _load_image_wlan_eventBox(parent, filename, label_text1, label_text2, scale_w, scale_h):
|
||||
# Create box for xpm and label
|
||||
box = Gtk.VBox(homogeneous=False, spacing=0)
|
||||
# Create an eventBox
|
||||
eventBox = Gtk.EventBox()
|
||||
# Now on to the image stuff
|
||||
pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(
|
||||
filename=filename,
|
||||
width=scale_w,
|
||||
height=scale_h,
|
||||
preserve_aspect_ratio=True)
|
||||
image = Gtk.Image.new_from_pixbuf(pixbuf)
|
||||
|
||||
label = Gtk.Label()
|
||||
label.set_markup("<span font='10' color='#FFFFFFFF'>%s\n</span>"
|
||||
"<span font='10' color='#FFFFFFFF'>%s</span>" % (label_text1, label_text2))
|
||||
#label.set_justify(Gtk.Justification.LEFT)
|
||||
label.set_line_wrap(True)
|
||||
|
||||
# Pack the pixmap and label into the box
|
||||
box.pack_start(image, True, False, 0)
|
||||
box.pack_start(label, True, False, 0)
|
||||
|
||||
# Add the image to the eventBox
|
||||
eventBox.add(box)
|
||||
|
||||
return eventBox
|
||||
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
|
||||
return "".join(random.choice(chars) for _ in range(size))
|
||||
# -------------------------------------------------------------------
|
||||
# -------------------------------------------------------------------
|
||||
|
||||
class NetdataWebserver(Gtk.Dialog):
|
||||
def __init__(self, parent):
|
||||
Gtk.Dialog.__init__(self, "Wifi", parent, 0)
|
||||
|
||||
if SIMULATE > 0:
|
||||
self.screen_width = 800
|
||||
self.screen_height = 480
|
||||
self.set_default_size(self.screen_width, self.screen_height)
|
||||
else:
|
||||
self.maximize()
|
||||
try:
|
||||
display = Gdk.Display.get_default()
|
||||
monitor = display.get_primary_monitor()
|
||||
geometry = monitor.get_geometry()
|
||||
scale_factor = monitor.get_scale_factor()
|
||||
self.screen_width = scale_factor * geometry.width
|
||||
self.screen_height = scale_factor * geometry.height
|
||||
except:
|
||||
self.screen_width = self.get_screen().get_width()
|
||||
self.screen_height = self.get_screen().get_height()
|
||||
|
||||
self.icon_size = get_icon_size_from_screen_size(self.screen_width, self.screen_height)
|
||||
sizes = get_sizes_from_screen_size(self.screen_width, self.screen_height)
|
||||
self.font_size = sizes[SIZES_ID_FONT_SIZE]
|
||||
|
||||
self.set_decorated(False)
|
||||
rgba = Gdk.RGBA(0.31, 0.32, 0.31, 0.8)
|
||||
self.override_background_color(0,rgba)
|
||||
|
||||
mainvbox = self.get_content_area()
|
||||
|
||||
self.page_ip = Gtk.VBox(homogeneous=False, spacing=0)
|
||||
self.page_ip.set_border_width(10)
|
||||
self.set_border_width(10)
|
||||
|
||||
self.title = Gtk.Label()
|
||||
self.title.set_markup("<span font='%d' color='#FFFFFFFF'><b>Access information to netdata</b></span>" % (self.font_size+5))
|
||||
self.page_ip.add(self.title)
|
||||
self.label_eth = Gtk.Label()
|
||||
self.label_eth.set_markup("<span font='%d' color='#FFFFFFFF'>netdata over Ethernet:</span>" % self.font_size)
|
||||
self.label_eth.set_xalign (0.0)
|
||||
self.label_ip_ethernet = Gtk.Label()
|
||||
#self.label_ip_ethernet.set_xalign (0.0)
|
||||
self.label_wifi = Gtk.Label()
|
||||
self.label_wifi.set_markup("<span font='%d' color='#FFFFFFFF'>netdata over Wifi:</span>" % self.font_size)
|
||||
self.label_wifi.set_xalign (0.0)
|
||||
self.label_ip_wlan0 = Gtk.Label()
|
||||
#self.label_ip_wlan0.set_xalign (0.0)
|
||||
self.label_hotspot = Gtk.Label()
|
||||
self.label_hotspot.set_xalign (0.0)
|
||||
|
||||
self.previous_click_time=0
|
||||
self.wifi_ssid=WIFI_DEFAULT_SSID
|
||||
self.wifi_passwd=WIFI_DEFAULT_PASSWD
|
||||
|
||||
self.info_grid = Gtk.Grid()
|
||||
self.info_grid.set_column_spacing(2)
|
||||
self.info_grid.set_row_spacing(2)
|
||||
|
||||
self.info_grid.attach(self.label_eth, 0, 1, 1, 1)
|
||||
self.info_grid.attach(self.label_ip_ethernet, 1, 1, 1, 1)
|
||||
|
||||
if self.is_wifi_available():
|
||||
print ("wlan0 is available")
|
||||
self.hotspot_switch = Gtk.Switch()
|
||||
|
||||
# set wlan switch state on first execution
|
||||
ip_wlan0 = get_ip_address(get_wlan_interface_name())
|
||||
if ip_wlan0 == WIFI_HOTSPOT_IP:
|
||||
self.hotspot_switch.set_active(True)
|
||||
else:
|
||||
self.hotspot_switch.set_active(False)
|
||||
|
||||
self.hotspot_switch.connect("notify::active", self.on_switch_activated)
|
||||
self.info_grid.attach(self.label_wifi, 0, 2, 1, 1)
|
||||
self.info_grid.attach(self.hotspot_switch, 0, 3, 1, 1)
|
||||
self.info_grid.attach(self.label_hotspot, 1, 3, 1, 1)
|
||||
|
||||
else:
|
||||
print ("wlan0 interface not available")
|
||||
self.info_grid.attach(self.label_hotspot, 0, 3, 1, 1)
|
||||
|
||||
self.page_ip.add(self.info_grid)
|
||||
self.refresh_network_page()
|
||||
self.connect("button-release-event", self.on_page_press_event)
|
||||
|
||||
mainvbox.pack_start(self.page_ip, False, True, 3)
|
||||
self.show_all()
|
||||
|
||||
def is_wifi_available(self):
|
||||
interface_name = get_wlan_interface_name()
|
||||
if len(interface_name) > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_wifi_config(self):
|
||||
filepath = "/etc/default/hostapd"
|
||||
if os.path.isfile(filepath):
|
||||
file = open(filepath, "r")
|
||||
i=0
|
||||
for line in file:
|
||||
if "HOSTAPD_SSID" in line:
|
||||
self.wifi_ssid = (line.split('=')[1]).rstrip('\r\n')
|
||||
i+=1
|
||||
if "HOSTAPD_PASSWD" in line:
|
||||
self.wifi_passwd=(line.split('=')[1]).rstrip('\r\n')
|
||||
i+=1
|
||||
file.close()
|
||||
if (i==2):
|
||||
print("[Wifi: use hostapd configuration: ssid=%s, passwd=%s]\n" %(self.wifi_ssid, self.wifi_passwd))
|
||||
else:
|
||||
self.wifi_ssid=WIFI_DEFAULT_SSID
|
||||
self.wifi_passwd=WIFI_DEFAULT_PASSWD
|
||||
print("[Wifi: use default configuration: ssid=%s, passwd=%s]\n" %(self.wifi_ssid, self.wifi_passwd))
|
||||
else:
|
||||
print("[Wifi: use default configuration: ssid=%s, passwd=%s]\n" %(self.wifi_ssid, self.wifi_passwd))
|
||||
|
||||
def set_random_wifi_config(self):
|
||||
self.wifi_ssid="ST-" + id_generator()
|
||||
#self.wifi_passwd=id_generator(6, string.ascii_lowercase)
|
||||
self.set_wifi_config(self.wifi_ssid, self.wifi_passwd)
|
||||
|
||||
def set_wifi_config(self, ssid, password):
|
||||
filepath = "/tmp/hostapd"
|
||||
file = open(filepath, "w")
|
||||
print ("[Wifi: set hostapd config: ssid=%s, passwd=%s]" %(ssid, password))
|
||||
file.write('HOSTAPD_SSID=%s\nHOSTAPD_PASSWD=%s\n' %(ssid, password))
|
||||
file.close()
|
||||
os.system('su -c \"cp /tmp/hostapd /etc/default/hostapd\"')
|
||||
|
||||
|
||||
def refresh_network_page(self):
|
||||
print("[Refresh network page]\n")
|
||||
|
||||
ip_list=get_ip_address_list().split()
|
||||
if len(ip_list) > 0:
|
||||
ip_ethernet = ip_list[0]
|
||||
ethernet_status = "<span font='%d' color='#FFFFFFFF'> %s</span>" % (self.font_size, ip_ethernet)
|
||||
else:
|
||||
ip_ethernet = get_ip_address('{}0'.format(ETHERNET_PREFIX))
|
||||
if ip_ethernet == "NA":
|
||||
ip_ethernet = get_ip_address('{}1'.format(ETHERNET_PREFIX))
|
||||
if ip_ethernet != "NA":
|
||||
ethernet_status = "<span font='%d' color='#FFFFFFFF'> http://%s:19999</span>" % (self.font_size, ip_ethernet)
|
||||
else:
|
||||
ethernet_status = "<span font='%d' color='#FF0000FF'> No Ethernet connection</span>" % self.font_size
|
||||
self.label_ip_ethernet.set_markup(ethernet_status)
|
||||
|
||||
if self.is_wifi_available():
|
||||
print ("wlan0 is available")
|
||||
ip_wlan0 = get_ip_address(get_wlan_interface_name())
|
||||
|
||||
print("Ip address of Wlan0 are: ", ip_wlan0)
|
||||
if ip_wlan0 == "NA":
|
||||
sleep(1)
|
||||
ip_wlan0 = get_ip_address(get_wlan_interface_name())
|
||||
print("Ip address of Wlan0 are: ", ip_wlan0)
|
||||
if ip_wlan0 == "NA":
|
||||
hotspot_status = "<span font='%d' color='#FF0000FF'> Wifi not started</span>" % self.font_size
|
||||
self.info_grid.remove_row(6)
|
||||
elif ip_wlan0 == WIFI_HOTSPOT_IP:
|
||||
self.get_wifi_config()
|
||||
hotspot_status = "<span font='%d' color='#00AA00FF'> Wifi hotspot started</span>" % self.font_size
|
||||
|
||||
wifi_qrcode_cmd = "WIFI:S:%s;T:WPA;P:%s;;" %(self.wifi_ssid, self.wifi_passwd)
|
||||
print("%s/bin/build_qrcode.sh" % os.path.join(DEMO_PATH,SUBMODULE_PATH), "-o /tmp/qr-code_wifi_access.png", wifi_qrcode_cmd)
|
||||
cmd = ["%s/bin/build_qrcode.sh" % os.path.join(DEMO_PATH,SUBMODULE_PATH), "-o /tmp/qr-code_wifi_access.png", wifi_qrcode_cmd]
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = proc.stdout.read().decode('utf-8')
|
||||
|
||||
url_qrcode_cmd = "http://%s:19999" % ip_wlan0
|
||||
cmd2 = ["%s/bin/build_qrcode.sh" % os.path.join(DEMO_PATH,SUBMODULE_PATH), "-o /tmp/qr-code_netdata_url.png", url_qrcode_cmd]
|
||||
proc = subprocess.Popen(cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
result = proc.stdout.read().decode('utf-8')
|
||||
|
||||
self.wifi_credential = _load_image_wlan_eventBox(self, "/tmp/qr-code_wifi_access.png", "ssid: %s" % self.wifi_ssid, "passwd: %s" % self.wifi_passwd, -1, self.icon_size)
|
||||
self.netdata_url = _load_image_wlan_eventBox(self, "/tmp/qr-code_netdata_url.png", "url: http://%s:19999" % ip_wlan0, "", -1, self.icon_size)
|
||||
self.info_grid.attach(self.wifi_credential, 0, 6, 1, 1)
|
||||
self.info_grid.attach(self.netdata_url, 1, 6, 1, 1)
|
||||
|
||||
self.show_all()
|
||||
else:
|
||||
hotspot_status = "<span font='%d' color='#FF0000FF'>Wifi started but not configured as hotspot</span>" % self.font_size
|
||||
self.info_grid.remove_row(6)
|
||||
|
||||
self.label_ip_wlan0.set_markup("<span font='%d' color='#FFFFFFFF'>NetData over Wifi: http://%s:19999</span>" % (self.font_size, ip_wlan0))
|
||||
self.info_grid.attach(self.label_ip_wlan0, 0, 6, 1, 1)
|
||||
self.show_all()
|
||||
else:
|
||||
print ("wlan0 interface not available")
|
||||
hotspot_status = "<span font='%d' color='#FF0000FF'> Wifi not available on board</span>" % self.font_size
|
||||
|
||||
self.label_hotspot.set_markup(hotspot_status)
|
||||
|
||||
def on_page_press_event(self, widget, event):
|
||||
self.click_time = time()
|
||||
#print(self.click_time - self.previous_click_time)
|
||||
# TODO : a fake click is observed, workaround hereafter
|
||||
if (self.click_time - self.previous_click_time) < 0.01:
|
||||
self.previous_click_time = self.click_time
|
||||
elif (self.click_time - self.previous_click_time) < 0.3:
|
||||
print ("double click : exit")
|
||||
self.destroy()
|
||||
else:
|
||||
#print ("simple click")
|
||||
self.previous_click_time = self.click_time
|
||||
|
||||
def on_switch_activated(self, switch, gparam):
|
||||
if switch.get_active():
|
||||
self.set_random_wifi_config()
|
||||
self.wifi_hotspot_start()
|
||||
else:
|
||||
self.wifi_hotspot_stop()
|
||||
self.refresh_network_page()
|
||||
|
||||
def wifi_hotspot_start(self):
|
||||
print('[DEBUG]: %s/application/netdata/bin/wifi_start.sh' % DEMO_PATH)
|
||||
os.system('%s/application/netdata/bin/wifi_start.sh' % DEMO_PATH)
|
||||
|
||||
|
||||
def wifi_hotspot_stop(self):
|
||||
print('[DEBUG]:%s/application/netdata/bin/wifi_start.sh\"' % DEMO_PATH)
|
||||
os.system('%s/application/netdata/bin/wifi_stop.sh' % DEMO_PATH)
|
||||
|
||||
def create_subdialogwindow(parent):
|
||||
_window = NetdataWebserver(parent)
|
||||
_window.show_all()
|
||||
response = _window.run()
|
||||
_window.destroy()
|
||||
|
||||
|
||||
# -------------------------------------------------
|
||||
# -------------------------------------------------
|
||||
# test submodule
|
||||
class TestUIWindow(Gtk.Window):
|
||||
def __init__(self):
|
||||
Gtk.Window.__init__(self, title="Test Launcher")
|
||||
create_subdialogwindow(self)
|
||||
self.show_all()
|
||||
|
||||
if __name__ == "__main__":
|
||||
win = TestUIWindow()
|
||||
win.connect("delete-event", Gtk.main_quit)
|
||||
win.show_all()
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
script -qc 'su -c "/usr/local/demo/bin/st-hotspot-wifi-service.sh start"'
|
||||
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
script -qc 'su -c "/usr/local/demo/bin/st-hotspot-wifi-service.sh stop"'
|
||||
@@ -0,0 +1,38 @@
|
||||
SUMMARY = "Add support of camera preview on Demo Launcher"
|
||||
HOMEPAGE = "wiki.st.com"
|
||||
LICENSE = "BSD-3-Clause"
|
||||
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9"
|
||||
|
||||
DEPENDS = "demo-launcher event-gtk-player wayland-utils"
|
||||
|
||||
PV = "2.0"
|
||||
|
||||
SRC_URI = " \
|
||||
file://Video_playback_logo.png \
|
||||
file://ST2297_visionv3.webm \
|
||||
file://ST19619_ST_Company_Video_16_9_EN_272p.webm \
|
||||
file://launch_video.sh \
|
||||
file://020-video.yaml \
|
||||
"
|
||||
|
||||
do_configure[noexec] = "1"
|
||||
do_compile[noexec] = "1"
|
||||
|
||||
do_install() {
|
||||
install -d ${D}${prefix}/local/demo/application/video/bin
|
||||
install -d ${D}${prefix}/local/demo/application/video/pictures
|
||||
install -d ${D}${prefix}/local/demo/media
|
||||
|
||||
# install yaml file
|
||||
install -m 0644 ${WORKDIR}/*.yaml ${D}${prefix}/local/demo/application/
|
||||
# install pictures
|
||||
install -m 0644 ${WORKDIR}/*.png ${D}${prefix}/local/demo/application/video/pictures
|
||||
# script
|
||||
install -m 0755 ${WORKDIR}/*.sh ${D}${prefix}/local/demo/application/video/bin
|
||||
# video
|
||||
install -m 0644 ${WORKDIR}/ST2297_visionv3.webm ${D}${prefix}/local/demo/media
|
||||
install -m 0644 ${WORKDIR}/ST19619_ST_Company_Video_16_9_EN_272p.webm ${D}${prefix}/local/demo/media
|
||||
}
|
||||
|
||||
FILES:${PN} += "${prefix}/local/demo/application/ ${prefix}/local/demo/media"
|
||||
RDEPENDS:${PN} += "demo-launcher event-gtk-player"
|
||||
@@ -0,0 +1,15 @@
|
||||
Application:
|
||||
Name: Video
|
||||
Description: playback
|
||||
Icon: application/video/pictures/Video_playback_logo.png
|
||||
Type: script
|
||||
Board:
|
||||
List: all
|
||||
Script:
|
||||
Start: application/video/bin/launch_video.sh
|
||||
Stop: application/video/bin/stop_video.sh
|
||||
Action:
|
||||
button_release_event: script_start
|
||||
button_press_event: highlight_eventBox
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,45 @@
|
||||
#!/bin/sh
|
||||
function pty_exec() {
|
||||
cmd=$1
|
||||
pty=$(tty > /dev/null 2>&1; echo $?)
|
||||
if [ $pty -eq 0 ]; then
|
||||
cmd=$(echo $cmd | sed "s#\"#'#g")
|
||||
event_cmd=$(echo /usr/local/demo/bin/touch-event-gtk-player -w $SCREEN_WIDTH -h $SCREEN_HEIGHT --graph \"$cmd\")
|
||||
eval $event_cmd > /dev/null 2>&1
|
||||
else
|
||||
# no pty
|
||||
echo "NO PTY"
|
||||
event_cmd=$(echo /usr/local/demo/bin/touch-event-gtk-player -w $SCREEN_WIDTH -h $SCREEN_HEIGHT --graph \"$cmd\")
|
||||
script -qc "$event_cmd" > /dev/null 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect if GPU are present or not
|
||||
gpu_presence=0
|
||||
if [ -f /etc/default/weston ] && $(grep "^OPTARGS" /etc/default/weston | grep -q "use-pixman" ) ;
|
||||
then
|
||||
echo "Without GPU"
|
||||
ADDONS="videoconvert ! video/x-raw,format=BGRx ! queue !"
|
||||
else
|
||||
echo "With GPU"
|
||||
gpu_presence=1
|
||||
ADDONS=""
|
||||
fi
|
||||
|
||||
# Detect size of screen
|
||||
SCREEN_WIDTH=$(wayland-info | grep logical_width | sed -r "s/logical_width: ([0-9]+),.*/\1/")
|
||||
SCREEN_HEIGHT=$(wayland-info | grep logical_width | sed -r "s/.*logical_height: ([0-9]+).*/\1/")
|
||||
|
||||
if [ $gpu_presence -eq 0 ] || [ $SCREEN_HEIGHT -lt 480 ];
|
||||
then
|
||||
VIDEO_FILE=/usr/local/demo/media/ST19619_ST_Company_Video_16_9_EN_272p.webm
|
||||
else
|
||||
VIDEO_FILE=/usr/local/demo/media/ST2297_visionv3.webm
|
||||
fi
|
||||
|
||||
echo "Gstreamer graph:"
|
||||
# WARNING: need to add a space before last ' to avoid that ' are taken by name and not by video-sink
|
||||
GRAPH="playbin3 uri=file://$VIDEO_FILE video-sink='$ADDONS gtkwaylandsink name=gtkwsink '"
|
||||
echo " $GRAPH"
|
||||
|
||||
pty_exec "$GRAPH"
|
||||
Reference in New Issue
Block a user