Skip to content

Commit

Permalink
initial code and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sigboe committed Feb 14, 2021
1 parent 8cbdd58 commit 829dcd1
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
2017-09-07-raspbian-stretch-lite.img
mistress
wallpaper.png
build
dist
__pycache__
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,49 @@
# MiSTress
RSS reader for MiSTer FPGA, changelog displayed on your wallpaper

![](demo.png)

This is a functioning, simple, easy to use rss reader for the MiSTer FPGA platform. Currently it shows the changelog for the 3 last updates by editing your wallpaper and adding the text to it. There are many things that should be improved and cleaned up here but currently I do not have time to work on this. This program is written in Python but has to be compiled to be able to include the dependencies, more on that below. I originally just wrote this as an excericise in getting to know more python, but it turned out in an excercise in futility compiling python to systems with old glibc. Notes below. Someone asked me to share how I got the changelog on my wallpaper, and I wanted to clean up a bit the files, and document how to pick up developement again as best I can. Feel free to make issues with bug reports, or feature requests, but I don't know if I have time shortly to fix stuff. Merge requests are also welcome.

You will find the precompiled binary in the release section here on github.

## Sideefect

MiSTress runs on boot and checks the rss feed for news, this is really quick but not instant, after MiSTress has updated your wallpaper it will restart the menu core, which results in a small flicker one time each boot. This does not happen when you go from a core back to the menu core.

# Requirements

1. Internet

# Installation

1. Copy mistress into your Scripts directory
2. Rename your wallpaper file from menu.png to wallpaper.png
3. From the Menu core, run the misterss (found with the scripts), answer yes to install the service. This has to be done each time Linux is updated or else the rss feed wont be updated on your wallpaper.

# Uninstallation

1. Run mistress from the menu core, and say yes to remove the service
2. Rename your wallpaper back from wallpaper.png to menu.png


# Compilation

The compilation is not straight forward, In the future it is possible simpler instructions will be included, or at the very least full instructions. I dont know the compilation dependencies since I made a chroot and installed packages in trial and error. I don't know if it is possible to legally share the raspbian enviornment I have setup to do the compilation, if you have any opinions about that feel free to write about it. Currently this requires a raspberry pi, and building a chroot (basic instructions included) and then installing the (unknown) dependencies into the chroot. I just googled for a while and managed to do it, but I am not sure which packages was needed from the once I installed.
I am sorry to say that currently in my life situation (which includes being a loving father) I don't currently have time to work on the build instructions. But it may be okay for me to share the chroot enviornment with dependencies installed? Checkout pi-chroot-notes.md if you want to build a chroot, and maybe you are proficient in figuring out the build dependencies.

You need to copy the source code and font and maybe spec file into the chroot, The command to compile is as follows

```bash
pyinstaller --hidden-import=packaging.requirements --add-data="Roboto-Regular.ttf:." --onefile --clean mistress.py
```

# TODO

Currently I don't have any short term plans to improve this programs, as I don't have time on my hands. But some of the things that I want to do if I get more spare time soon:

- [] Improved handling of the current wallpaper wallaper file, so its easier to install and uninstall.
- [] Improve the text handling, to fix edge cases where some text isn't formatted correctly when written on the picture
- [] Add an optional options file, to override things like what RSS feed to fetch, how many posts, and maybe more

I don't remember everything, but there is more that I wanted to do
Binary file added Roboto-Regular.ttf
Binary file not shown.
Binary file added demo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions mistress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/usr/bin/env python3
import feedparser, sys, os, argparse, locale, ssl, textwrap, time
from subprocess import run, PIPE
from PIL import Image, ImageFont, ImageDraw
from dialog import Dialog
# feedparser, PIL and dialog are dependencies not met on MiSTer
# these are baked in with PyInstaller.
# PyInstaller needs to be patched to include libxcb,
# as it is designed to explicitly ignore that, but MiSTer needs it.

# Disable ssl enforcement if platform doesn't support it
# This is needed by MiSTer. If not, feedparser will error.
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context

# This is currently needed to use the included baked in font file
os.chdir(sys._MEIPASS)

# Dialog
locale.setlocale(locale.LC_ALL, '')
d = Dialog(dialog="dialog", autowidgetsize=True)
d.set_background_title("RSS Wallpaper v0.1")
# Parse command line options (ie. -u)
parser = argparse.ArgumentParser(description='enable/disable daemon that writes an rss feed to the wallpaper.')
parser.add_argument('--updaterss', '-u', help='update wallpaper with latest rss', action='store_true')
args = parser.parse_args()
# Setup the rss feed
rss = feedparser.parse('https://misterfpga.org/feed.php?t=147')
feed = ''
# Settup pillow for drawing
image = Image.open('/media/fat/wallpaper.png').convert('RGB')
draw = ImageDraw.Draw(image)
font = ImageFont.truetype('./Roboto-Regular.ttf', 23)
color = "black"
shadowcolor = "white"
(x, y) = (24, 200)
#Text wrap settings
wrapper = textwrap.TextWrapper(width=50, subsequent_indent=' ')
# init system
inittab = '/etc/inittab'
initline = '::sysinit:/media/fat/Scripts/rss -u'

