Monday 28 January 2019

What is the Linux Shell

When we use linux we communicate with it to manage our resouces and "do useful things" by means of the shell.  There are a number of different shells (e.g. bash, sh, csh) but they all do the same sorts of things, file management, running applications, etc.  Shell scripts are used to automate a list of actions and make systems easier to use.  I spent a little while investigating what a shell is and found the results interesting.

When you login to linux, the operating system executes a program for you.  You can find out which with :
pi@PI3 - ~ grep pi /etc/passwd
pi:x:1000:1000:,,,:/home/pi:/bin/bash
pi@PI3 - ~

You can change a users shell with:
chsh --shell /home/pi/c/shell.o pi

The program you run is not special, it simply provides a user interface and arranges for commands to be executed, either within the program or by calling the Operating system.  For my experiment I wrote a simple program which displays a command prompt, waits for an input line, echoes the line and repeats.  It terminates when the user types exit.  I set this up as the users shell and logged in.  The program starts automatically. When exit is typed the user connection is terminated.

Stephen Brennan has written a very neat introduction to writing a shell in C which explains how to initiate processes using fork and exec system calls.
A simple introductory fork example is provided at GeeksforGeeks

Thursday 24 January 2019

Casting

Background 


For the past couple of years I have successfully used Pulse Jongo devices for playing music / radio on multiple devices.  By default you use the Pure Connect app to distribute sound but it has a useful feature using Caskeid which takes a bluetooth input to any Jongo and copies it other Jongos, thereby providing a proper multiroom system.  This formed the heart of my Multi-room Music Server (MuSe) which was based on a RPI streaming music via bluetooth to a Jongo and thence to the rest of the house.  However bluetooth has a short range and my (probably erroneous) perception was that is unreliable.

A second approach was to utilise RPIs in each room and use the multi-system networking capability of pulseaudio to send sound between them using Multicast RTP.  Each RPI is attached to a system via a 3.5mm jack plug interface.  This works ok but is restricted by the low-ish quality DAC provided on RPI.  A DAC HAT can be purchased to improve the quality (e.g. £12 from Pimoroni).  It would be preferable to stream directly from RPI to Pulse devices.  There is a much better solution for multi-room audio using multiple RPIs in the form of snapcast which can be installed through apt.  Snapserver is run on the source system and snapclient on recipient systems (which can include the source).  Music is streamed from a fifo audio output on mpd to //tmp/snapchat/fifo and then transmitted to clients and played through alsa or pulseaudio.  It was very well synchronised and sounded excellent.

Casting


I have been thinking for a while that it would be useful to cast to devices using something similar to ChromeCast audio (which has recently been discontinued).  It turns out this is really easy.

Phone-BubbleuPnP: this has a choice of where to cast music you are playing - Jongo devices such as JON and JOG are included in the list so you select the one you want and start playing music.  On a linux platform BubbleuPnP Server can be installed.  This makes it easier to connect to devices and also provides an alternative configuration called OpenHome which is a standard for devices.

Windows 10.  In the network folder Jongos are shown as media devices. Right clicking allows you to turn media streaming on for that device (or multiple devices).  You can then simply right-click on music and cast to a device, music plays straight away.

Note that uPnP, DLNA and casting are closely related.  What you need is to be able to send music to a device.  This requires an app which is DLNA or uPnP aware to initiate the communication.  We dont want client software.  It is a feature of some DLNA servers such as Windows Media Player.  It doesn't appear to work with vlc - usually my goto software for streaming functions.

This is a great solution - it is exactly what we want to do, casting from a variety of devices to Pure bluetooth/wireless Jongo connected speakers using wireless without needing to use Pure software to control them.

Linux Casting - pulseaudio-dlna

The last step is to cast from Linux to Pure devices. Music players such as mpg123 output to the alsa card by default we need to redirect the output to Jongo devices. I looked very quickly at using minidlna or servers like serviio but soon realised that pulseaudio casting is what I need.  There are two suitable solutions rygel and pulseaudio-dlna.  I successfully tried "apt-get install pulseaudio-dlna" so concentrated on its configuration.  Starting pulseaudio-dlna as user pi causes extra sinks to be added to pulseaudio.  You can then start music (e.g. using mpg123) and redirect output to the jongo.
Initially pulseaudio-dlna wouldn't connect to pulseaudio.  I put pulseaudio in system mode but then mpd would not connect to pulseaudio.  Messing around with groups and the load for module-native-protocol-tcp seemed to fix the problem and I was able to control pulseaudio in the usual way use Pulse Jongo devices.

This is an awesome result, we are using Pure devices as if they are speakers from linux and they fit perfectly to our web/mpd/pulseaudio solution avoiding the need to use bluetooth.  Much kudos is due to Massimo Mund (Masmu) for developing the pulseaudio-dlna add-on.

[update] After the euphoria of finding a neat solution using pulseaudio-dlna there was a show-stopper.  pulseaudio-dlna doesn't support the pulseaudio feature which allows you to send output to multiple devices. Pulseaudio provides module-combine-sink which permits a number of sinks to be combined and output can be redirected to all of them.  A similar effect is achievable using module loopback to "listen" to the sink.monitor stream.  Unfortunately pulseaudio-dlna doesn't support these "virtual" devices and I was unable to complete the installation.
Masmu did provide an experimental branch of pulseaudio-dlna on github which aimed to provide the necessary functionality for combined-sink but I didn't feel confident enough in the software to test it.

