Monday, January 20, 2025

Sweethome3D web viewer

 Sweethome3D web viewable.


I've made a Sweethome3d model that I want to share online. I exported from Sweehome3d as an OBJ and then imported into FreeCAD. I removed the window panes and room ceiling with this:

FreeCAD.Console.PrintMessage("Making Sweethome3D OBJ more viewable\n")

for obj in App.ActiveDocument.findObjects():
  if obj.Name.startswith("room_"):
    if int(obj.Name[-1]) % 2 != 0:
      print(f"name: {obj.Name}")
      App.ActiveDocument.removeObject(obj.Name)
  if obj.Name.startswith("sweethome3d_window_pane"):
    print(f"name: {obj.Name}")
    App.ActiveDocument.removeObject(obj.Name)

App.ActiveDocument.recompute()

FreeCAD.Console.PrintMessage("Done!\n")

This can then be loaded into https://3dviewer.net/, for example.

Saturday, January 18, 2025

 Garden hose adapter


I'm playing with plumbing parts. It turns out I need a GHT (garden hose 3/4INCH) thread. The excellent BOSL2 in OpenSCAD doesn't have a pre-defined GHT threaded_rod, so I've hacked together my own:


edit: /home/richard/.local/share/OpenSCAD/libraries/BOSL2-master/threading.scad


replace the TPI in npt_threaded_rod with the value from here:

https://pickhose.com/garden-hose-thread-vs-npt/


re-render.

Monday, June 24, 2024

 Putting HTTP basic auth in front of an arbitrary container. I use Apache. Steps are:

  1. start your container on the host. Forward the port to somewhere you can apply a firewall to.
  2. firewall off the port using, ideally, the providers firewall tool.
  3. start an apache container, and configure it with a reverse proxy, and basic auth.
  4. make sure the Apache port isn't firewalled.

Friday, April 29, 2022

Forward LMS to the net

I have a LMS installation at home and a shoutcast music stream public-ally available. Sometimes I want to join some friends online and allow them to queue music up from my LMS into the shoutcast stream.

I use darkice to stream what I'm listening to up to a shoutcast server. And then I forward the http of my LMS install to an intermediary host with this command:


ssh -R 8081:localhost:9000 -p 23 richard@my-intermediary-host.com


Then, on my-intermediary-host, I set up an apache proxy, and add in basic http auth to stop folks chancing apon it.


Listen 8008
<VirtualHost *:8008>
    ProxyPreserveHost On

    # Servers to proxy the connection, or;
    # List of application servers:
    # Usage:
    # ProxyPass / http://[IP Addr.]:[port]/
    # ProxyPassReverse / http://[IP Addr.]:[port]/
    # Example:
    ProxyPass / http://0.0.0.0:8081/
    ProxyPassReverse / http://0.0.0.0:8081/
    <Proxy *>
        Order deny,allow
        Allow from all
        Authtype Basic
        Authname "Password Required"
        AuthUserFile /etc/httpd/.htpasswd
        Require valid-user
    </Proxy>
</VirtualHost>

The next step here is to avoid using darkice and probably use LMS's mp3 streaming output to plug directly into shoutcast... probably using ssh forwarding for that as well.

Saturday, February 26, 2022

I recently discovered a friend had passed away. This is my history with this wonderful man.

I first met James in a competitive hockey game at the age of ~15. He played goalie, a position that required a disguise. I was left-back, not close enough to get a good look until we shook hands at the end of the game. I remember the game, so did James when we met three or four years later. It was away for me in south London. It was a home game for James.
 
Next time we met was at Cottam Side. We were both starting our second year of University and needed somewhere to live. He was studying Math and a language (may be Italian?). He introduced me to the super nintendo and Yoshie's Island. He brought a guitar and music to the house. He introduced me to the Meters. We smoked and drank together along with the others in the house. It was a busy house with lots of folks visiting. There were Mario Kart tournaments with players bring their own controller. He was an accomplished gamer. At one point the TV pitched forward and crushed the cartridge into the top of the Nintendo. The console survived but the game didn't.

James was part of the group I hung out with for the duration of my time at University. With the release of the N64 and Goldeneye, he garnered the nick name Dr Shit because of his unwavering choice of character. He was a scientist, wearing a brown suit. I have searched thought the characters but can't find it now. The year after the N64 was released, the PlayStation was released. We chipped ours and played FF VII on one TV while watching the test match on the other. James had cultivated kapoera expertise at this point and would arrive out our house in MHP through the window.

