Index: Makefile
==================================================================
--- Makefile
+++ Makefile
@@ -46,11 +46,11 @@
 	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.rpm" st2.py
 tar:
 	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.bin.txz" st2.py
 exe:
 	$(PACK) -t $@ $(OPTS) $(DEPS) -p "$(NAME)-VERSION.exe" \
-	--exe-exec 'cmd /K c:\usr\share\streamtuner2\dev\install_python_gtk.bat' \
+	--exe-exec 'usr\share\streamtuner2\dev\install_python_gtk.bat' \
 	--exe-dest c:/ --version $(VERSION) help/help.chm dev/install_python_gtk.* dev/*ico st2.py
 arch:
 	$(PACK) -t $@ $(OPTS) $(DEPS_A) -p "$(NAME)-VERSION.arch.txz" st2.py
 pyz:
         #@BUG: relative package references leave a /tmp/doc/ folder
@@ -64,10 +64,13 @@
 # test .deb contents
 check:
 	dpkg-deb -c streamtuner2*deb
 	dpkg-deb -I streamtuner2*deb
 	rpm -qpil *rpm
+	
+upload:
+	scp *.{deb,rpm,exe,pyz,arch,txz} io:st2/
 
 # manual installation
 install:
 	mkdir	-p				$(DEST)/channels
 	mkdir	-p				/usr/share/doc/streamtuner2/help/img

Index: Packfile
==================================================================
--- Packfile
+++ Packfile
@@ -11,12 +11,13 @@
 deb:	# complainy lintian needs a custom changelog.gz
 	gzip -9c usr/share/doc/streamtuner2/NEWS > usr/share/doc/streamtuner2/changelog.gz
 zip:
 rpm:
 exe:
-	mv usr/share/streamtuner2/help/help.chm usr/share/doc/streamtuner2/help.chm
+	#mv usr/share/streamtuner2/help/help.chm usr/share/doc/streamtuner2/help.chm
 	mv usr/share/streamtuner2/dev/streamtuner2.ico usr/share/pixmaps/streamtuner2.ico
+	sed -i '10 s/"\/usr\/share\/streamtuner2"/os.path.realpath(os.path.dirname(__file__)+"\/..\/share\/streamtuner2")/' usr/bin/streamtuner2
 src:
 tar:
 
 arch:
 	sed -i '1 s/python/python2/' usr/bin/streamtuner2

Index: action.py
==================================================================
--- action.py
+++ action.py
@@ -146,11 +146,11 @@
     except:
         log.ERR("Command not found:", cmd)
 
 # Open help browser, chm, or streamtuner2 pages
 def help(*args):
-    for path in ("./help", "/usr/share/doc/streamtuner2/help", "./usr/share/doc/streamtuner2"):
+    for path in ("./help", "/usr/share/doc/streamtuner2/help", "../share/streamtuner2/help"):
         if not os.path.exists(path):
             continue
         if conf.windows:
             return run(("%s/help.chm" % path).replace("/", '\\'))
         else:

Index: bin
==================================================================
--- bin
+++ bin
@@ -4,10 +4,10 @@
 # title: streamtuner2
 # pack: bin=/usr/bin/streamtuner2
 #
 # Invocation script for /usr/share/streamtuner2/st2.py
 
-import sys
+import sys, os
 sys.path.insert(0, "/usr/share/streamtuner2")
 
 import st2
 st2.main()

Index: dev/install_python_gtk.ps1
==================================================================
--- dev/install_python_gtk.ps1
+++ dev/install_python_gtk.ps1
@@ -9,38 +9,35 @@
  #  - crafts streamtuner2 shortcuts in Start menu
  #
  #>
 
 [CmdletBinding()]            
-Param(            
-)            
+Param()            
 
 # admin check            
 function Test-IsElevated {
     [CmdletBinding()]
-    param(
-    )
+    param()
     [Security.Principal.WindowsPrincipal] $Identity = [Security.Principal.WindowsIdentity]::GetCurrent()
     $Identity.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
 }
 
 
 # prerequisites check
 function Check-Prerequisites {
     [CmdletBinding()]
-    param(
-    )
+    param()
 
     ForEach ($task in $tasks) {
-       $title, $url, $cmd, $args, $regkey, $reghive = $task;
+       $title, $url, $cmd, $args, $regkey, $check = $task;
         if ($regkey) { 
-            if (!(Get-Item -Path ($regHive + "\" + $regkey))) {     # avoid runtime error if not existent (not working in PS1)
+            if (!(Get-Item -Path $regkey)) {     # avoid runtime error if not existent (not working in PS1)
                 Write-Host $title " not found"
                 return 0
             }
             else {
-                Write-Host (Get-ItemProperty -Path ($regHive + "\" + $regkey) -Name "DisplayName".DisplayName).DisplayName " found"
+                Write-Host (Get-ItemProperty -Path $regkey -Name "DisplayName".DisplayName).DisplayName " found"
             }
         }
         elseif ($title = "Python requests") {
             if (!(Get-Item -Path "$PYTHON\Lib\site-packages\requests-2.12.1-py2.7.egg")) {
                 write-Host $title " not found"
@@ -66,33 +63,31 @@
 
 # default paths
 $TEMP = $env:TEMP
 $PYTHON = "C:\Python27"
 $OutputEncoding = [System.Text.Encoding]::UTF8
+$StartMenu = "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs"
 
 #-- Get ST installation folder
 $ScriptPath = (Split-Path $MyInvocation.MyCommand.Path -Parent).Split("\") #PS1/2 compatibility"
-
 $UsrFolder=$ScriptPath[0]+"\"
 for ($i=1; $i -le $ScriptPath.Length - 4; $i++) {
     $UsrFolder = $UsrFolder+$ScriptPath[$i]+"\"
 }
-
 if (!(Test-Path -Path("..\..\..\bin\streamtuner2"))) {
     Write-Host -foregroundcolor Red "The Streamtuner2 start script could not be found. The installation cannot continue."
     Write-Host -foregroundcolor Red "Please do not change the folder structure of the Streamtuner2 package!"
     Write-Host -foregroundcolor Red "Press any key to exit ..."
     $null = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
     exit;
 }    
 
-
 # prepare registry lookup
 $regPathCU = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
-$regPath = "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
-if(!(Test-Path $regPath)) {
-    $regPath = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
+$regPathHK = "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
+if(!(Test-Path $regPathHK)) {
+    $regPathHK = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall"
 }
 
 
 #-- what and how to install
 #   each row is a list of (title,url,cmd,msi args,regkey,reghive)
@@ -100,55 +95,126 @@
   @(
     "Python 2.7.12",                                                  # title
     "https://www.python.org/ftp/python/2.7.12/python-2.7.12.msi",     # url
     "",                                                               # custom cmd
     "TARGETDIR=C:\Python27 /qb",                                      # msi args
-    "{9DA28CE5-0AA5-429E-86D8-686ED898C665}",                         # registry
-    "$regPath"                                                        # registry hive/path
+    "$regPathHK\{9DA28CE5-0AA5-429E-86D8-686ED898C665}",              # registry
+    "$regPathHK\{9DA28CE5-0AA5-429E-86D8-686ED898C665}"               # installed check
   ),
   @(
     "PyGtk 2.24.2",
     "http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/2.24/pygtk-all-in-one-2.24.2.win32-py2.7.msi",
     "",
     "TARGETDIR=C:\Python27 ADDLOCAL=ALL REMOVE=PythonExtensionModulePyGtkSourceview2,PythonExtensionModulePyGoocanvas,PythonExtensionModulePyRsvg,DevelopmentTools /qb",
-    "{09F82967-D26B-48AC-830E-33191EC177C8}",
-    "$regPath"                                                               
+    "$regPathHK\{09F82967-D26B-48AC-830E-33191EC177C8}",
+    "$regPathHK\{09F82967-D26B-48AC-830E-33191EC177C8}"
   ),
   @(
     "Python requests",
     "requests", # no download url, pip handles this
     "easy_install",
     "",
     "",
-    ""
+    "$PYTHON\Lib\site-packages\requests-2.12.1-py2.7.egg"
   ),
   @(
     "LXML 2.3",
     "https://pypi.python.org/packages/3d/ee/affbc53073a951541b82a0ba2a70de266580c00f94dd768a60f125b04fca/lxml-2.3.win32-py2.7.exe",
     "",
     "",
-    "lxml-py2.7",
-    "$regPathCU"
+    "$regPathCU\lxml-py2.7",
+    "$regPathCU\lxml-py2.7"
   ),
   @(
     "PyQuery 1.2.1",
     "https://pypi.python.org/packages/62/71/8ac1f5c0251e51714d20e4b102710d5eee1683c916616129552b0a025ba5/pyquery-1.2.17-py2.py3-none-any.whl",
     "pip",
     "",
     "",
-    ""
+    "$PYTHON\Lib\site-packages\pyquery-1.2.17.dist-info"
   ),
   @(
     "PIL 1.1.7",
     "http://effbot.org/downloads/PIL-1.1.7.win32-py2.7.exe",
     "",
     "",
-    "PIL-py2.7",
-    "$regPathCU"
+    "$regPathCU\PIL-py2.7",
+    "$regPathCU\PIL-py2.7"
+  ),
+  @(
+    "ST2 invocation (relocatability)",
+    "",
+    'Rewrite-Startscript',
+    "",
+    "",
+    "$UsrFolder\bin\streamtuner2.bak"
+  ),
+  @(
+    "Desktop shortcut",
+    "",
+    'Make-Shortcut -dir $Home\Desktop -name Streamtuner2.lnk -target $PYTHON\pythonw.exe -arg $UsrFolder\bin\streamtuner2',
+    "",
+    "",
+    "$Home\Desktop\Streamtuner2.lnk"
+  ),
+  @(
+    "Startmenu shortcut",
+    "",
+    'Make-Shortcut -dir "$StartMenu\Streamtuner2" -name Streamtuner2.lnk -target $PYTHON\pythonw.exe -arg $UsrFolder\bin\streamtuner2',
+    "",
+    "",
+    ""
+  ),
+  @(
+    "Startmenu help.chm",
+    "",
+    'Make-Shortcut -dir "$StartMenu\Streamtuner2" -name Help.lnk -target $UsrFolder\share\streamtuner2\help\help.chm -arg $false',
+    "",
+    "",
+    ""
+  ),
+  @(
+    "**FINISHED**.", "", '$true', "", "", ""
   )
 )
 
+#-- create Desktop/Startmenu shortcuts
+function Make-Shortcut {
+    [CmdletBinding()]
+    param($dir, $name, $target, $arg)
+    if (!(Test-Path -Path $dir)) {
+        New-Item -Path $dir -ItemType directory
+    }
+    $wsh = New-Object -ComObject WScript.Shell
+    $lnk = $wsh.CreateShortcut("$dir\$name")
+    $lnk.TargetPath = $target
+    if ($arg) {
+        $lnk.Arguments = $arg
+        $lnk.IconLocation = $UsrFolder + "share\pixmaps\streamtuner2.ico"
+        $lnk.WorkingDirectory = $UsrFolder + "bin"
+    }
+    $lnk.Save()
+}
+
+
+#-- modify ST2 wrapper script
+function Rewrite-Startscript {
+    [CmdletBinding()]
+    param()
+    $WrapperScript = Get-Content -Path $UsrFolder"\bin\streamtuner2"
+    for ($i=0; $i -lt $WrapperScript.Length ; $i++) {
+        $WrapperScript[$i] = $WrapperScript[$i].Replace("sys.path.insert(0, " + """" + "/usr/","sys.path.insert(0, " + """" + $UsrFolder)
+        Out-File -FilePath $UsrFolder"\bin\streamtuner2.new" -Encoding ascii -Append -InputObject $WrapperScript[$i]
+    }
+
+    if (Test-Path -Path $UsrFolder"\bin\streamtuner2.bak") {
+        Remove-Item -Path $UsrFolder"\bin\streamtuner2.bak" -Force
+    }
+    Rename-Item -NewName "streamtuner2.bak" -Path $UsrFolder"\bin\streamtuner2" #save old script
+    Rename-Item -NewName "streamtuner2" -Path $UsrFolder"\bin\streamtuner2.new"
+    Set-Acl $UsrFolder"\bin\streamtuner2" (Get-Acl $UsrFolder"\bin\streamtuner2.bak") # set file permissions 
+}
 
 
 
 #-- ask before running
 Write-Host ""
@@ -162,134 +228,101 @@
     Write-Host -foregroundcolor red "┃ ⚠ ⛔  If you run this script in non-elevated mode you will not be able to  ┃"
     Write-Host -foregroundcolor red "┃      uninstall Python and Gtk using the control panels´ software list.    ┃"
     Write-Host -foregroundcolor red "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
 }
 Write-Host ""
-$y = Read-Host "y/n"
-if ($y -notmatch "y|Y|1") {
+if ((Read-Host "y/n") -notmatch "[yY123ar]") {
     exit;
 }
 Write-Host ""
 
 
 #-- check prereqs installation
+<#
 Write-Host ""
 Write-Host "Checking installation"
 Write-Host "------------------------"
 Write-Host ""
-
-
 $prereqs = (Check-Prerequisites)
 if ($prereqs -match 1) {
     Write-Host ""
     Write-Host -foregroundcolor Yellow "All required Python components are already installed."
     Write-Host -foregroundcolor Yellow "Do you want to (R)einstall them or (S)kip the installation?"
     $y = Read-Host "R/S"
-}
-if ($y -notmatch "s|S|2" -OR $prereqs -match 0) {
-    #-- process
-    ForEach ($task in $tasks) {
-        $title, $url, $cmd, $args, $regkey, $regpath = $task;
-
-        Write-Host ""
-        Write-Host "Installing $title"
-        Write-Host "------------------------"
-        Write-Host ""
-        chdir($TEMP);
-
-
-        # get "filename" part from url
-        $file = [regex]::match($url, "/([^/]+?)([\?\#]|$)").Groups[1].Value;
-
-        # download
-        if ($url -match "https?://.+") {
-            Write-Host -foregroundcolor DarkGreen  " → download( $url )"
-            $wget = New-Object System.Net.WebClient
-            $wget.DownloadFile($url, "$TEMP\$file");
-        }
-
-        # run shorthand or custom command
-        if ($cmd) {
-            chdir($PYTHON)
-            if ($cmd -eq "pip") {
-                $cmd = "$PYTHON\Scripts\pip.exe install $TEMP\$file"
-            }
-            elseif ($cmd -match "^(easy|easy_install|silent)$") {
-                 $cmd = "$PYTHON\Scripts\easy_install.exe $url"
-            }
-            Write-Host -foregroundcolor DarkYellow   " → exec( $cmd )"
-            Invoke-Expression "& $cmd"
-        }
-        # msi
-        elseif ($file -match ".+.msi$") {
-            write-host -foregroundcolor DarkYellow " → exec( msiexec /i $file $args )"
-            Start-Process -Wait msiexec -ArgumentList /i,"$TEMP\$file",$args
-            if ($regkey) { Try {
-                Set-ItemProperty -Path "$regPath\$regkey" -Name "WindowsInstaller"  -Value "0"
-            } Catch {} }
-        }
-        # exe
-        elseif ($file -match ".+.exe$") {
-            write-host -foregroundcolor DarkYellow " → exec( $file $args )"
-            if ($args) {
-                Start-Process -Wait "$TEMP\$file" -ArgumentList $args
-            }
-            else {
-                Start-Process -Wait "$TEMP\$file"
-            }
-        }
-        # other files
-        else {
-          echo " → exec( $file )"
-          & "$TEMP\$file"
-        }
-    }
-}
-
-
-#-- modify ST2 wrapper script
-Write-Host ""
-Write-Host "Configuring Streamtuner2 ..."
-$WrapperScript = Get-Content -Path $UsrFolder"\bin\streamtuner2"
-for ($i=0; $i -lt $WrapperScript.Length ; $i++) {
-    $WrapperScript[$i] = $WrapperScript[$i].Replace("sys.path.insert(0, " + """" + "/usr/","sys.path.insert(0, " + """" + $UsrFolder)
-    Out-File -FilePath $UsrFolder"\bin\streamtuner2.new" -Encoding ascii -Append -InputObject $WrapperScript[$i]
-}
-
-if (Test-Path -Path $UsrFolder"\bin\streamtuner2.bak") {
-    Remove-Item -Path $UsrFolder"\bin\streamtuner2.bak" -Force
-}
-Rename-Item -NewName "streamtuner2.bak" -Path $UsrFolder"\bin\streamtuner2" #save old script
-Rename-Item -NewName "streamtuner2" -Path $UsrFolder"\bin\streamtuner2.new"
-Set-Acl $UsrFolder"\bin\streamtuner2" (Get-Acl $UsrFolder"\bin\streamtuner2.bak") # set file permissions 
-
-
-Write-Host ""
-Write-Host "Creating Shortcuts ..."
-#-- create ST2.lnk on desktop
-$WshShell = New-Object -ComObject WScript.Shell
-$Shortcut = $WshShell.CreateShortcut("$Home\Desktop\Streamtuner2.lnk")
-$Shortcut.TargetPath = "$PYTHON\pythonw.exe"
-$Shortcut.Arguments = $UsrFolder + "bin\streamtuner2"
-$Shortcut.IconLocation = $UsrFolder + "share\pixmaps\streamtuner2.ico"
-$Shortcut.WorkingDirectory = $UsrFolder + "bin"
-$Shortcut.Save()
-
-#-- create ST2 links in start menu
-$StartMenuFolder = "$env:USERPROFILE\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Streamtuner2"
-if (!(Test-Path -Path $StartMenuFolder)) {
-    New-Item -Path $StartMenuFolder -ItemType directory
-}
-$WshShell = New-Object -ComObject WScript.Shell
-$Shortcut = $WshShell.CreateShortcut("$StartMenuFolder\Streamtuner2.lnk")
-$Shortcut.TargetPath = "$PYTHON\pythonw.exe"
-$Shortcut.Arguments = $UsrFolder + "bin\streamtuner2"
-$Shortcut.IconLocation = $UsrFolder + "share\pixmaps\streamtuner2.ico"
-$Shortcut.WorkingDirectory = $UsrFolder + "bin"
-$Shortcut.Save()
-
-$Shortcut = $WshShell.CreateShortcut("$StartMenuFolder\Help.lnk")
-$Shortcut.TargetPath = $UsrFolder + "share\doc\streamtuner2\help.chm"
-$Shortcut.Save()
-
-Write-Host ""
-Write-Host -ForegroundColor Yellow "Installation completed."
+    if ($y -match "s|S|2") {
+        exit
+    }
+}
+#>
+
+#-- process
+$reinstall = "ask"
+ForEach ($task in $tasks) {
+    $title, $url, $cmd, $args, $regkey, $testpath = $task;
+
+    Write-Host ""
+    Write-Host "Installing $title"
+    Write-Host "------------------------"
+    Write-Host ""
+    chdir($TEMP);
+    
+    # test if element (directory/file or registry key) already exists:
+    if ($reinstall -eq "all") {
+    }
+    elseif ($testpath -AND (Test-Path -Path $testpath)) {
+        echo " → Is already present."
+        if ($reinstall -eq "none") { continue }
+        $y = Read-Host "   Reinstall [y/N/all/none]?"
+        if ($y -match "all|always|re|A") { $reinstall = "all" }
+        elseif ($y -match "never|none|skipall|S") { $reinstall = "none"; continue }
+        elseif ($y -match "y|yes|1|go|R") { } # YES
+        else { continue } # everything else counts as NO
+    }
+
+    # get "filename" part from url
+    $file = [regex]::match($url, "/([^/]+?)([\?\#]|$)").Groups[1].Value;
+
+    # download
+    if ($url -match "https?://.+") {
+        Write-Host -foregroundcolor DarkGreen  " → download( $url )"
+        $wget = New-Object System.Net.WebClient
+        $wget.DownloadFile($url, "$TEMP\$file");
+    }
+
+    # run shorthand or custom command
+    if ($cmd) {
+        chdir($PYTHON)
+        if ($cmd -eq "pip") {
+            $cmd = "$PYTHON\Scripts\pip.exe install $TEMP\$file"
+        }
+        elseif ($cmd -match "^(easy|easy_install|silent)$") {
+             $cmd = "$PYTHON\Scripts\easy_install.exe $url"
+        }
+        Write-Host -foregroundcolor DarkYellow   " → exec( $cmd )"
+        Invoke-Expression "$cmd"
+    }
+    # msi
+    elseif ($file -match ".+.msi$") {
+        write-host -foregroundcolor DarkYellow " → exec( msiexec /i $file $args )"
+        Start-Process -Wait msiexec -ArgumentList /i,"$TEMP\$file",$args
+        if ($regkey) { Try {
+            Set-ItemProperty -Path "$regkey" -Name "WindowsInstaller"  -Value "0"
+        } Catch {} }
+    }
+    # exe
+    elseif ($file -match ".+.exe$") {
+        write-host -foregroundcolor DarkYellow " → exec( $file $args )"
+        if ($args) {
+            Start-Process -Wait "$TEMP\$file" -ArgumentList $args
+        }
+        else {
+            Start-Process -Wait "$TEMP\$file"
+        }
+    }
+    # other files
+    elseif ($file) {
+      echo " → exec( $file )"
+      & "$TEMP\$file"
+    }
+}
+
+