if args.updaterss:
for i in range(5):
date = time.strftime("%b %d", rss.entries[i].published_parsed)
xmllint = run(['xmllint', '--html', '--xpath', '//text()', '-'], input = rss.entries[i].summary, stdout=PIPE, universal_newlines=True)
summary = wrapper.fill(text=xmllint.stdout)
feed += rss.entries[i].author + ' @ ' + date + '\n' + summary + '\n\n'

print(feed, end =" ")

# draw text outline first
draw.text((x-1, y-1), feed, font=font, fill=shadowcolor)
draw.text((x+1, y-1), feed, font=font, fill=shadowcolor)
draw.text((x-1, y+1), feed, font=font, fill=shadowcolor)
draw.text((x+1, y+1), feed, font=font, fill=shadowcolor)

# then draw text over it
draw.text((x, y), feed, fill=color, font=font)
image.save('/media/fat/menu.png')
sys.exit()

#enabling this will make it run via init system
# https://buildroot.org/downloads/manual/manual.html#_init_system

with open(inittab) as origin:
for line in origin:
if not initline in line:
serviceenabled = False
continue
try:
serviceenabled = True
break
except IndexError:
print

if serviceenabled:
if d.yesno("RSS service is installed and enabled, remove service?") == d.OK:
with open(inittab,"r+") as f:
new_f=f.readlines()
f.seek(0)
for line in new_f:
if initline not in line:
f.write(line)
f.truncate()
else:
if d.yesno("RSS service is not installed, install service?") == d.OK:
f=open(inittab, "a+")
f.write(initline + "\n" )
33 changes: 33 additions & 0 deletions mistress.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['rss.py'],
pathex=['/root/misterss'],
binaries=[],
datas=[('Roboto-Regular.ttf', '.')],
hiddenimports=['packaging.requirements'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='rss',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )
35 changes: 35 additions & 0 deletions mount-chroot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash

set -e


if [[ "${EUID}" -ne "0" ]]; then
echo "Please run as root"
exit
fi

if [[ -z "${1}" ]]; then

# set up image as loop device
kpartx -d /dev/loop0
kpartx -avs ./2017-09-07-raspbian-stretch-lite.img

# mount partition
mount -o rw /dev/mapper/loop0p2 /mnt/raspbian
mount -o rw /dev/mapper/loop0p1 /mnt/raspbian/boot

# mount binds
mount --bind /dev /mnt/raspbian/dev/
mount --bind /sys /mnt/raspbian/sys/
mount --bind /proc /mnt/raspbian/proc/
mount --bind /dev/pts /mnt/raspbian/dev/pts

echo "mounted, you may chroot into: chroot /mnt/raspbian /bin/bash"

fi

if [[ "${1}" == "unmount" ]]; then
# unmount everything
umount /mnt/raspbian/{dev/pts,dev,sys,proc,boot,}
kpartx -d /dev/loop0
fi
70 changes: 70 additions & 0 deletions pi-chroot-notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
```bash
# raspbian stretch lite on ubuntu

### You can write the raspbian image onto the sd card,
# boot the pi so it expands the fs, then plug back to your laptop/desktop
# and chroot to it with my script
# https://gist.github.com/htruong/7df502fb60268eeee5bca21ef3e436eb
# sudo ./chroot-to-pi.sh /dev/sdb
# I found it to be much less of a pain in the ass and more reliable
# than doing the kpartx thing

# install dependecies
apt-get install qemu qemu-user-static binfmt-support

# download raspbian image
# wget https://downloads.raspberrypi.org/raspbian_latest
# should download specific version that has an old enough glibc, like 2017-11-29

# extract raspbian image
unzip raspbian_latest

# extend raspbian image by 1gb
dd if=/dev/zero bs=1M count=1024 >> 2017-11-29-raspbian-stretch-lite.img

# set up image as loop device
kpartx -v -a 2017-11-29-raspbian-stretch-lite.img

#do the parted stuff, unmount kpartx, then mount again
parted /dev/loop0
resizepart 2 -1s
quit
kpartx -d /dev/loop0
kpartx -v -a 2017-11-29-raspbian-stretch-lite.img

# check file system
e2fsck -f /dev/mapper/loop0p2

#expand partition
resize2fs /dev/mapper/loop0p2

# mount partition
mount -o rw /dev/mapper/loop0p2 /mnt/raspbian
mount -o rw /dev/mapper/loop0p1 /mnt/raspbian/boot

# mount binds
mount --bind /dev /mnt/raspbian/dev/
mount --bind /sys /mnt/raspbian/sys/
mount --bind /proc /mnt/raspbian/proc/
mount --bind /dev/pts /mnt/raspbian/dev/pts

# ld.so.preload fix
sed -i 's/^/#/g' /mnt/raspbian/etc/ld.so.preload

# copy qemu binary
cp /usr/bin/qemu-arm-static /mnt/raspbian/usr/bin/

# chroot to raspbian
chroot /mnt/raspbian /bin/bash
# do stuff...
exit

# revert ld.so.preload fix
sed -i 's/^#//g' /mnt/raspbian/etc/ld.so.preload

# unmount everything
umount /mnt/raspbian/{dev/pts,dev,sys,proc,boot,}

# unmount loop device
kpartx -d /dev/loop0
```

0 comments on commit 829dcd1

Please sign in to comment.