Category: linux

Raspberry Pi Sound issues- trying to fix it

Raspberry Pi Sound issues- trying to fix it

Loudpeaker
Image by OpenClipart-Vectors from Pixabay

In working through my Linux/Raspberry Pi eBook(Yes – the second eBook!), I’m up to the chapter where sounds are introduced using the SDL_mixer library. And I’ve hit two sets of problems.

It sometimes refuses to initialize the sound code.  This code below hits the LogError line:

	int success=Mix_OpenAudio(22050, AUDIO_S16LSB, 2, 8192);
	if (success==-1 ) {
		LogError("InitSetup failed to init audio");
	}

The other day it was working but not today. Now I have updated the Pi’s code (sudo apt update etc) but I wouldn’t have expected that to break it. I’ve been looking on the internet and find the whole thing a bit complicated.

I’ve got my Pi running 64-bit Raspberry Pi OS. I’ve changed the output device to headphones which plug into the headphone socket. If I run the VLC media player and tell it to play into the headphones, it will happily play the .wav files I’ve got for the asteroids game.

But if I run speaker-test, a terminal application with this command line

speaker-test -c2 -twav -l7 plughw:1,0

I get

speaker-test 1.2.4

Playback device is default
Stream parameters are 48000Hz, S16_LE, 2 channels
WAV file(s)
Setting of hwparams failed: Invalid argument

By running this command:

aplay -L

I got 71 lines of output but of these these below are the most important

output
hw:CARD=Headphones,DEV=0
    bcm2835 Headphones, bcm2835 Headphones

and the speaker-test command using the device parameter –Dhw:Headphones now worked. I’ve highlighted the bits in the aplay output needed to identify the device.

The new command  is

speaker-test -c2 -twav -l7 -Dhw:Headphones

I can now hear a female voice saying front left then front right a few times in my headphones.

So my Pi’s sound device is working; I just have to figure why SDL_mixer isn’t always. I’ll keep looking.

And the second problem which only occurs when the mixer is working, is when you play a lot of sounds. The PlayASound() function checks the result. On Windows it never had a problem but on Raspberry Pi, when you blow up a lot of asteroids say at one time, it plays a number of explosions then returns an error for each explosion after that. I think there’s only so many channels; that’s an easy fix; just ignore the error and return as if it succeeded.

How to Configure Visual Studio Code for C/C++ development

How to Configure Visual Studio Code for C/C++ development

VS Code C/C++ extensionWhen I first started with VS Code on Linux, I found the C/C++ configuration somewhat confusing.  I blundered through, wasted a bit of time and got there in the end. After a gap of a couple of years I did the same again recently on Raspberry Pi. It’s clearer in my mind now so I thought I’d explain it here. This works for Ubuntu, Raspberry Pi OS and should for most other Linuxes. (Not that I’ve tried them all…)

We’ll start with you having already installed Clang (or GCC) and VS Code, and the C/C++ extension for VS Code (shown above). So make sure those are all done.

Start by defining a Folder for VS Code. VS code doesn’t use projects but it manages everything relative to the currently defined Folder.  It’ll ask you to open a folder initially. That’s where your source code etc will go. I created a folder called examples under my home folder and used that.

To compile anything C/C++ you also need two json files. These files are

  • tasks.json
  • c_cpp_properties.json

They are held in a hidden folder called .vscode in your current folder. Press F1 and you’ll see a popup menu. Type in C/C++ and you’ll see all the C/C++ items. Select C/C++: Edit Configurations (JSON). It’s highlighted below.

Vs Copde C++ menu

Now if you click that, and look in the folder examples you’ll see nothing but if you know how to view hidden files using the files utility (as shown below). Then you’ll see the folder .vscode.  On Raspberry Pi the file explorer always shows hidden files.

Show hidden files in files utility Now look in that folder and you’ll see c_cpp_properties.json.

Next we want tasks.json. On the Terminal menu, click the bottom item which is Configure Default Build Task

It’ll ask you to select the clang  build active task so click that and voila you now have tasks.json open in the editor.

Vs Code Configure Default Build Task

Build Active File

 

 

 

 

 

 

 

 

 

 

Now I’ve created the standard hello world file in the file hw.c.

#include <stdio.h>

int main() {
  printf("Hello world\n");
  return 0;
}