Thinking laterally, it occured that I could set up multiple mpd outputs to pulseaudio and route each to a single pulseaudio-dlna speaker.  It was a bit of a botch but did work except that output from the two speakers stuttered, so I didn't progress it further.

As an aside GMediaRender is of interest.  It can be installed with apt-get. When running on an RPI the RPI will show up as a media renderer in BubbleuPnP so that music can be played on the RPI speaker.  GMediaRender allows a wide variety of sinks to be used and I thought it might be possible to direct output accordingly.  I installed various gstreamer packages to identify and use sinks but nothing looked promising.  Gstreamer is an audio swiss army knife and other functions may be worth investigating in future, for example.

Linux casting part II - nodejs

There is an apparent dearth of software to send music to DLNA outputs in Linux.  Rygel appears to be Gnome GUI oriented, mkchromecast and castnow provide Chromecast output but don't recognise other DLNA devices. Simon Kusterer's castnow github page mentions another utility called dlnacast, which wouldn't work for me but it also mentioned a upnp/DLNA media-renderer client by Thibaut Seguy upon which it was based.
upnp-mediarenderer-client (UMC) is written in "server" Javascript which I haven't used before.  I installed nodejs and npm and was then able to install UMC.  Thibaut provides a sample node.js javascript program to read media and send it to DLNA. The DLNA device address is a SSDP (Simple Service Discovery Protocol) URL, which I have never seen or heard of.  Googling provided an answer so I installed gupnp-tools and ran gssdp-discover which provided a list of ssdp locations.  An SSDP location is a http URL for an XML file.  The URL includes the IP address UUID (available in windows properties) and a port number (which I couldn't find elsewhere).
UMC is based on upnp-device-client which provides the basic functions for device communication.

Once I substituted an SSDP location and a valid music URL in the sample node.js program I was able to play music on a Pure Jongo system.  Modifying the program to send output to two devices and sound came out from both simultaneously., it was a wonderful experience.  We now have a program which sends output wherever we want it.

[update]
Although our NodeJs program plays files either from a folder (e.g. /home/pi/music/runaway.mp3) or a web URL (e.g. http://rpip/music/runaway.mp3) if I tried to play an mpd stream output (http://localhost:8100/) I heard a snippet <1 second and no more.  I could tell the stream was running as it played correctly in a browser session.
I tried unsuccessfully to reconfigure MPD httpd output with different parameters.  I also tried but failed to setup shoutcast server output.
I tried to understand the UMC source code but it wasn't easy to guess its function.  I then investigated other npm audio packages in an attempt to shed light on playing / streaming music but they seemed somewhat flaky, nothing worked well so I abandoned node.js and investigated python instead.
It turns out that the node.js program works just fine.  I simply had to install icecast2 for MPD shoutcast to work and nodejs/client worked perfectly.





Monday 7 January 2019

Watching TV without an aerial

Problem

Until recently my upstairs TV was near to an aerial socket.  I have moved it to a room without an aerial but still want to watch programmes which are available through DVB (Digital Video Broadcast).  I have a Samsung Smart TV which has an ethernet/internet connection so I figure there should be a good way to stream "broadcast" channels to the TV.  My preference is for a solution which doesn't require extra hardware purchase or a subscription and it must be simple / non-technical to use.

Approaches

1 Use a (free) app on the smart TV
2 Cast programmes from an Android/IoS device
3 Play in a TV web browser session - tortuous
4 Use an extra hardware box - not that interesting
5 Use an RPI to send a stream to the TV

App (Smart IPTV)

My TV has about 100 apps which can be used to watch content.  iPlayer, all4 etc are very good but only when you want to watch a particular programme or channel.  I want a more general ability to change between any available channel.  Many of the apps such as Amazon, Netflix require a subscription and provide access to premium content; as the TV is used only occasionally this is not appropriate for me.  There are many more specialist apps which are of no interest.
Google pointed me to tvplayer which works on Samsung and shows a good range of channels.  It works well on an iPad or in a PC browser window.  Unfortunately it is not supported by my Samsung TV(s).

After further investigation I settled on using the Smart IPTV app.  It doesn't actually provide any IPTV channels but allows you to create and save your own list of channels which you can then play.  It has a nice interface so that you can see whats on using an EPG (Electronic Programme Guide) and you can surf channels using the TV program button.  It is available for both my Samsung TVs.  There is a one-off £5 subscription per device so that you can upload your channel list to their website and then download it to the TV based on Mac address.  However you can try it for a week to see if it works before paying up.

I found streaming URLs (google online tv stream url)  without too much difficulty.  

Casting

I tried casting from my (old) iPad and Samsung S5 Neo.  Both of them allowed youtube to cast (the old large Samsung TV was very temperamental) but I didn't find other apps. On the S5 you connect using Quick Connect and you are then able to play local videos and music from the phone. 
I also have an apple cable to connect my iPad to a TV.  That works when playing xvid or hdtv films with vlc.  It also works quite well playing TVplayer on the iPad and allows iPlayer and youtube. I foresee few occasions to use this in practice.