A year or two after parted ways at university, he came an played hockey with me at St Francis on a weekend. He played in goal and didn't let anything through. That evening, Laura invited me and James to a party in Brighton. It was fancy dress. I dress as an African King and James as something else (I don't remember). But I do remember he suggested that if he had a superman costume, he could borrow a wheelchair from his mum to make it complete. This was, and still is, a very funny and inappropriate image to me.
 
My girlfriend and I visited him for an evening in Surburburtan. He put us up for the night. We were on our way for a day at Kew Gardens. We met his girlfriend at the time, and played games and drank together. This was the era of the xbox. Outrun is the game I remember best.
 
I saw James last on the occasion at party immediately before my wedding. We were on a canal boat and on the Saturday evening James managed to locate us and appeared as if by magic. We hung out for a few hours before heading off. I needed to be reminded of this by my friend when we talked about James last weekend. The last correspondence I shared with him was in 2010. He wrote to me explaining his tardiness in replying to my previous message because his daughter Maisie had been born.

He is a great friend for me and I feel said to think that he is not somewhere on this world, doing something, waiting for a chance encounter to reconnect me with him.

Thursday, June 18, 2020

Some helpful stuff to make a party online:

https://github.com/theasp/docker-novnc

https://stackoverflow.com/questions/43312975/record-sound-on-ubuntu-docker-image

apt-get update
apt-get install pulseaudio socat
apt-get install alsa-utils

# Start the pulseaudio server
pulseaudio -D --exit-idle-time=-1

# Load the virtual sink and set it as default
pacmd load-module module-virtual-sink sink_name=v1
pacmd set-default-sink v1

# set the monitor of v1 sink to be the default source
pacmd set-default-source v1.monitor
 
 
 
Then use darkice and darksnow to send to icecast2. 

Wednesday, May 6, 2020

CentOS8 and vpnc

VPNC packages are missing from CentOS8 and EPEL 8. Furthermore, recent RPMs from Fedora will not install on CentOS8 because rpm is apparently missing zlib compression support. For this reason, if you want to connect to vpnc I suggest you rebuild the SRPMs. I used:

  NetworkManager-vpnc-1.2.6-4.fc32.src.rpm
and
  vpnc-0.5.3-37.svn550.fc32.src.rpm

And those packages got everything working for me from the command line on CentOS8.

Thursday, April 2, 2020

wiimms tools compile on AArch64 with Fedora 33...

I've downloaded a recent version of Wiimms tools to manipulate WBFS and wii images. https://wit.wiimm.de/

make all failes unless I added this to the LDFLAGS in the Makefile:


-Wl,--allow-multiple-definition
 
 
Thanks to this post: https://github.com/onsi/ginkgo/issues/435

Wednesday, August 21, 2019

Rename export from JB7, Brennan

I found myself having to migrate a MP3 collection off a Brennan JB7. This was good new as the JB7 wasn't fit for purpose in this case. I exported the MP3s, and the catalogue to a text file. I was surprised to discover the JB7 does not apparently use MP3 ID3 tags.

The script below corrects this by applying the catalogue data from the text file to the MP3 metadata. Use at your own risk!

import re
import eyed3
from pathlib import Path

if __name__ == "__main__":

    file = open('jb7_catalogue.txt', 'r')
    big_list = file.read().split('\n')
    cd_dict = {}
    lineno = 1    for line in big_list:
        m = re.match('^(\d)+$', line)
        if m:
            title = big_list[lineno - 2]
            if re.match('^(\d|[A-Z])+$', title):
                title = big_list[lineno - 3]
            artist = title
            if '/' in title:
                artist = title.split(' / ')[0]
                title = title.split(' / ')[1]
            if artist not in cd_dict:
                cd_dict[artist] = {}
            cd_dict[artist][title] = big_list[lineno:lineno+int(line)]
        lineno += 1
    processed = 0    for artist, album in cd_dict.items():
        print("processing {} of {}: {} .".format(processed, len(cd_dict.keys()), artist))
        for title, tracks in album.items():
            print("processing album {}".format(title))
            trackcounter = 0            for track in tracks:
                for f in list(Path("/path/to/brennan/exported/mp3/directory/").rglob("{}.mp3".format(track))):
                    if artist in str(f) and title in str(f):
                        trackcounter += 1                        mp3file = eyed3.load(f)
                        mp3file.initTag()
                        mp3file.tag.artist = artist
                        mp3file.tag.album = title
                        mp3file.tag.title = track
                        mp3file.tag.track_num = trackcounter
                        mp3file.tag.save()
        processed += 1    print("Done" )

