ARTE Live Web videos

The Franco-German cultural Web site ARTE Live Web is an excellent resource for lovers of music (classical, jazz, alternative and World) and dance. The show videos at the site are enjoyable but unfortunately only viewable for a fixed period of time before the site removes them. Back in 2011 I wanted to download the video of a performance I’d attended and loved. I searched for a Linux tool but could not find one, then found a Windows freeware GUI tool called artepupper, and used version 0.2 to download the video. You can read about the tool on the author’s blog pages artepupper 0.1, artepupper 0.2 and artepupper 0.3. The reason for the change from 0.2 to 0.3 was that ARTE Live Web changed the format of an embedded URL inside the XML page for the video on their Web site.

Now, artepupper is based on livewebarte1.1.sh, a 2010 Bash script by Carmelo Ingrao, and a Perl script livewebarte.pl by Juan Domingo based on livewebarte1.1.sh, both of which are still available on line at Carmelo’s download page and which I only discovered after using artepupper in Windows. I tried the Perl script in Linux back in 2011, and it worked for me.

Recently I wanted to download another video from the ARTE Live Web site and found that, although artepupper 0.3 in Windows worked, the Perl script livewebarte.pl no longer worked. Presumably this was because of the aforementioned change to the embedded URL. However, I found that the Bash script livewebarte1.1.sh still worked. Actually, I had to edit the script to replace “./rtmpdump” with “rtmpdump“, as I had installed the command-line tool rtmpdump using the Linux distribution’s package manager and the executable is not stored in the same directory as the Bash script. But, apart from that, it worked.

Carmelo is a star for having deciphered how to access and download videos from the site. However, looking at his Bash script, the part where he parses a line in the XML code and extracts a string between the delimiters “MP4” and “mp4” is based on a hard-coded character position, which could change if the Web site’s owners change the format of the URL. So I decided to modify the Bash script to avoid using character positions to extract a string. The Bash script livewebarte1.2.sh is an updated version of Carmelo’s livewebarte1.1.sh script.

#!/bin/bash
# Script pour récupérer les vidéos FLV du site liveweb.arte.tv
# par Carmelo Ingrao <carmelo42@gmail.com> http://c.ingrao.free.fr/code/
# version 1.0
# release date 21 février 2010
## modified by Fitzcarraldo 24 April 2013
## version 1.2
## release date 24 April 2013
# licence : GPLv2
# rtmpdump compilé doit être dans le même répertoire que le script
## rtmpdump must be installed and in user's $PATH (e.g. I have it in /usr/bin/)
# utilisation du script :
#
# ./script.sh url fichier.flv
# _______________

# url --> $1
# fichier --> $2

# fichier de sortie
# on efface l'écran avant de commencer
clear

# on affiche les infos sur le script
echo "livewebarte.sh version 1.0."
echo "(c) 2010 Carmelo Ingrao; License : GPL"
echo "livewebarte.sh version 1.2."
echo "updated from version 1.1 by Fitzcarraldo on 24 April 2013; License : GPL"
echo "usage : ./livewebarte.sh url_concert_sur_liveweb.arte.tv fichier.flv"
echo "rtmpdump must be installed and in your path."

# on télécharge le code source de la page streamant le concert dans le fichier sourceconcert.html
wget $1 -O sourceconcert.html

# on récupère le numéro d'event et on le copie dans eventok.txt
#cat sourceconcert.html | grep "new LwEvent" > event.txt
#cat event.txt | cut -b "15 16 17" > eventok.txt
grep "new LwEvent" sourceconcert.html | grep -E -o -e "[0-9]+" > eventok.txt

# on prend le fichier XML d'arte et on crée l'url avec le bon numéro d'event
# xmloriginal="http://arte.vo.llnwd.net/o21/liveweb/events/event-610.xml"

# url du xml sans le numéro d'event original (pour faciliter)
xmloriginal2="http://arte.vo.llnwd.net/o21/liveweb/events/event-"

# on assigne à la variable b le contenu de eventok.txt --> numéro correct d'event
b=$(cat eventok.txt)

# on créer l'url correct du fichier XML qu'on téléchargera
xmlok=$(echo $xmloriginal2$b)
finxml=".xml"
xmlfinal=$(echo $xmlok$finxml)

# on télécharge le bon XML
wget $xmlfinal -O xmlok.xml
echo "Fichier XML téléchargé"

