Raspberry Pi 3B FM Broadcasting… It can be done, but I want more.

Posted on Updated on

This is a discovery document and ramblings…  I’ve added to it all day and processed thoughts. I may adjust it and fix it, but, this is as it stands, as it took me about a day to compile.



This is going to be an interesting.



End Game:

Host a radio station on the Pi that just works. You turn it on and it starts transmitting a program.

In doing this…

Multiple ways:

Route Any audio that comes from the Pi to be transmitted via the FM TX.


Read an M3u file and feed that to a audio player that pipes to the FM TX.


Hopefully to be able to use StationPlaylist Creator and Studio.


So far, only 1 version of a transmitter has succeeded.



Only Plays WAVE files

sudo ./fm_transmitter -f 91.3 -r star_wars.wav












Maybe this could work:


Haven’t Tried:





Broadcast from a usb microphone (see arecord manual page for config)

arecord -d0 -c2 -f S16_LE -r 22050 -twav -D copy | sudo ./fm_transmitter -f 103.3 -

Where it redirects a device to the FM TX…

Maybe I could set up a device/ALSA or something, and pipe that in to the TX?



Very Helpful, but didn’t work.



Someone else wants the same thing:

Is there a way to redirect all audio to the FM transmitter? #18


The different Pins. We need GPIO 4, which is PIN 7




Other information:



Mostly idiots talking about “breaking the law”. At under 100mw, which this isn’t even close, it’s perfectly legal. But, it does contain some good RF stuff.

Easily Turn Your Raspberry Pi into an FM Transmitter


This is a kernel module for playback… Not sure on the status or if it works though.










I think this is the key:


The easiest way to basicly play anything you want to, is by using audio loopdevices.
Simply load snd-aloop via modprobe (or just add it to /etc/modules), and you are ready to go.
use a terminal to start PiFm:
sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 - | sudo ./pi_fm_rds -audio -

then you are free to play whatever you want with whatever program you want, as long as it allows you to specify the audio device you want to use to output to.
for example:
sudo aplay -D hw:Loopback,0,0 "FILE"

if you want to, you can even define the loopdevice as your standard output device, by changing the .asoundrc in your home directory to
# .asoundrc pcm.!default { type plug slave.pcm "hw:Loopback,0,0" }

That way you can even use VLC within X to transmit your audio.







This generates a new loopback device which wasn’t there before

sudo modprobe snd-aloop

Maybe Stationplaylist can actually play a file through this method… Not that it can see the loop-back audio driver?


sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 - | sudo ./pi_fm_rds -audio -


Trying: https://github.com/F5OEO/PiFmRds

This is the latest version of the PiFmRds in Github.

Run this as well, Otherwise the build will fail when compiling it.


sudo apt-get install libsndfile1-dev


wget https://github.com/F5OEO/PiFmRds/archive/master.zip
unzip master.zip
cd PiFmRds-master/
cd src

Fails to build.


This builds:

git clone https://github.com/ChristopheJacquet/PiFmRds.git
cd PiFmRds/src
make clean

This will broadcast something on 107.5

sudo ./pi_fm_rds

This Demo will play a file in slow motion ( or correctly without the loopback I think)

sudo ./pi_fm_rds -audio sound.wav


Shows the Audio Devices.

arecord -L


This transmits, but it locks up the device after about 2 seconds.

sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 - | sudo ./pi_fm_rds -audio -




pi@raspberrypi:~/fm_transmitter-WAVE_Only $ sudo ./fm_transmitter -f 107.9 star_wars.wav


sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 – | sudo ./fm_transmitter -f 107.9 -audio –





Get the sourcecode from here:




sudo apt-get install make gcc g++


cd fm_transmitter-WAVE_Only/

sudo modprobe snd-aloop

sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 – | sudo ./fm_transmitter -f 107.9 -audio –


Even at 22.5k it still stutters. A little less, but still noticeable.

sudo arecord -fS16_LE -r 22500 -D hw:Loopback,1,0 -c 2 – | sudo ./fm_transmitter -f 107.9 -audio –



pi@raspberrypi:~/fm_transmitter-WAVE_Only $ sudo modprobe snd-aloop
pi@raspberrypi:~/fm_transmitter-WAVE_Only $ sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 – | sudo ./fm_transmitter -f 107.9 -audio –
Playing: STDIN
Recording WAVE ‘-‘ : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo

Right Click on the Speaker icon at the top. Set the Audio to LoopBack

Raspbian VLC should work with some Audio files and push play.

It should work!


CPU Stays at about 30%+

Audio also stutters slightly


install WineTricks and  Q4Wine




Currently I can’t get SPL to output to the Loopback – even though it says it is.

The WineCFG test outputs to the correct location, just not SSL.


Trying to set it up so it’s automatic a little.

Create the following files with a +777 permission and you should be good. Just change the location of the fm_transmitter file.



sudo modprobe snd-aloop
#sudo arecord -fS16_LE -r 44100 -D hw:Loopback,1,0 -c 2 - | sudo /home/pi/fm_transmitter-WAVE_Only/fm_transmitter -f 107.9 -audio -
sudo arecord -Dhw:Loopback,1,0 -fS16_LE -r44100 -v -c 2 - | sudo /home/pi/fm_transmitter-WAVE_Only/fm_transmitter -f 107.9 -audio -



sudo kill -9 $(pidof arecord)
sudo pkill -9 -f arecord
sudo kill -9 $(pidof fm_transmitter)
sudo killall -9 fm_transmitter
sudo pkill -9 -f fm_transmitter



Current conclusion: 20180317

I can now stream from any native program that is happy to follow the audio output rules of the system. VLC works fine, as does XMMS.

However, both programs have mild stutters about once a second for about .001 of a second. It’s minor, but it is noticeable. It’s like a CD with a minor glitch skip. Frustrating.

This isn’t there when “sudo ./fm_transmitter -f 91.3 -r star_wars.wav” is called. So, there is a buffering/hangup issue when using arecord to pipe the audio through, of which I need to investigate further and see if there are optimisations that can be made.

This current set up also using a consistent 30% of CPU resources in the X windows setup of the Noob version of the pi OS.

I suspect the problem could relate to the fact that it’s MP3s being upsampled to a WAVE @ 44.1khz stereo, captured, and then pushed out to the FM TX program. That’s a lot of data for a small processor.




Another possible option?

I could use the web streamer in SPL and capture that and feed it to the arecord. More investigation required, but I do recall someone mentioning that somewhere.


I’m trying IceCast2


sudo aptitude install icecast2

I wonder if I could use this as a template…

sox -t mp3 http://www.linuxvoice.com/episodes/lv_s02e01.mp3 -t wav -  | sudo ./pi_fm_rds -audio -


My Current Idea? – which could just put extra strain or processing on the device… but, it could do the opposite…?

Set SPL Output as NULL.

Set up the Streaming to the location newly created IceCast2 host.

So, go from SPL -> Icecast2 URL.

sox -t mp3 http://localhost/stream.mp3 -t wav - | sudo /home/pi/fm_transmitter-WAVE_Only/fm_transmitter -f 107.9 -audio -


After setting this up and SPL correctly connecting to the IceCast2 server, this doesn’t work because of the following error:

Playing: STDIN
sox WARN wav: Length in output .wav header will be wrong since can’t seek to fix it


It plays for about 3 seconds and then fades.



Next Stop… Asking the ExaGear guys. They are supporting wine, or similar. Time to see if they can assist…


Either that, or find a new player that read the m3u or pls files and have StationPlaylist Creator generate new files via CLI on a schedule.

The audio player/FM service could be stopped and started on a regular hourly basis so it keeps a rough time?


After letting it run overnight, I came to find that the radio broadcasting had stopped. This is probably because arecord has a time limit on it… Could be wrong.

Also, I’m thinking that the slight delay in the broadcast could be related to the speed of the card I’m using: Just a thought.





Observations and other research

ExaGear needed to have winbind install to run the demo version of StationPlaylist Creator

My result:

cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq





XMMS2 – “Winamp”:


After an original night trial without any audio radio tests to see how the pi could handle it, SPL Locked up overnight for some reason. Probably because it is a demo version.

When the fridge compressor pump kicked in to keep the fridge cooler, it must have caused a surge/brownout, as the pi rebooted, and the digital radio turned itself on… all the defaults.


php 7.1 and nginx not storing sessions

Posted on

Depending on your server settings, you may find every now and then and installing new modules, or program updates through yum, can break things.

Well, this happened to me.

I can’t explain what went wrong exactly, but after attempting to install the php mbstring extension, I had the whole thing go belly up.