So just do Terminal/Run Build Task and it will have clang compile the currently opened file. If you get terminal failed to launch (exit code: -1) then it’s likely that your hello world source file was not the currently opened file in the editor. You can see which file is open because its tab is brightest.

Note that hw.c is brighter than tasks.json on the left. On the right, the open file is tasks.json and its tab is brighter.

Open file in VS Code

Tasks.json is open

So what are the json files for?

The c_cpp_properties.json lets you specify include file paths.  For instance if you have the SDL files installed, the include files are in /usr/include/SDL2

SDL2 include files

Note you can install SDL on linux by following these instructions.

The tasks.json file lets you specify which files are to be included and also linked.

Here I’ve just shown the args section from a tasks.json used to build SDL2 games.

	"args": [
		"-g",
		"${file}",
		"${workspaceFolder}/hr_time.c",
		"-o",
		"${fileDirname}/${fileBasenameNoExtension}",
		"-lSDL2",
		"-lSDL2_image",
		"-lSDL2_mixer",
		"-lm"
	],

The -g option includes files. The ${file} is the current opened file and {workspaceFolder{} specifies the current folder where the file hr_time.c (used for timing). The -l is for linking files and links SDL2, SDL2_image and SDL2_mixer.  The last -lm links math(s) code; technically the -l{name} flag tells the linker to link against lib{name}. So -lm links against libm, the c math library.

A minor whinge about Linux

A minor whinge about Linux

Screenshot of Virtualmin update screenI’ve been a Windows developer since the late 1990s and I got into Linux about 2008. I’m still a Windows developer but now that .NET applications can run on Mac and Linux as well as Windows, it makes it easier to write software in C# that runs on Linux.  Using a Linux VPS is probably the cheapest way to do that.

I still use Visual Studio on Windows for developing and just by changing the publish target can run it on Windows or Linux. If you manage a VPS as I do, you want to keep it up to date and that’s what my whinge is.

It used to be that Windows was a pain with having to reboot after installing software. These days that’s only when you’re doing a major update. But Linux? I’m finding that I have to reboot it after an update on average perhaps once a week. This week it happened twice! I grabbed a screenshot to show it.

The screenshot is of the bottom of the VirtualMin update page. I use Virtualmin for administering it because I prefer to spend my time programming. That blue Reboot Now button appeared because one of the packages that got updated required a reboot. I don’t think there’s anything that can be done except click it; the reboot has to happen and only seems to take a minute at most.  It’s just the irony that for years people complained about Windows reboots and now it’s actually Linux that is the major culprit!

And with a bit of help I got it fixed

And with a bit of help I got it fixed

Visual Studio Publish Target runtime dialogThanks to suggestions in the Reddit CSharp subreddit (you can view the entire thread here), I fixed the missing file issue and SkiaSharp is now happily outputting graphics on the VPS.  I’m referring to the More Programming Joys blog entry I posted yesterday.

There were two things that were needed to fix it.

  1. Add a package to the solution. This was the SkiaSharp.NativeAssets.Linux package and I used Nuget to add it to my Windows solution. If you haven’t used Nuget, it’s a great package manager and makes it very easy to add packages.
  2. On the Visual Studio Publish page, I needed to change the Target Runtime to linux-x64. That’s the dialog above. When I clicked the Publish it put all the files including the library that was missing (libSkiaSharp.so) into the Target location and once uploaded it worked.
More Programming Joys

More Programming Joys

Game MapSo I’ve been doing some .NET programming. First on Windows because I can debug it there then “Publish it” which puts all the files (compiled in release) needed, including any dlls into one folder and upload it to a VPS using WinSCP. I’ve also got a terminal session connected by Putty. I use Serilog for logging and SkiaSharp for graphics.

First bug was a missing file but it was a stupid error on my part. I had the file in a path under the home folder and had used ~ in the file’s path. You can use ~ in Bash- it means your home folder, but not in a file path in an application. Putting in the full path fixed the bug. D’oh.

Because it’s .NET (6) that I’m using, you don’t get configuration stuff the same as you did with .NET Framework. I store some config information in a file and define the path with these lines of code which work on both Linux and Windows.

 bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
 var appSettingsFilePath = IsWindows ? @"c:\turfwar\twConfig.json" : "/home/user/turfwar/twConfig.json";

I like Serilog ( with project on Github at ). Nice and simple logging but flexible enough. As this application is a command line app run whenever, it’s easier to view the logs afterwards.

Why use SkiaSharp?

I was quite happy to use System.Drawing but according to this, There are issues with libgdiplus. So I thought I’d try SkiaSharp as I’m doing stuff with Flutter and Skia is the library that underpins that. This is what it takes to create a 100 x100 grey coloured Bitmap in SkiaSharp, add yellow dots and save it to disk as a .jpg. That’s what you see up above.

        internal void SaveBitMap(int id, string filename, Gang gang)
        {
            var info = new SKImageInfo(100, 100);
            using var surface = SKSurface.Create(info);
            SKCanvas myCanvas = surface.Canvas;

            // clear the canvas / fill with white
            myCanvas.DrawColor(new SKColor(0x99, 0x99, 0x99));

            // draw the dots, one for each block
            foreach (var block in Blocks)
            {
                if (block.Owner == id)
                {
                    myCanvas.DrawPoint(block.X*5/2, block.Y*5/2, SKColors.Yellow);
                }
            }

            // Now save to filename
            var mainCanvasImage = surface.Snapshot();
            var TempTIFbitmap1 = SKBitmap.Decode(mainCanvasImage.Encode());
            using (var image = SKImage.FromBitmap(TempTIFbitmap1))
            using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 100))
            {
                // save the data to a stream
                using (var stream = File.OpenWrite(filename))
                {
                    data.SaveTo(stream);
                }
            }
        }

