Category: linux

Great mysteries – number 1

Great mysteries – number 1

Hyper-v that refuses to become fullscreen!I run Ubuntu in a hyper-V session.  It works very well and handy for getting screenshots. I’ve been using a 24.04 LTS for a while and decided I needed another one to test CyberPanel. i already have Webmin on my main one so wanted a clean Ubuntu so as not to mess Webmin.  It took ten minutes to setup then another 20 minutes to install 300+ updates.

Then I edited Grub to give me a fullscreen- 1920 x 1080.  You just edit /etc/default/grub with an editor run under sudo. I use Gedit but nano will do. Just change the line to this:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash video=hyperv_fb:1920x1080"

followed by

sudo update-grub

and that should be it. Only it didn’t work in my new Ubuntu 24.04 LTS VM. I installed ifconfig from net-tools, connected to it from my Windows PC and copied grub across. I did the same with my older 24.04 LTS VM and compared the two grub files. Both identical yet one works fullscreen and the newer one doesn’t. Any ideas?

Bit of a curiosity – Rust runs slower on Windows than Linux

Bit of a curiosity – Rust runs slower on Windows than Linux

And it is a fair comparison because the Linux I’m running (Ubuntu 24.04 LTS) runs on my Windows 11 box in a hyper-V VM. I wrote a Poker hand evaluation program which loaded a text file containing lines of seven playing cards in text format TS 2C 4D sort of thing. It was seven cards because there’s two in your hand and five on the table.

There were 1,000 lines of these and the program loaded the file into memory, holding the cards in a Vec<Vec<Card>>. Then it loops through the 1,000 elements and figures out the best hand for each set.  The bit that was timed was the loop not the loading the file into memory.

The source file is on GitHub. It has the project files plus some test cards. You can try it yourself. Note at the bottom of this article is a link to a much faster version.

https://github.com/David-H-Bolton/Projects/blob/main/rust_pokerhand.zip

On my PC, the Windows one average time per hand is 768 ns. On Ubuntu is 540ns. Mad eh! The same program runs in 70% of the time on Linux compared to Windows. Both are run with this command from a terminal/command line.

cargo run --release 1000_card_hads.txt

You can also try the test_card_hands.txt but you need to enable the show_cards feature. That shows the cards but doesn’t do timing. The default is do the timing but don’t show the cards or the evaluation.

cargo run --release --features show_card test_card_hands.txt

Shows the Rust program with the feature

 

 

 

 

 

 

 

 

 

 

 

 

The test cards say what each hand is and the output at the bottom is the program working out each hand.
The file

https://github.com/David-H-Bolton/Projects/blob/main/rust_pokerhand_faster.zip

contains a much faster version. On Linux it takes about 127 ns per hand. On Windows it’s about 190 ns.

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!