After some frantic searching, I was able to solve the problem (eventually) by giving access once again to the nginx server, so it could store sessions.

Strangely enough, it was a permission error, where the location where php7.1 wanted to store it’s files had mysterious changed, or, the permission for that path had changed.

The solution was found in /var/opt/remi/php7X of all places.

Also, to help you find the problems, just look in your log files. It will often tell you what is wrong, or as to why it can’t do a certain task.

I thought I’d just let everyone know my quick thoughts.

Drive, Folder, Files Browsing VB.net 2107

Posted on Updated on

Finally, after searching the internet and finding nothing without modification I want to release some code, as it used be in the old VB5 and VB6 days.

I modified the code I’d found originally, and can’t remember which site did it, because most didn’t work at all. This however will get you the basics back using VB.NET.

(EDIT) Actually, this is the original code.  A HUGE THANKS!!! http://www.dreamincode.net/forums/topic/400525-treeview-drive-folder-and-file-explorer/



Imports Microsoft.VisualBasic
Imports System.IO 'File Operations 

Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub

Private Sub TV_Explorer_BeforeExpand(sender As Object, e As TreeViewCancelEventArgs) Handles Tv_Explorer.BeforeExpand
 Dim DrvIsReady As Boolean = (From d As DriveInfo In DriveInfo.GetDrives Where d.Name = e.Node.ImageKey Select d.IsReady).FirstOrDefault