Tuesday, October 23, 2018

pycharm debug detecting

I use pycharm. I have a program that works through tasks in parallel. When I'm debugging, however, I want to work though tasks in series. So I have this check to know if I'm running in debug:

    IS_DEBUG = True if __loader__.path.endswith('pydev/pydevd.py') else False

or, you can just use:

 __debug__


Wednesday, July 25, 2018

parse clj

if you've got a lob of Clojure data in a clj file, this gubbins will allow you to ingest it into python using the pyparsing library

            lkey = Suppress(Literal(":")) + Word(printables)
            lvalue = Forward()
            lvalue << (QuotedString(quoteChar='"', escChar='\\')
                       ^ Suppress('[') + Group(OneOrMore(QuotedString('"', escChar='\\'))) + Suppress(']')
                       ^ Suppress('{') + Dict(delimitedList(Group(lkey + lvalue), delim=',')) + Suppress('}'))
            row = Suppress("{") + Dict(delimitedList(Group(lkey + lvalue), delim=',')) + Suppress("}")

you call it with: cljdict = row.parseString(row_of_clj data)

Thursday, March 8, 2018

dockerfile for get_iplayer on Alpine linux

as subject:

FROM alpine:latest

RUN apk update
RUN apk add perl curl git perl-utils perl-dev musl-dev make gcc wget perl-net-ssleay libxml2-dev
RUN curl -L http://cpanmin.us | perl - App::cpanminus
RUN cpanm HTML::Entities JSON::PP LWP LWP::Protocol::https Mojolicious XML::LibXML CGI
RUN git clone https://github.com/get-iplayer/get_iplayer.git
CMD ["/get_iplayer/get_iplayer.cgi", "--getiplayer=/get_iplayer/get_iplayer", "--listen=0.0.0.0", "--port=8080"]

Tuesday, July 11, 2017

autossh and systemd to start a reverse ssh tunnel

I have a machine behind my firewall. When I turn this machine on, I want it to make a reverse ssh connection to another machine, which is available from outside the firewall. I use autossh to make and maintain the connection, and systemd to start the task on boot. The systemd unit file looks like:


cat /etc/systemd/system/autossh.service
[Unit]
Description=Keeps a tunnel to 'MYEXTERNALDOMAIN.com' open
After=network-online.target

[Service]
Environment=AUTOSSH_GATETIME=0
ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -i /root/.ssh/id_rsa -R 22222:localhost:22 -p 23 USER@MYEXTERNALDOMAIN.com

[Install]
WantedBy=multi-user.target


And then do:

systemctl start autossh
systemctl enable autossh
 

Thursday, April 28, 2016

booting a sd card image in qemu

I want to boot an AArch64 sd card image in qemu. The image has uefi boot and is from here http://mirror.centos.org/altarch/7/isos/aarch64/

To do this, I needed to grab some firmware to support UEFI booting on ARM. I got this from here:
http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/716/QEMU-AARCH64/RELEASE_GCC49/

This page has the details:
https://wiki.linaro.org/LEG/UEFIforQEMU

Once I did that, I could run the following command to get the image to boot.

qemu-system-aarch64 -M virt -cpu cortex-a57 -m 1024 -smp 1 -bios ./QEMU_EFI.fd -serial stdio -drive if=none,file=./CentOS-aarch64.img,id=hd0 -device virtio-blk-device,drive=hd0

Tuesday, December 9, 2014

GNOME planner page size work-around

It seems GNOME planner has a few bugs that means I can't manage to get a decent export from it. The bugs I am apparently observing include:
 + characters 'fi' are do not appear in the export to PDF.
 + specify printing to a page size that is not about Letter size.

The work-around is to:

1. Install cups-pdf driver.
2. Modify /etc/cups/cups-pdf.conf to hi-jack the in intermediatory Postscript and redirect it to a file. By default the postscript is converted to pdf, which then misses the 'fi' characters.

/etc/cups/cups-pdf.conf must contain:
 

### Key: GhostScript
##  location of GhostScript binary (gs)
##  MacOSX: for using pstopdf (recommended) set this to /usr/bin/pstopdf
##          or its proper location on your system

GhostScript /usr/bin/echo

### Key: GSCall
## command line for calling GhostScript (!!! DO NOT USE NEWLINES !!!)
## MacOSX: for using pstopdf set this to %s %s -o %s %s

GSCall %s %s; cat > %s < %s