It works fine on Windows but on Linux, (Ubuntu 20.04) I hit bug #2. “System.TypeInitializationException: The type initializer for ‘SkiaSharp.SKImageInfo’ threw an exception.”. And that’s where I am at the moment.  This is similar.  I’ll keep you informed.

My PC is broke… plan b

My PC is broke… plan b

Linux Tux
Image by FreeCliparts from Pixabay

I repurposed my wife’s old Toshiba laptop a year ago, installing Ubuntu 20.04 LTS on it to replace Windows 10. Today my Windows PC broke. It appears that the cooler has given up after five and a half years faithful service. The warranty of course was only for five years… I just have to make sure it is the cooler and not the PSU has gone and get it replaced.

I know it was overheating because I rebooted after 30 minutes and into the UEFI BIOS. There I watched the temperature climb at a rate of 1C every second. When it hit 75 C and the text turned red, I knew that it was overheating.

So I dug out the Toshiba and upgraded Ubuntu on it finally figuring out the password after 20 or so tries. Only 560 packages needed upgrading! That took a while and I’ve also been installing other software since. My VS Code was that old that it won’t actually update. When I did the Linux version of Asteroids I tested it on here.  It seems I have to download a recent version of VS Code which will let it upgrade with apt.

It shouldn’t but it never fails to surprise me how quick Linux is. This laptop has an I3 CPU and a hard disk and is about . It has 4 GB of RAM; I upgraded that a couple of years ago to try and speed up Windows. Even after upgrading Windows 8 to 10 and removing some of the Toshiba bloatware, it was never that quick. But now it flies.

Thankfully Chrome had the password to the site so I was able to login and write this from the laptop. I may have to do without my Windows PC for a week or two…

lldb-mi no longer exists

lldb-mi no longer exists

lldb vs code extensionsThis is debugging vs code with lldb. It seems as of clang-10, it’s no longer supported which is a pita. I’d been working on the Onslaught code and something wasn’t working so I thought I’d try to debug it.  However the debugger wouldn’t start. Investigating a bit further and I found this discussion thread on the GitHub cpp tools.

I have to say this. I find Linux development quite frustrating at times because of things like this. Something that worked in an earlier version of clang has been removed. Why? There’s a similar issue with Ubuntu 18.04 compared to 20.04 running in Hyper-V VM. With 18.04 I can use the clipboard to copy and paste between Windows and Ubuntu, but so far I have been unable to do it in 20.04.

You spend ages wasting time trying to find answers. I find Windows development with C# much less problematic. Open source developers sometimes don’t appear to take the needs of their users as seriously as say commercial developers do.