If (e.Node.ImageKey <> "Desktop" AndAlso Not e.Node.ImageKey.Contains(":\")) OrElse DrvIsReady OrElse Directory.Exists(e.Node.ImageKey) Then
 AddChildNodes(e.Node, e.Node.Tag.ToString)

ElseIf e.Node.ImageKey = "Desktop" Then
 Dim PublicDesktopFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory)
 Dim CurrentUserDesktopFolder As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
 AddChildNodes(e.Node, CurrentUserDesktopFolder)
 AddChildNodes(e.Node, PublicDesktopFolder)

 e.Cancel = True
 MessageBox.Show("The CD or DVD drive is empty.", "Drive Info...", MessageBoxButtons.OK, MessageBoxIcon.Information)
 End If
 End Sub

Private Sub TV_Explorer_AfterCollapse(sender As Object, e As TreeViewEventArgs) Handles Tv_Explorer.AfterCollapse
 End Sub

Private Sub TV_Explorer_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles Tv_Explorer.AfterSelect
 TxtBx_Path.Text = e.Node.Tag.ToString
 End Sub

Private Sub TV_Explorer_NodeMouseDoubleClick(sender As Object, e As TreeNodeMouseClickEventArgs) Handles Tv_Explorer.NodeMouseDoubleClick
 If e.Button = MouseButtons.Left AndAlso File.Exists(e.Node.Tag.ToString) Then
 Catch ex As Exception
 MessageBox.Show(ex.Message, "Error...", MessageBoxButtons.OK, MessageBoxIcon.Error)
 End Try
 End If
 End Sub

Private Sub AddSpecialFolderRootNode(SpecialFolder As SpecialNodeFolders)
 Dim SpecialFolderPath As String = Environment.GetFolderPath(CType(SpecialFolder, Environment.SpecialFolder))
 Dim SpecialFolderName As String = Path.GetFileName(SpecialFolderPath)

AddImageToImgList(SpecialFolderPath, SpecialFolderName)

Dim DesktopNode As New TreeNode(SpecialFolderName)
 With DesktopNode
 .Tag = SpecialFolderPath
 .ImageKey = SpecialFolderName
 .SelectedImageKey = SpecialFolderName
 End With

 End Sub

Private Sub AddDriveRootNodes()
 For Each drv As DriveInfo In DriveInfo.GetDrives
 Dim DriveNode As New TreeNode(drv.Name)
 With DriveNode
 .Tag = drv.Name
 .ImageKey = drv.Name
 .SelectedImageKey = drv.Name
 End With
 End Sub

Private Sub AddChildNodes(tn As TreeNode, DirPath As String)
 Dim DirInfo As New DirectoryInfo(DirPath)
 For Each di As DirectoryInfo In DirInfo.GetDirectories
 If Not (di.Attributes And FileAttributes.Hidden) = FileAttributes.Hidden Then
 Dim FolderNode As New TreeNode(di.Name)
 With FolderNode
 .Tag = di.FullName
 If Tv_ImgList.Images.Keys.Contains(di.FullName) Then
 .ImageKey = di.FullName
 .SelectedImageKey = di.FullName
 .ImageKey = "Folder"
 .SelectedImageKey = "Folder"
 End If
 End With
 End If

Dim files As String()
 Dim file As String
 files = IO.Directory.GetFiles(DirPath) 'Your directory
 For Each file In files
 Dim FileInfo As New FileInfo(file)
 File_ListView.Items.Add(FileInfo.Name) 'adds all files in directory to listbox
 Catch ex As Exception
 MsgBox("You Can't Enter The Folder", MsgBoxStyle.Critical)
 End Try

Catch ex As Exception
 MessageBox.Show(ex.Message, "Error...", MessageBoxButtons.OK, MessageBoxIcon.Error)
 End Try
 End Sub

Private Sub AddSpecialAndStandardFolderImages()
 AddImageToImgList(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Folder")

Dim SpecialFolders As New List(Of Environment.SpecialFolder)
 With SpecialFolders
 End With

For Each sf As Environment.SpecialFolder In SpecialFolders
 End Sub

Private Function AddImageToImgList(FullPath As String, Optional SpecialImageKeyName As String = "") As String
 Dim ImgKey As String = If(SpecialImageKeyName = "", FullPath, SpecialImageKeyName)
 Dim LoadFromExt As Boolean = False

If ImgKey = FullPath AndAlso File.Exists(FullPath) Then
 Dim ext As String = Path.GetExtension(FullPath).ToLower
 If ext <> "" AndAlso ext <> ".exe" AndAlso ext <> ".lnk" AndAlso ext <> ".url" Then
 ImgKey = Path.GetExtension(FullPath).ToLower
 LoadFromExt = True
 End If
 End If

If Not Tv_ImgList.Images.Keys.Contains(ImgKey) Then
 'Tv_ImgList.Images.Add(ImgKey, Iconhelper.GetIconImage(If(LoadFromExt, ImgKey, FullPath), IconSizes.Large32x32))
 End If

Return ImgKey
 End Function

Private Enum SpecialNodeFolders As Integer
 Desktop = Environment.SpecialFolder.Desktop
 Favorites = Environment.SpecialFolder.Favorites
 History = Environment.SpecialFolder.History
 MyDocuments = Environment.SpecialFolder.MyDocuments
 MyMusic = Environment.SpecialFolder.MyMusic
 MyPictures = Environment.SpecialFolder.MyPictures
 MyVideos = Environment.SpecialFolder.MyVideos
 Recent = Environment.SpecialFolder.Recent
 UserProfile = Environment.SpecialFolder.UserProfile
 End Enum

End Class

eBay Parcel Tracking!!!??

Posted on

So maybe you are like me and you collect the odd parcel from eBay every now and then, but they give you a crazy tracking number that doesn’t work?

Well, you need to check out this site, which will tell you where your package is and where it’s going.

This is especially helpful when Australia Post doesn’t specially know either.

Enter this example number, and you’ll see what I’m talking about: UPAAB000000234365152
(It’s not my order)



This isn’t UPS, USPS or HDL. It’s for eBay postage.

Raid6 Recovery on a ReadyNAS Ultra 6

Posted on Updated on

Ok, well this was the update I didn’t want to ever need to do. But, I’ve done it and so far it’s been sucessful.

About a month ago, I was sitting using my computer, and for no “apparent” reason, I got a message saying “Server is shutting down”. I thought that was weird, but it did as it said. My NetGear ReadyNAS Ultra 6 shut itself down, and didn’t want to come back up – at all.

I didn’t know what to do, so I let it sit for a while.

I’ve always kept the NAS up to date with the official stock OS of RAIDiator 4.X, so I knew it probably wasn’t going to be something weird of a customisation I’d done.

A long time ago, I’d read that this NAS had a VGA out port on the motherboard. I’d never looked at this before, but I thought that may be my go-to. So I pulled the guts out of the board to see what the problem was.


I figured a drive may have died, but I didn’t know which one, or how to diagnose the issue, because the NAS just wouldn’t boot. In the past I’d received emails telling me that drives were failing and that it was going to shut down, but this time… I didn’t get those messages.

So, I travelled to my local computer shop and bought a new 3TB WD Red drive, and a VGA breakout port… turns out while the computer geek who served me, didn’t notice (nor myself) that the pins on the AUS GEFORCE GT 710 card was actually 8 pins and not the required 15 pins. So… that was a waste of $40.

Instead I went to JayCar and collected all the bits I needed to make sure I could do this thing and potentially read any output of the VGA port on the board. At this stage I didn’t even know if I could do it…


So, I built all the bits and then when I booted the device… It showed up on the screen… BINGO! 🙂


I had a dead drive.

This NAS is just your standard computer with bit of custom work for the NAS stuff. The BIOS told me it was all normal and that the drive was dead. So… I took out my Seagate 3TB drive – yeah, you know the type… What ever you do in the future – stay clear of these drives ST3000DM001. Trust me. Just look them up in Google, and you’ll see what I’m getting at.

I replaced it with the WD Red drive and boom, it started up and started a resync.


I had to move the NAS to a different location and was a bit hesitant to switch it off during a resync, but, if a controlled shutdown is performed, a resync will continue safely.

Everything was going great.

I fixed up the notifications so I’d get alerted via email and also push alerts (via Pushover) and it was all good. Actually, while I’m on that, you should look in to Pushover.net for real-time alerts on your phone or device. It’s brilliant.

So, the big scary problem happened next.

I was tidying up around the place and a small power plug knocked the top of the NAS. The NAS beeped (which is weird, ’cause it beeps when the front door opens too) and I received a series of messages on my phone too…

Those messages were the very big concern.

***** File system check performed at Sun Oct  8 13:22:00 EST 2017 *****
fsck 1.42.12 (29-Aug-2014)
fsck.ext4: No such file or directory while trying to open /dev/c/c
Possibly non-existent device?


The paths for the shares listed below could not be found.  Typically, this occurs when the ReadyNAS is unable to access the data volume.
[Sun Oct  8 13:22:17 EST 2017]


Oh dear… This meant bad news. really bad news.

So, I did some digging.

My Admin panel said “No Volumes”. I nearly freaked. My computer couldn’t located the shared drive paths either.

After doing some searching, I found a few answers I wasn’t sure about, but it couldn’t hurt.

I logged in via FTP. As suggested, there was nothing in the “/c/” path, or in the “/mount/c” path. So… this was troubling.

What I discovered which was worse is that RAID6 array had failed to mount, or load, or something. This was bad. 9TB of data missing…

This was as bad as it gets.

Or was it?

Below is a list of the commands I typed via SSH, and you can clearly see the results.

In case you don’t know how to SSH to your box, you should have already installed the Enable Root SSH Access” Addon. If you haven’t, then you’ll need to find a way in before you run these commands.

ReadyNas:~# cat /proc/mdstat
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4] 
md1 : active raid1 sda2[0] sdf2[8] sde2[7] sdd2[6] sdc2[9] sdb2[1]
 524276 blocks super 1.2 [6/6] [UUUUUU]
md0 : active raid1 sda1[0] sdf1[6] sde1[8] sdd1[7] sdc1[9] sdb1[2]
 4193268 blocks super 1.2 [6/6] [UUUUUU]
unused devices: <none>

ReadyNas:~# mdadm --examine
mdadm: No devices to examine

ReadyNas:~# cat /proc/mdstat 
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4] 
md1 : active raid1 sda2[0] sdf2[8] sde2[7] sdd2[6] sdc2[9] sdb2[1]
 524276 blocks super 1.2 [6/6] [UUUUUU]