## I have changed the code in this part:
# on extrait le nom du fichier MP4 depuis le fichier xmlok.xml
mp4hd=$(cat xmlok.xml | grep "urlHd")
# on efface le début de l'url du MP4
# on efface le surplus à la fin du nom du MP4 et on sauve le nom dans la variable mp4hdcut2
mp4hdcut2=${mp4hd#*MP4}
mp4hdcut2=${mp4hdcut2%%mp4*}
mp4hdcut2="MP4"$mp4hdcut2"mp4"
## end of my changes to evaluate mp4hdcut2

# on lance la commande rtmpdump avec les paramètres
# rappel :
# $2 = nom du fichier de sortie
# $mp4hdcut2 = nom du fichier MP4

## Carmelo had ./rtmpdump here, but I removed the "./"
rtmpdump -r rtmp://arte.fcod.llnwd.net:1935/a2306/o25 -a a2306/o25 -f LNX 10,0,45,2 -W http://liveweb.arte.tv/flash/player.swf -t rtmp://arte.fcod.llnwd.net:1935/a2306/o25 -p http://liveweb.arte.tv/ -o $2 -y $mp4hdcut2

# on efface les fichiers crées
rm sourceconcert.html
#rm event.txt
rm eventok.txt
rm xmlok.xml

# Affichage des infos de fin
echo "________"
echo "Voilà, le téléchargement est terminé."
echo "Le fichier se trouve ici :"
echo " "
echo $2
echo " "
echo "Bon visionnage"
echo " "
echo " "
exit 0

Save it in your home directory and make it executable:

$ chmod +x livewebarte1.2.sh

Also make sure you have the package rtmpdump installed and that it is in your $PATH.

Then you can browse the ARTE Live Web site and select the performance video you wish to download. Hover the mouse pointer over the video pane and click on “INTEGRER LA VIDEO” to find the URL for that video, which will be of the form http://liveweb.arte.tv/fr/video/foo/, where “foo” is some string of characters (not literally “foo”, of course). The command to download it is then as shown below. I’ll use a file name foo.flv here, but any prefix would do:

$ ./livewebarte1.2.sh http://liveweb.arte.tv/fr/video/foo/ foo.flv

Note that it is essential to include the forward slash at the end of the URL. The file will be downloaded to your home directory and you can watch it in VLC or any other Linux media player that plays Flash video.

So there you have it; currently you can use artepupper 0.3 in Windows or livewebarte1.2.sh in Linux to download from ARTE Live Web a video of a performance you attended and loved.

Installing Dropbox in Gentoo running KDE

I had never used Dropbox before and had no intention of doing so, but today a work colleague sent me some large files via Dropbox so I was forced to sign up. I tried to install Dropbox on my main laptop running Gentoo Linux and KDE but, for a well-known application, I had a surprising amount of trouble, hence this blog post.

To begin with, I found the following Dropbox-related packages:

# eix dropbox
* gnome-extra/nautilus-dropbox
Available versions: (~)0.6.9 (~)0.7.0 0.7.1 (~)1.4.0 {debug}
Homepage: http://www.dropbox.com/
Description: Store, Sync and Share Files Online

* net-misc/dropbox
Available versions: 1.2.48-r1^ms (~)1.2.51-r2^ms (~)1.4.3-r1^ms (~)1.4.7-r1^ms (~)1.4.7-r2^ms (~)1.4.17^ms (~)1.4.23^ms (~)1.6.16^ms {X +librsync-bundled}
Homepage: http://dropbox.com/
Description: Dropbox daemon (pretends to be GUI-less)

* net-misc/dropbox-cli
Available versions: 1 1-r1 {PYTHON_TARGETS="python2_6 python2_7"}
Homepage: http://www.dropbox.com/
Description: Cli interface for dropbox daemon (python)

* xfce-extra/thunar-dropbox [1]
Available versions: [m](~)0.2.0
Homepage: http://www.softwarebakery.com/maato/thunar-dropbox.html
Description: Plugin for Thunar that adds context-menu items for Dropbox

[1] "sabayon" /var/lib/layman/sabayon

Found 4 matches.

But I don’t have GNOME or Xfce installed on my main laptop, so the first and last packages were of no interest. A quick search on the Web turned up Kfilebox, which seemed to be exactly what I needed. I was pleased to find that the package is in the main Portage tree:

# eix kfilebox
* kde-misc/kfilebox
Available versions: (4) (~)0.4.8 (~)0.4.9
{LINGUAS="ar br cs de el es fr gl it lt nl pl pt ru si tr zh zh_CN"}
Homepage: http://kdropbox.deuteros.es/
Description: KDE dropbox client

So I installed kfilebox, dropbox and dropbox-cli, thinking I would need them all. Then, before doing anything else, I surfed to the Dropbox Web site and signed up for an account.

I launched Konsole and entered the command kfilebox. A window popped-up telling me that the Dropbox Daemon was being downloaded, then another window popped up offering me two options/buttons: ‘Run gtk based installer’ and ‘Or simply link account’. I clicked on the latter, thinking that was all I needed to do as I had already signed up for an account via the Dropbox Web site. But a Dropbox icon did not appear in the Panel, nor did Dolphin show a Dropbox folder icon in my home directory, and the KDE Notifications widget kept popping up notification after notification from Kfilebox to “Please visit url to link to this machine”. The trouble was that clicking on the apparent link in the notifications did nothing.

The directories .dropbox and .dropbox-dist existed in my home directory, and the contents of /home/fitzcarraldo/.kde4/share/config/kfileboxrc were as follows:

[General]
AutoStart=true
Browser=rekonq
DropboxDir=/home/fitzcarraldo/.dropbox-dist/
FileManager=dolphin
GtkUiDisabled=true
IconSet=default
ShowNotifications=true
StartDaemon=true

As the rekonq Web browser is not installed on this laptop, I edited the file and changed Browser=rekonq to Browser=firefox then rebooted, but it made no difference.

So I uninstalled everything:

# emerge -C kfilebox dropbox dropbox-cli
# rm -rf /home/fitzcarraldo/.dropbox
# rm -rf /home/fitzcarraldo/.dropbox-dist
# rm /home/fitzcarraldo/.kde4/share/config/kfileboxrc

then rebooted and reinstalled only Kfilebox:

# emerge kfilebox

I then launched Konsole and entered the command kfilebox. The pop-up window appeared notifying me that the Dropbox Daemon was being downloaded, followed by the pop-up window offering me the choice of running the gtk-based installer or simply linking the account. This time I chose the option to run the gtk-based installer and just followed the intuitive instructions in the various pop-up windows that followed, one of which offered to create a new Dropbox account or to link to an existing Dropbox account. As I wanted to do the latter I entered my e-mail address and Dropbox password, a Dropbox icon then appeared on the Panel and a Dropbox folder icon is now visible in Dolphin.

I checked the contents of ~/.kde4/share/config/kfileboxrc and they were the same as listed above, so I edited the file to replace rekonq with firefox, although I’m not sure yet what (if anything) that does, as Dropbox is new to me and I’m still learning. Anyway, the important thing is that I could now click on the ‘View folder’ button in an e-mail sent to me by a colleague and the files uploaded by my colleague were automatically downloaded into the ~/Dropbox directory.

EDIT May 30, 2013: Kfilebox is no longer in development and has started playing up. However, I found out how to install Dropbox directly and use it with KDE, and it’s just as user-friendly as Kfilebox. See my post Dropbox revisited for how to install Dropbox directly.

Switching the display quickly between a laptop monitor and an external monitor or projector in Linux


I connect my laptop to an external keyboard and an external monitor or projector in various offices and at home, and each of the monitors has a different resolution. Fn-F3 on my laptop keyboard allows me to toggle between monitors, but I want more control (including the ability to specify the resolution of the external display). Now, I find the GPU manufacturer’s application and the Desktop Environment’s GUI for switching monitors and changing screen resolution rather cumbersome, so I wanted an icon on the Desktop that I could double-click to switch monitors without having to enter the root user’s password and fiddle around too much. So I decided to create some simple Bash scripts and associated Desktop Config files with nice-looking icons on the desktop, which I can launch easily and quickly by double-clicking. Obviously the resolutions are limited to the range of resolutions supported by the GPU and external monitor.

The suite of Desktop Config files I created have self-explanatory names:

$ cd ~/Desktop
$ ls -1 Switch*
Switch_OFF_laptop_monitor_if_external_monitor_is_connected
Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto
Switch_ON_laptop_monitor_and_external_monitor
Switch_ON_laptop_monitor_and_switch_off_external_monitor
$ ls -1 Toggle*
Toggle_display

The difference between Switch_OFF_laptop_monitor_if_external_monitor_is_connected and Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto is that the former prompts for the resolution of the external monitor whereas the latter tries to find the resolution automatically. I have both because I have found that, for some external display devices (e.g. projectors), it is handy to have the ability to specify the resolution manually.

Switch off the laptop monitor if an external monitor is connected (find resolution automatically)

The Desktop Config file I double-click the most is ~/Desktop/Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto, and it contains the following text:

[Desktop Entry]
Comment[en_GB]=switch off laptop monitor if external monitor is connected auto
Comment=switch off laptop monitor if external monitor is connected auto
Exec=sh /home/fitzcarraldo/switch_off_laptop_monitor_if_external_monitor_is_connected_auto.sh
GenericName[en_GB]=Switch off laptop monitor if external monitor is connected auto
GenericName=Switch off laptop monitor if external monitor is connected auto
Icon=/home/fitzcarraldo/Pictures/Icons/display.png
MimeType=
Name[en_GB]=Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto
Name=Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=

The Bash script it launches, ~/switch_off_laptop_monitor_if_external_monitor_is_connected_auto.sh, contains the following code:

#!/bin/bash
if xrandr -q | grep "CRT1 connected"; then
  xrandr --output LVDS --off
  xrandr --output CRT1 --off
  xrandr --output CRT1 --auto
else
  xrandr --output CRT1 --off
  xrandr --output LVDS --off
  xrandr --output LVDS --mode 1920x1080
# 1920x1080 is the native resolution of my laptop monitor
fi

Don’t forget to make them executable:

$ chmod +x /home/fitzcarraldo/Desktop/Switch_OFF_laptop_monitor_if_external_monitor_is_connected_auto
$ chmod +x /home/fitzcarraldo/switch_off_laptop_monitor_if_external_monitor_is_connected_auto.sh

If you’re wondering how I knew I had to specify ‘CRT1’ and ‘LVDS’ in the Bash script, I used the xrandr command to find out what names the GPU gives the monitors:

$ xrandr
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 1920 x 1920
LVDS connected (normal left inverted right x axis y axis)
1920x1080 60.0 +
1680x1050 60.0
1400x1050 60.0
1600x900 60.0
1280x1024 60.0
1440x900 60.0
1280x960 60.0
1280x768 60.0
1280x720 60.0
1024x768 60.0
1024x600 60.0
800x600 60.0
800x480 60.0
640x480 60.0
DFP1 disconnected (normal left inverted right x axis y axis)
CRT1 connected 1920x1080+0+0 (normal left inverted right x axis y axis) 476mm x 268mm
1920x1080 60.0*+
1280x1024 75.0 60.0
1280x960 60.0
1280x800 59.8
1152x864 75.0
1280x720 60.0
1024x768 75.0 70.1 60.0
800x600 72.2 75.0 60.3 56.2
640x480 75.0 72.8 67.0 59.9

Switch off the laptop monitor if an external monitor is connected (enter resolution)

The Desktop Config file I double-click is ~/Desktop/Switch_OFF_laptop_monitor_if_external_monitor_is_connected, and it contains the following text:

[Desktop Entry]
Comment[en_GB]=switch off laptop monitor if external monitor is connected
Comment=switch off laptop monitor if external monitor is connected
Exec=sh /home/fitzcarraldo/System_Administration/switch_off_laptop_monitor_if_external_monitor_is_connected.sh
GenericName[en_GB]=Switch off laptop monitor if external monitor is connected
GenericName=Switch off laptop monitor if external monitor is connected
Icon=/home/fitzcarraldo/Pictures/Icons/display.png
MimeType=
Name[en_GB]=Switch_OFF_laptop_monitor_if_external_monitor_is_connected
Name=Switch_OFF_laptop_monitor_if_external_monitor_is_connected
Path=
StartupNotify=true
Terminal=true
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=

The Bash script it launches, ~/switch_off_laptop_monitor_if_external_monitor_is_connected.sh, contains the following code:

#!/bin/bash
if xrandr -q | grep "CRT1 connected"; then
echo -n "Enter resolution width of external monitor (hint 1920 Doha, 1440 home): "
read EXTERNAL_WIDTH
echo -n "Enter resoluton height of external monitor (hint 1080 Doha, 900 home): "
read EXTERNAL_HEIGHT
  xrandr --output LVDS --off
  xrandr --output CRT1 --off
  xrandr --output CRT1 --mode $EXTERNAL_WIDTH"x"$EXTERNAL_HEIGHT
else
  xrandr --output CRT1 --off
  xrandr --output LVDS --off
  xrandr --output LVDS --mode 1920x1080
# 1920x1080 is the native resolution of my laptop monitor
fi

Don’t forget to make them executable:

$ chmod +x /home/fitzcarraldo/Desktop/Switch_OFF_laptop_monitor_if_external_monitor_is_connected
$ chmod +x /home/fitzcarraldo/switch_off_laptop_monitor_if_external_monitor_is_connected.sh

Switch on the laptop monitor and external monitor simultaneously

I don’t need to use this one much, only when I am using an external monitor but suddenly want to use the laptop’s built-in Webcam and so have to open fully the laptop’s lid. The file ~/Desktop/Switch_ON_laptop_monitor_and_external_monitor contains the following text:

[Desktop Entry]
Comment[en_GB]=switch_ON_laptop_monitor_and_external_monitor
Comment=switch_ON_laptop_monitor_and_external_monitor
Exec=sh /home/fitzcarraldo/switch_on_laptop_monitor_and_external_monitor.sh
GenericName[en_GB]=Switch_ON_laptop_monitor_and_external_monitor
GenericName=Switch_ON_laptop_monitor_and_external_monitor
Icon=/home/fitzcarraldo/Pictures/Icons/display.png
MimeType=
Name[en_GB]=Switch_ON_laptop_monitor_and_external_monitor
Name=Switch_ON_laptop_monitor_and_external_monitor
Path=
StartupNotify=true
Terminal=true
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=

and the Bash script it calls, ~/switch_on_laptop_monitor_and_external_monitor.sh, contains the following code:

#!/bin/bash
if xrandr -q | grep "CRT1 connected"; then
  echo "Note that the resolution specified must be the same for both monitors, and must be achievable on both monitors."
  echo -n "Enter resolution width of external monitor (hint 1920 office, 1440 home): "
  read EXTERNAL_WIDTH
  echo -n "Enter resoluton height of external monitor (hint 1080 office, 900 home): "
  read EXTERNAL_HEIGHT
  #xrandr --output LVDS --off
  xrandr --output LVDS --mode $EXTERNAL_WIDTH"x"$EXTERNAL_HEIGHT
  xrandr --output CRT1 --off
  xrandr --output CRT1 --mode $EXTERNAL_WIDTH"x"$EXTERNAL_HEIGHT
else
  xrandr --output CRT1 --off
  xrandr --output LVDS --off
  xrandr --output LVDS --mode 1920x1080
# 1920x1080 is the native resolution of my laptop monitor
fi

Don’t forget to make them executable:

$ chmod +x /home/fitzcarraldo/Desktop/Switch_ON_laptop_monitor_and_external_monitor
$ chmod +x /home/fitzcarraldo/switch_on_laptop_monitor_and_external_monitor.sh

Switch on the laptop monitor and switch off an external monitor

I don’t need to use this one much either, given that the display mode reverts to the laptop monitor after I reboot or shutdown/power-up the laptop. The file ~/Desktop/Switch_ON_laptop_monitor_and_external_monitor contains the following text:

[Desktop Entry]
Comment[en_GB]=switch on laptop monitor and switch off external monitor
Comment=switch on laptop monitor and switch off external monitor
Exec=sh /home/fitzcarraldo/switch_on_laptop_monitor_and_switch_off_external_monitor.sh
GenericName[en_GB]=Switch on laptop monitor and switch off external monitor
GenericName=Switch on laptop monitor and switch off external monitor
Icon=computer-laptop
MimeType=
Name[en_GB]=Switch_ON_laptop_monitor_and_switch_off_external_monitor
Name=Switch_ON_laptop_monitor_and_switch_off_external_monitor
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=
X-KDE-SubstituteUID=false
X-KDE-Username=

The Bash script it launches, ~/switch_on_laptop_monitor_and_switch_off_external_monitor.sh, contains the following code:

#!/bin/bash
xrandr --output CRT1 --off
xrandr --output LVDS --auto
xrandr --output LVDS --mode 1920x1080
# 1920x1080 is the native resolution of my laptop monitor

I did also create a fifth Desktop Config file and associated Bash script, to toggle between the three modes (laptop monitor only > both monitors > external monitor only) rather than having to double-click three different icons. But, to be honest, it’s quicker and easier to have the three icons and double-click on the one I want rather than toggling through three display modes. Anyway, in case you are interested, the Desktop Config file ~/Desktop/Toggle_Display contains the follow text:

[Desktop Entry]
Comment[en_GB]=Toggle between laptop monitor, external monitor and both
Comment=Toggle between laptop monitor, external monitor and both
Exec=sh /home/fitzcarraldo/toggle_display.sh
GenericName[en_GB]=Toggle between laptop monitor, external monitor and both
GenericName=Toggle between laptop monitor, external monitor and both
Icon=video-display
MimeType=
Name[en_GB]=Toggle_display
Name=Toggle_display
Path=
StartupNotify=false
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=

and the Bash script it launches, ~/toggle_display.sh, contains the following code:

#!/bin/sh

# Using the xrandr command I found that the two video outputs from my laptop are named LVDS
# (the internal display) and CRT1 (the external display driven by the laptop's VGA socket).
# My external monitor at home has a resolution of 1440x900.

CONNECTED=`xrandr | grep -i ' connected' | grep LVDS | awk '{print $1}'`
CONNECTED="${CONNECTED} `xrandr | grep -i ' connected' | grep CRT | awk '{print $1}'`"

ENABLED=`awk '{print;exit}' ~/displays_enabled 2>/dev/null`

if [ "$CONNECTED" = "LVDS" -o "$CONNECTED" = "LVDS " -o "$CONNECTED" = " LVDS" ]; then
        # Only the internal display is connected, so don't do anything.
        echo "LVDS" > ~/displays_enabled
        ENABLED="LVDS"
        xrandr --output CRT1 --off
        xrandr --output LVDS --off
        xrandr --output LVDS --auto
        exit 0
elif [ "$CONNECTED" = "LVDS CRT1" ]; then
        # Both the internal and external displays are connected, so let's toggle
        # LVDS > LVDS,CRT1 > CRT1

        EXTERNALRES=`xrandr | awk 'c&&c--;/ connected/{c=1}' | awk '{print $1}' | grep 1440x900`
        if [ "$ENABLED" = "LVDS" ]; then
        # Switching on both displays.
                xrandr --output LVDS --off
                if [ "$EXTERNALRES" = "1440x900" ]; then
                         xrandr --output LVDS --mode 1440x900
                         xrandr --output CRT1 --off
                         xrandr --output CRT1 --auto
                else
                         xrandr --output LVDS --auto
                         xrandr --output CRT1 --off
                         xrandr --output CRT1 --auto
                fi
                ENABLED="LVDS CRT1"
                echo "LVDS CRT1" > ~/displays_enabled
        elif [ "$ENABLED" = "LVDS CRT1" ]; then
        # Switching on only external display.
                xrandr --output LVDS --off
                xrandr --output CRT1 --off
                xrandr --output CRT1 --auto
                ENABLED="CRT1"
                echo "CRT1" > ~/displays_enabled
        else
        # Switching on only internal display.
                xrandr --output CRT1 --off
                xrandr --output LVDS --off
                xrandr --output LVDS --auto
                ENABLED="LVDS"
                echo "LVDS" > ~/displays_enabled
        fi
fi

As I use KDE, I also used System Settings > Shortcuts and Gestures | Custom Shortcuts to create a keyboard shortcut which I named ‘Toggle display’, with Meta+P as Trigger and sh ~/toggle_display.sh as Action, but I tend to use the mouse rather than the keyboard in any case.

By the way, you might think some of the xrandr commands in the above Bash scripts are redundant. You would be correct in thinking that, but in practice I found that the displays did not switch if I didn’t include the additional commands shown (due to a bug in xrandr, perhaps?). Even then, when I switch to an external monitor, occasionally the screen resolution is slightly too big or too small, so I placed the icons at the top left of the desktop so that they are always accessible and I can just double-click on the same icon again if necessary. As I’m using KDE, I placed a Folder View Plasmoid for ~/Desktop/ at the top left of the desktop, as you can see in the screenshot.

Desktop showing icons for switching between monitors

Footnote

I’ve been using the above method of switching between displays for a couple of years now with an AMD ATI GPU. It works nicely and suits my needs perfectly. AMD has supported xrandr since 2008 (see Ref. 1), whereas NVIDIA only began to support xrandr last year (see Ref. 2) so I’m not sure how well these scripts would work with NVIDIA GPUs.

Ref. 1: AMD Catalyst 8.9 Gets WINE Fix, RandR 1.2 Support, September 18, 2008
Ref. 2: NVIDIA’s 302 Linux Driver Finally Has RandR 1.2/1.3, May 2, 2012