So now I’m looking a for a better way to debug C/C++ programs from vs code. There is a lldb – vs code adapter as well as native debug and Code LLDB (see screenshots) so I’ll investigate and see if any of these work. Or I can just study my code and work out in my head why it isn’t working!

Interesting article on the state of Linux gaming

Interesting article on the state of Linux gaming

Linux playYes it’s on Medium, but its worth a read. The gist of the article and this one is saying that there’s a problem with Linux for gaming. Also that anyone new to Linux gaming is looking online and finding old articles that suggests that SteamOS is a good distro to use while in reality it hasn’t been updated in a while.  The problem is that Valve (creators of Steam) have let SteamOS languish.

Though its not as if Valve have ignored Linux gaming. They released an open source tool Steam Proton (Link goes to it on GitHub) that lets you run many Windows games (6000 or so)  on Linux. The Linux Steam client includes a copy of Proton.

The problem though is that this hasn’t really helped attract more people to Linux gaming. People I know either play games on Windows or on consoles like PlayStations.  Linux is perceived, wrongly I’m sure as being an inferior game platform.

How to move a SDL project from Windows to Linux

How to move a SDL project from Windows to Linux

SDL Logo
The SDL Logo is from libsdl.org

It’s not actually that hard to do, there’s just a few things that are different between C and Linux, specifically between MSVC and GCC /Clang.. I did this when I wrote the Asteroids game in the book.

Originally I developed it on Windows then moved it to Linux (Ubuntu) and then I added the bits to have it work on a Raspberry Pi. It worked on the Pi more or less as is on Ubuntu but I added support for game pad, detecting that it was on a Pi and displaying the temperature.

Here’s what I’ve found is different between MSVC and GCC/Clang.

  1. The safe string functions. MSVC has the _s functions so instead of strcpy, there’s strcpy_s on MSVC. This doesn’t exists in GCC/Clang but there are similar functions with an n in the middle e.g. strncpy. In future I’ll create a macro for each function that uses the appropriate type so the compiler will pick the correct type.   However it seems even strncpy may not be all that safe. If there is no \0 in the n characters then the copied string won’t have a terminating \0 and thus could still blow up.  This article says that in order of safety it goes like this with strcpy least safe and strlcpy the most.
    strcpy < strncpy < snprintf < strlcpy

    so maybe I should be using strlcpy instead.

  2. The include path for SDL in GCC/Clang is “SDL\SDL.h” not “SDL.h” as it is in MSVC. Again this could be fixed with a macro prefix for the SDL path so all #include works correctly on either system.

3.  I found that the file type was wrong. This wasn’t just a matter of CR/LF versus LF which you get between Windows and Linux (CR = Carriage return, LF = Line feed). Somehow the Windows file had a different UTF encoding type to what GCC/Clang expected and the compiler did not like it. However Visual Studio Code shows you what encoding it is (on the bottom of the edit window) and lets you change it, so no harm done. You may need to do this once on each file you’ve moved from Windows to Linux.

4. I found that the time header file in Linux needed a bit of work to make it compile. The standard for this dictates that differences aren’t done to the header file but by adding in additional headers.

So I’ll look into strlcpy.

 

 

 

Hyper-V VMs are not all the same

Hyper-V VMs are not all the same

Hyper-V Ubuntu installOne of the big problems with Hyper-V and Ubuntu in particular is the clipboard or lack of it. I had 18.04 LTS installed with an X Org RDP login. This worked perfectly and I could have a full screen in my Monitor and could copy/paste.  Don’t underestimate copy/paste.

It’s a real PITA if you have to use say WinSCP to copy files over. I think WinSCP is excellent BTW but the amount of labour saving that copy/paste has done since some genius thought it up is immeasurable. That and allowing the full screen of the monitor are two highly important things.

Sadly the 20.04 LTS didn’t seem to allow it. Copy/paste didn’t work between my Windows PC (host) and Ubuntu (guest). There’s nothing worse than losing a feature you’ve grown fond of.

If you follow these instructions for creating a Hyper-V 18.04, you get the screen size popup but not with 20.04 LTS. For that you have to follow these instructions!

It’s things like this that suggest why Linux Desktop has never been that successful. You can waste many hours getting simple things working and sometimes like Copy/Paste they break between versions. And this is with Ubuntu, probably the biggest and best known and supported Distro.