md0 : active raid1 sda1[0] sdf1[6] sde1[8] sdd1[7] sdc1[9] sdb1[2]
 4193268 blocks super 1.2 [6/6] [UUUUUU]
unused devices: <none>

ReadyNas:~# mdadm --examine 
mdadm: No devices to examine

ReadyNas:~# mdadm --assemble --scan --assume-clean
mdadm:option --assume-clean not valid in assemble mode

ReadyNas:~# mdadm --assemble --scan 
mdadm: /dev/md/001AD40EDDAC:2 assembled from 5 drives and 1 rebuilding - not enough to start the array while not clean - consider --force.
mdadm: No arrays found in config file or automatically

ReadyNas:~# mdadm --scan 
mdadm: --scan does not set the mode, and so cannot be the first option.

ReadyNas:~# mdadm --assemble --scan
mdadm: /dev/md/001AD40EDDAC:2 assembled from 5 drives and 1 rebuilding - not enough to start the array while not clean - consider --force.
mdadm: No arrays found in config file or automatically

ReadyNas:~# mdadm --assemble --scan --force
mdadm: Marking array /dev/md/001AD40EDDAC:2 as 'clean'
mdadm: /dev/md/001AD40EDDAC:2 has been started with 5 drives (out of 6) and 1 rebuilding.