With these configurated values, after selecting the 'cups-pdf' printer, I end up with a postscript file in /home/rhenwood/Desktop probably called something like 'Planner_job__2.pdf' or something.

The file is a postscript file, to load it into inkscape for editing, you'll need to rename it '.ps'.

Friday, September 19, 2014

hidden forums 404 with bbpress

BBpress allows private forums. I configured a private forum and the default behavior was undesirable: if you are not logged in, visiting a link to the forum returns the generic 404 page.

I was happy with the 404 page, but I wanted some special when people visited the private forum - that encouraged them to register or login.

I hacked this into my 404.php:


...




 
  if ('/forums/forum/someforum/' == $_SERVER['REQUEST_URI']) {
        _e('You need to be registered and logged in to participate in the forum.');
        } else { 
        _e( 'It looks like nothing was found at this location. Maybe try a search', 'twentyfourteen' ); echo '
'; get_search_form();
  } ?>

                        
...


Sadly, this blog publishing software doesn't do syntax highlighting, so good luck.

Thursday, September 19, 2013

htlatex and pdflatex

I'm a big fan of the gnuplot tool that has an output terminal of pdflatex. This produces a pdf figure with an overlay of latex for beautiful results. Similarly, inkscape has an output format with pdf overlayed with latex.

I had a problem with htlatex. I use pdflatex and so everything is a pdf in my figures. My overlayed output from latex, with the file extension 'pdf_tex' uses an import file and then includegraphics at the bottom. htlatex complained it couldn't find the bounding box of my pdf file... which is reasonable enough as htlatex calls pdftex and apprently doesn't support including pdfs.

My solution was to include the following in my preamble. This allows the file to continue to work as previously with 'pdflatex' and when 'htlatex' is called, the convert program is called to generate a eps file.

 \graphicspath{{figures/}{results/}}

% call as:
% htlatex myfile.tex  "" "" "" -enable-write18
%
\makeatletter
\LetLtxMacro\latexincludegraphics\includegraphics
\@ifpackageloaded{tex4ht}
    {\renewcommand{\includegraphics}[2][]{%
        \immediate\write18{s=\Ginput@path; (IFS='{}'; for i in $s; do convert ${i}#2 ${i}#2.eps; done)}%
        \latexincludegraphics[#1]{#2.eps}}}
    {\renewcommand{\includegraphics}[2][]{\latexincludegraphics[#1]{#2}}}
\makeatother

Notes: 
  • you must call htlatex with -enable-write18 so it can execute commands in the shell.
  • you must include your graphics path setup before this gubbins.

Monday, July 29, 2013

scribus, latex, and bibtex

I've been playing with scribus. I managed to get bibtex working with my rendered frame and am recording the steps here.

1. create your latex frame, and include your bibliography stuff at the end of the document as you would for a normal document. i.e.

\bibliographystyle{abbrv}
\bibliography{refer}

2. Find out what the current temporary filename scribus is using for rendering is. It will be mentioned in the 'Program Messages' listing. The file will be in the $TEMP directory.

3. Jump into that directory and copy your bib file into the $TEMP directory.
4. Run bibtex on the temporary filename.
5. Run latex again, and again, using the 'Update' button on the Editor dialogue.



Thursday, April 18, 2013

I wanted to find the difference between accessed and modified epochs of a bunch of files. The incantation below gives you this number for each item in a directory:

$ stat -c "%X %Y %N" ~/* | awk '{diff = $1 - $2; print diff, $3}'
40449 '/home/home/my_cgi'
2173034 '/home/home/run_pvr.sh'
124618 '/home/home/tools'

Saturday, December 29, 2012

powerpc-eabi-ranlib: command not found

I'm trying to compile wiimc, these two pages have proved very helpful setting up my compile environment and getting to the point of building wiimc. However, my make in wiimc directory falls over complaining:

libtool: install: chmod 644 /opt/devkitpro/portlibs/ppc/lib/libfribidi.a
libtool: install: powerpc-eabi-ranlib /opt/devkitpro/portlibs/ppc/lib/libfribidi.a
../libtool: line 947: powerpc-eabi-ranlib: command not found


The solution I found is to run make with dir1, dir2 and dir3, then to cd into the directories for dir1, dir2, dir3 and run make install separately. Like this:

$ make dir1; make dir2; make dir3
$ cd ./fribidi; make install; cd ..
$ cd ./libexif; make install; cd ..
$ cd ./libiconv; make install; cd ..

This is suitably hacky for my needs.