ReadyNas:~# cat /proc/mdstat 
Personalities : [raid0] [raid1] [raid10] [raid6] [raid5] [raid4] 
md127 : active raid6 sda3[0] sdf3[6] sde3[8] sdd3[7] sdc3[9] sdb3[2]
 11702178816 blocks super 1.2 level 6, 64k chunk, algorithm 2 [6/5] [UU_UUU]
 [>....................] recovery = 2.4% (71975936/2925544704) finish=1255.9min speed=37866K/sec
md1 : active raid1 sda2[0] sdf2[8] sde2[7] sdd2[6] sdc2[9] sdb2[1]
 524276 blocks super 1.2 [6/6] [UUUUUU]
md0 : active raid1 sda1[0] sdf1[6] sde1[8] sdd1[7] sdc1[9] sdb1[2]
 4193268 blocks super 1.2 [6/6] [UUUUUU]
unused devices: <none>


As you can see, the md127 listing, this meant that the RAID6 was back! And… It was ready to resync!!

So, I cleanly restarted the box, and it’s now resyncing the data and all the shares are  working again. All shares are back. And I’m super happy I still have my data! 😀


I hope this helps someone. ‘Cause it was difficult to know what to do, but it was fairly simple in the end.

Getting the IPs from AWS on a load balancer using Piwik Stats

Posted on Updated on

I’ll keep this short and give the general gist of this.

Basically I had a problem, whereby Piwik was not getting the correct IP of the visitor, as the AWS setup was not passing the correct IP through on the expected value.

Try this code out as a test and see what you get.

Getting server/client IP:<br>


echo "1: " . $_SERVER['SERVER_ADDR'] . "<br>";
echo "2: " . $_SERVER['SERVER'] . "<br>";
echo "3: " . $_SERVER['HTTP_X_FORWARDED_PORT'] . "<br>";
echo "4: " . $_SERVER['HTTP_X_FORWARDED_PROTO'] . "<br>";
echo "5: " . $_SERVER['HTTP_X_FORWARDED_FOR'] . "<br>";
echo "6: " . $_SERVER['SERVER_ADDR'] . "<br>";
echo "7: " . $_SERVER['SERVER_PORT'] . "<br>";
echo "8: " . $_SERVER['REMOTE_ADDR'] . "<br>";

echo phpinfo();

As an intro, to help you figure out the correct value, use the above code as a test.

The problem with the suggestions on the Piwik site saying to make changes to these files, is that is didn’t work for me.

; Uncomment line below if you use a standard proxy
;proxy_client_headers[] = HTTP_X_FORWARDED_FOR
;proxy_host_headers[] = HTTP_X_FORWARDED_HOST

; Uncomment line below if you use CloudFlare
;proxy_client_headers[] = HTTP_CF_CONNECTING_IP

; Uncomment line below if you use another proxy (that sets Client-IP header)
;proxy_client_headers[] = HTTP_CLIENT_IP

You have more luck, but it’s for viewing here: https://piwik.org/faq/how-to-install/faq_98/

So, while there are many values in Piwik to have various settings, it’s worth filling in as many as possible…

The key value for this IP issue is this:


Here’s an example that will probably work for you. It’s pulled from a live site, but modified for anonymous use).


global $IDSITE;
$IDSITE = 2;  
// This is so we can get the correct IP of the visitor from behind the AWS load balancer.    
    { $IP_Tracker = $_SERVER['HTTP_X_FORWARDED_FOR'];} else
    { $IP_Tracker = $_SERVER['REMOTE_ADDR']; }
$pagetitle = "Home"; // The name of the tab for the stats.
// Tracking Code
// -- Piwik Tracking API init -- 
require_once "PiwikTracker.php";
PiwikTracker::$URL = 'http://loadbalancer.serverlocation.com/piwik/';

$t = new PiwikTracker( $IDSITE, 'http://loadbalancer.serverlocation.com/piwik/');

// End of configuration settings.  

// Optional function calls
$vid = '';

// Allow the follow-through tracking from page to page. - Visitor ID
if( isset($_POST['vid']) ) { $vid = addslashes($_POST['vid']); } else { if( isset($_GET['vid']) ) { $vid = addslashes($_GET['vid']); } }; // get vid
if(strlen($vid) > 10 && strlen($vid)< 30) { $t->setVisitorId($vid); }; // double check it
// If you want to force the visitor IP, or force the server date time to a date in the past,
// it is required to authenticate the Tracking request by calling setTokenAuth
// You can pass the Super User token_auth or any user with 'admin' privilege on the website $idSite

$token_auth = "YOURTOKEN";
$t->setTokenAuth( $token_auth );
$t->setIp( $IP_Tracker );
// If you wanted to force to record the page view or conversion to a specific visitorId
$t->setUrl($url = 'https://app.yoursever.com/2015_home_tab.php');

// Finally, track the page view with a Custom Page Title
// In the standard JS API, the content of the <title> tag would be set as the page title

<a href="http://app.yoursitecom/page2.php?vid=<?php echo $t->getVisitorId(); ?>">Page 2</a>






Artist and Song search of Spotify and iTunes via web URL

Posted on Updated on

This took me a while to find out how to do, so I thought I’d share my research to you.

I had a problem where I wanted users to be able to click on a link and it would open up the Spotify, or iTunes program to the search results of the values I passed it.

As mentioned, this took a long while to get. The Spotify one was easy as, and they should be commended for their simplicity. The iTunes one was not as easy to find.

So, this is my resulting code example, which I hope will help you in the future.

See this example work in JSFiddle


&lt;a href="https://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/advancedSearch?genreIndex=1&amp;media=music&amp;restrict=true&amp;submit=seeAllLockups&amp;entity=songs&amp;allArtistNames=tobyMac&amp;allTitle=Love+Broke+Thru"&gt;&lt;i class="fa fa-apple"&gt;&lt;/i&gt;Apple iTunes&lt;/a&gt;
&lt;a href="spotify:search:tobyMac+Love+Broke+Thru"&gt;&lt;i class="fa fa-spotify"&gt;&lt;/i&gt;Spotify&lt;/a&gt;

PHP Source Code

$artist = "TobyMac";
$title = "Love Broke Through";
echo '&lt;a href="spotify:search:' . str_replace(" ","+",$artist) . "+" . str_replace(" ","+",$title) . '"&gt;&lt;i class="fa fa-spotify"&gt;&lt;/i&gt; Spotify&lt;/a&gt;';
echo '&lt;a href="https://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/advancedSearch?genreIndex=1&amp;media=music&amp;restrict=true&amp;submit=seeAllLockups&amp;entity=songs&amp;allArtistNames=' . str_replace(" ","+",$artist) . "&amp;allTitle=" . str_replace(" ","+",$title) . '"&gt;&lt;i class="fa fa-apple"&gt;&lt;/i&gt; iTunes&lt;/a&gt;';

// Or so the browser opens a window and then closes it.
$iTunes_link = "https://search.itunes.apple.com/WebObjects/MZSearch.woa/wa/advancedSearch?genreIndex=1&amp;media=music&amp;restrict=true&amp;submit=seeAllLockups&amp;entity=songs&amp;allArtistNames=". str_replace(" ","+",$artist) . "&amp;allTitle=" . str_replace(" ","+",$title);
echo '&lt;a href="javascript:closeOnLoad(\'' . $iTunes_link. '\');"&gt;&lt;i class="fa fa-apple"&gt;&lt;/i&gt;&lt;/a&gt;';


&lt;script type="text/Javascript"&gt;
function closeOnLoad(myLink)
    var newWindow = window.open(myLink);

Both of these examples do 2 different things.
The Full iTunes example opens up a new window by JS and then closes it a second later. This is to allow the page to load, and then have the Apple page call the iTunes program. It then opens it to an advanced search page (which until I started playing with this stuff didn’t even know existed).

The Spotify example just opens the app directly if you have it installed – if you don’t use WordPress of course. They’ve wrecked the link in the example by removing the “spotify:search:” at the front of the link.

If this has helped you, please let me know, I’d love to hear, even send me a donation through PayPal.