Properly handle spaces in filenames along the path to the installer.
[ardour.git] / tools / linux_packaging / stage2.run
1 #!/bin/sh
2
3 ####################################
4 #
5 #       stage2.run
6 #       Ardour/Mixbus bundle installer
7 #       Todd Naugle
8 #
9 ###################################
10
11
12
13 PGM_NAME="Ardour"
14 PGM_VENDOR="Ardour"
15 PGM_EXEC_FILE="ardour3"
16
17 INSTALL_DEST_BASE="/opt"
18
19 PGM_NAME_LOWER=$(echo $PGM_NAME | tr '[:upper:]' '[:lower:]')
20
21 #### Global Variables ####
22 HAS_XDG="T"
23
24 ########################
25 # Function Definitions
26 ########################
27
28 VaildateYesNoQuestion ()
29 {
30         # $1 = Question Text
31         
32         local INPUT_OK="n"
33         local USER_INPUT=""
34
35         until test "y" = $INPUT_OK;
36         do
37                 echo ""
38                 read -p "$1 [y/n]: " USER_INPUT
39                 echo ""
40
41                 if [ ! -z $USER_INPUT ]; 
42                 then            
43                         if [ "Y" = $USER_INPUT -o "y" = $USER_INPUT -o "n" = $USER_INPUT -o "N" = $USER_INPUT ];
44                         then
45                                 INPUT_OK="y"
46                         fi
47                 fi
48         done
49         
50         echo $USER_INPUT | tr '[:upper:]' '[:lower:]'
51         
52 }
53
54 SystemInstall ()
55 {
56
57         # Determine which software install app to use and then install requested package
58         # $1 = Package Name
59
60         if which yum > /dev/null;
61         then
62                 ${SUPER} yum -y install $1
63                 rtrn=$?
64
65                 if [ $rtrn -ne 0 ];
66                 then
67                         echo ""
68                         echo "!!! ERROR !!! yum install failed for an unknown reason."
69                         echo "Please install package $1 after this installer completes."
70                         echo ""
71                 fi
72
73         elif which apt-get > /dev/null;
74         then
75                 ${SUPER} apt-get -y install $1
76                 rtrn=$?
77
78                 if [ $rtrn -ne 0 ];
79                 then
80                         echo ""
81                         echo "!!! ERROR !!! apt-get install failed for an unknown reason."
82                         echo "Please install package $1 after this installer completes."
83                         echo ""
84                 fi
85
86         else
87                 echo ""
88                 echo "!!! ERROR !!! - Not able to detect which software install tool to use (yum or apt-get)."
89                 echo "Please install package $1 using the system software install tool."
90                 echo ""
91                 rtrn=1
92         fi
93         
94         return $rtrn
95
96 }
97
98 ########################################################################
99 #                                 Main
100 ########################################################################
101
102 # If you double click a script, some systems don't get the PWD correct.
103 # Force it to be correct
104 PKG_PATH=$(dirname "$(readlink -f "$0")")
105 cd "${PKG_PATH}"
106
107 echo ""
108 echo "Welcome to the ${PGM_NAME} installer"
109 echo ""
110
111 #############################
112 # Check for root privileges
113 #############################
114
115 SUPER=""
116
117 if [ "$(id -u)" != "0" ]; then
118
119         if ! which sudo > /dev/null;
120         then
121                 echo ""
122                 echo "!!! ERROR !!!"
123                 echo ""
124                 echo "The installer requires root privileges. It is currently not"
125                 echo "running as root AND the program sudo is missing from this system."
126                 echo ""
127                 echo "Please correct this by installing and configuring sudo or running"
128                 echo "the installer as root."
129                 echo ""
130                 read -p "Press ENTER to exit installer:" BLAH
131                 exit 1
132         fi
133
134         if ! sudo date;
135         then
136                 echo ""
137                 echo "!!! ERROR !!!"
138                 echo ""
139                 echo "Either you don't know the root password or the user is not allowed to sudo"
140                 echo "Please correct this and run the installer again"
141                 echo "(hint: use visudo to edit sudoers file)"
142                 echo ""
143                 read -p "Press ENTER to exit installer:" BLAH
144                 exit 1
145         fi
146         SUPER="sudo"
147 else
148         echo ""
149         echo "!!! Warning !!!"
150         echo ""
151         echo "The installer is running as the root user which is not the prefered method."
152         echo "There are checks run at the end of the installer to help ensure proper operation"
153         echo "of ${PGM_NAME} (realtime priviledges, memory locking, frequency scaling)."
154         echo "Running as root will invalidate these tests."
155         echo ""
156         read -p "Press ENTER to continue:" BLAH
157         
158 fi
159
160 ############################
161 # Determine processor type
162 ############################
163
164 case `uname -m` in
165         i[3456789]86|x86|i86pc)
166                 echo "Architecture is x86"
167                 ARCH='x86'
168                 ;;
169         x86_64|amd64|AMD64)
170                 echo "Architecture is x86_64"
171                 ARCH='x86_64'
172                 ;;
173         *)
174                 echo ""
175                 echo "!!! ERROR !!! - Unknown architecture `uname -m`"
176                 echo ""
177                 read -p "Press ENTER to exit installer:" BLAH
178                 exit 1
179                 ;;
180 esac
181
182 ####################
183 # Check disk space
184 ####################
185
186 # We have to check the current folder and the INSTALL_DEST_BASE just
187 # in case they are on different devices
188 echo "Checking for required disk space"
189
190 if [ ! -e .${PGM_NAME}_${ARCH}-*.size ]; then
191         echo ""
192         echo "!!! ERROR !!! Can't locate .size file for ${ARCH} bundle."
193         echo ""
194         exit 1
195 else
196         REQUIRED_BYTES=$(cat .${PGM_NAME}_${ARCH}-*.size)
197
198         #Check space in current folder
199         FREE_BYTES=$(df -P -B 1 "${PKG_PATH}" | grep / | awk '{print $4}')
200
201         if [ ${FREE_BYTES} -le ${REQUIRED_BYTES} ] ; then
202                 echo ""
203                 echo "!!! ERROR !!! - Insufficient disk space in ${PKG_PATH}"
204                 echo ""
205                 exit 1
206         fi
207
208         #Check space in INSTALL_DEST_BASE
209         FREE_BYTES=$(df -P -B 1 ${INSTALL_DEST_BASE} | grep / | awk '{print $4}')
210
211         if [ ${FREE_BYTES} -le ${REQUIRED_BYTES} ] ; then
212                 echo ""
213                 echo "!!! ERROR !!! - Insufficient disk space in ${INSTALL_DEST_BASE}"
214                 echo ""
215                 exit 1
216         fi
217 fi
218
219 #####################
220 # Unpack the bundle
221 #####################
222
223 # untar the correct bundle for us to install
224 echo "Unpacking bundle for $ARCH"
225
226 if [ ! -e ${PGM_NAME}_${ARCH}-*.tar.bz2 ]; then
227         echo ""
228         echo "!!! ERROR !!! Can't locate ${ARCH} bundle file."
229         echo ""
230         exit 1
231 fi
232
233 tar -xjf ${PGM_NAME}_${ARCH}-*.tar.bz2
234 BUNDLE_DIR=$(basename `find -maxdepth 1 -type d -name "${PGM_NAME}_${ARCH}-*"`)
235
236
237 #######################
238 # Check for xdg utils
239 #######################
240
241 XDG_MENU_VER=$(xdg-desktop-menu --version 2> /dev/null)
242 if [ -z "$XDG_MENU_VER" ];
243 then
244         echo "System does not have xdg-desktop-menu installed"
245         HAS_XDG="F"
246 fi
247
248 XDG_ICON_VER=$(xdg-icon-resource --version 2> /dev/null)
249 if [ -z "$XDG_ICON_VER" ];
250 then
251         echo "System does not have xdg-icon-resource installed"
252         HAS_XDG="F"
253 fi
254
255 #################################################
256 # Check if system libs are OK (libc, etc)
257 #################################################
258
259 echo ""
260 echo "Checking system libs to see if they are compatible with ${PGM_NAME}."
261 echo ""
262
263 LIB_ERROR="F"
264 LD_PATH=`pwd`/${BUNDLE_DIR}/lib
265
266 # check the main App
267 LDD_RESULT=$(LD_LIBRARY_PATH=${LD_PATH} ldd ${BUNDLE_DIR}/bin/${PGM_NAME_LOWER}-* 2>&1 > /dev/null)
268
269 if [ -n "$LDD_RESULT" ];
270 then
271         echo "$LDD_RESULT"
272         LIB_ERROR="T"
273 fi
274         
275 # check the libs
276 LIB_FILES=$(find ${BUNDLE_DIR}/lib -name "*.so")
277
278 for path in $LIB_FILES
279 do
280         LDD_RESULT=$(LD_LIBRARY_PATH=${LD_PATH} ldd $path 2>&1 > /dev/null)
281         if [ -n "$LDD_RESULT" ];
282         then
283                 echo "$LDD_RESULT"
284                 LIB_ERROR="T"
285         fi
286 done
287
288 if test "T" = $LIB_ERROR;
289 then
290         echo ""
291         echo "!!! ERROR !!! - Missing library detected!"
292         echo "This system does not have the correct libs to run ${PGM_NAME}."
293         echo "Installation will not complete. Please use a compatible distro."
294         echo ""
295         read -p "Press ENTER to exit installer:" BLAH
296         exit 1
297 fi
298
299 ################################
300 # Setup derived variables
301 ################################
302 PGM_VERSION=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $2 }' | awk 'BEGIN { FS = "_"} ; { print $1}')
303 PGM_BUILD=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $2 }' | awk 'BEGIN { FS = "_"} ; { print $2}')
304 PGM_BUILDTYPE=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $3 }')
305
306 if [ -z ${PGM_BUILDTYPE} ];
307 then
308         PGM_FULL_NAME="${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}"
309         ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}"                    #no dash between name and version since dash seperates vendor from program
310         MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}.desktop"    #no dash between name and version since dash seperates vendor from program
311         DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}.desktop"
312 else
313         PGM_FULL_NAME="${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}-${PGM_BUILDTYPE}"
314         ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}"                   #no dash between name and version since dash seperates vendor from program
315         MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"   #no dash between name and version since dash seperates vendor from program
316         DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"
317 fi
318
319 PGM_EXEC_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/bin/${PGM_EXEC_FILE}"
320 ICON_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/etc/icons"
321 MENU_FILE_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/share"
322
323         
324
325 ################################
326 # Install bundle and Menu/Link
327 ################################
328
329 if [ ! -d ${INSTALL_DEST_BASE} ];
330 then
331         echo ""
332         echo "!!! ERROR !!! - Installation location ${INSTALL_DEST_BASE} does not exist!"
333         echo "Installation will not complete."
334         echo ""
335         read -p "Press ENTER to exit installer:" BLAH
336         exit 1
337 fi
338
339 # uninstall any older versions
340 UNINSTALLERS=$(find ${INSTALL_DEST_BASE} -maxdepth 1 -type f -name "${PGM_NAME}*.uninstall.sh")
341 if [ ! -z "$UNINSTALLERS" ];
342 then
343         for i in $UNINSTALLERS; do
344                 echo ""
345                 echo "Found existing ${PGM_NAME} installation."
346                 
347                 ANSWER=$(VaildateYesNoQuestion "Do you want to run the uninstaller ${i} ?")
348
349                 if test "y" = $ANSWER;
350                 then
351                         echo ""
352                         echo "Running uninstaller $i"
353                         
354                         ${i}
355                         ${SUPER} rm -f ${i}
356                 fi
357         done
358 fi
359
360
361 # install 
362
363 echo ""
364 echo "Installing ${PGM_NAME} ${PGM_VERSION} built from ${PGM_BUILD} in ${INSTALL_DEST_BASE}"
365 echo ""
366
367 # Copy the new version in the install directory
368 ${SUPER} mkdir ${INSTALL_DEST_BASE}/${PGM_FULL_NAME} 
369 ${SUPER} cp -Rf ${BUNDLE_DIR}/* ${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/
370
371 # write the desktop/menu file
372 echo "[Desktop Entry]" > /tmp/${MENU_FILE}
373 echo "Encoding=UTF-8" >> /tmp/${MENU_FILE}
374 echo "Version=1.0" >> /tmp/${MENU_FILE}
375 echo "Type=Application" >> /tmp/${MENU_FILE}
376 echo "Terminal=false" >> /tmp/${MENU_FILE}
377 echo "Exec=${PGM_EXEC_PATH}" >> /tmp/${MENU_FILE}
378 if [ -z ${PGM_BUILDTYPE} ];
379 then
380         echo "Name=${PGM_NAME}-${PGM_VERSION}" >> /tmp/${MENU_FILE}
381 else
382         echo "Name=${PGM_NAME}-${PGM_VERSION}-${PGM_BUILDTYPE}" >> /tmp/${MENU_FILE}
383 fi
384 echo "Icon=${ICON_NAME}" >> /tmp/${MENU_FILE}
385 echo "Comment=Digital Audio Workstation" >> /tmp/${MENU_FILE}
386 echo "Categories=AudioVideo;AudioEditing;Audio;Recorder;" >> /tmp/${MENU_FILE}
387
388 chmod ugo+rx /tmp/${MENU_FILE}
389 ${SUPER} mv /tmp/${MENU_FILE} ${MENU_FILE_PATH}/.
390
391 # install the Menu, Link, and Icon(s)
392 if [ "T" = ${HAS_XDG} ];
393 then
394         echo "Adding ${PGM_NAME} to the applications menu"
395         ${SUPER} xdg-icon-resource install --context apps --size 16 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_16px.png ${ICON_NAME}
396         ${SUPER} xdg-icon-resource install --context apps --size 22 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_22px.png ${ICON_NAME}
397         ${SUPER} xdg-icon-resource install --context apps --size 32 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_32px.png ${ICON_NAME}
398         ${SUPER} xdg-icon-resource install --context apps --size 48 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_48px.png ${ICON_NAME}
399
400         if [ -e ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg -a -d /usr/share/icons/hicolor/scalable/apps ]; 
401         then
402                 ${SUPER} cp -f ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg  /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
403         fi
404
405         ${SUPER} xdg-desktop-menu install ${MENU_FILE_PATH}/${MENU_FILE}
406         ${SUPER} xdg-desktop-menu forceupdate --mode system                     # Some systems need an extra kick
407         
408         echo ""
409         echo "Creating a desktop link for ${PGM_NAME}"
410         cp ${MENU_FILE_PATH}/${MENU_FILE} ~/Desktop/${DESKTOP_LINK_FILE}
411         chmod ugo+rx ~/Desktop/${DESKTOP_LINK_FILE}
412 else
413         echo ""
414         echo "Creating a desktop link for ${PGM_NAME}"
415         cp ${MENU_FILE_PATH}/${MENU_FILE} ~/Desktop/${DESKTOP_LINK_FILE}
416         chmod ugo+rx ~/Desktop/${DESKTOP_LINK_FILE}
417 fi
418
419 echo ""
420 echo "Copying uninstall script to ${INSTALL_DEST_BASE}"
421 echo ""
422
423 ${SUPER} cp -f ${BUNDLE_DIR}/bin/*.uninstall.sh ${INSTALL_DEST_BASE}/.
424
425 ###########################
426 # Check Jack and qjackctl
427 ###########################
428
429 echo ""
430 echo "Checking to see if Jack is installed"
431 echo ""
432
433 if ! which jackd > /dev/null;
434 then
435         echo ""
436         echo "The program Jack is missing from this system. Jack is a required component of $PGM_NAME."
437         echo ""
438
439         ANSWER=$(VaildateYesNoQuestion "Install jack using system software repository?")
440
441         if test "y" = $ANSWER;
442         then
443                 echo "Attempting to install Jack"
444                 SystemInstall "jackd"
445
446                 if [ $? -ne 0 ];
447                 then
448                         echo ""
449                         read -p "Press ENTER to continue:" BLAH
450                 fi
451         fi
452 else
453         echo "Jack OK"
454 fi
455
456
457 if ! which qjackctl > /dev/null;
458 then
459         echo ""
460         echo "The program QjackCtl is missing from this system."
461         echo "QjackCtl is an extremely useful tool for any system that runs JACK applications like $PGM_NAME."
462         echo "We recommend that you install it."
463         echo ""
464
465         ANSWER=$(VaildateYesNoQuestion "Install QjackCtl using system software repository?")
466
467         if test "y" = $ANSWER;
468         then
469                 echo "Attempting to install QjackCtl"
470                 SystemInstall "qjackctl"
471
472                 if [ $? -ne 0 ];
473                 then
474                         echo ""
475                         read -p "Press ENTER to continue:" BLAH
476                 fi
477         fi
478 fi
479
480
481 ########################
482 # Run Sanity Check
483 ########################
484
485 USER_GROUP_ADJUSTED="f"
486
487 if ! ./${BUNDLE_DIR}/bin/sanityCheck -a > /dev/null;
488 then
489         echo ""
490         echo "System failed the quick sanity check... Looking for the cause"
491
492         if ! ./${BUNDLE_DIR}/bin/sanityCheck -rt > /dev/null;
493         then
494                 echo ""
495                 echo "System does not allow realtime for the current user... Looking for a solution"            
496                 
497                 if ./${BUNDLE_DIR}/bin/sanityCheck -hasaudiogroup > /dev/null;
498                 then
499                         if ./${BUNDLE_DIR}/bin/sanityCheck -memberaudiogroup > /dev/null 2>&1;
500                         then
501                                 ## This is an odd case. We have an audio group and are a member.
502                                 echo ""
503                                 echo "!!! WARNING !!! - The current user can not execute realtime processes."
504                                 echo "This will adversely affect audio latency."
505                                 echo "This system has an audio group and the user is a member. If jack was"
506                                 echo "just installed, a simple log out/in may fix this."
507                                 echo ""
508                                 echo "For best results, please correct this on your system."
509                                 echo "(Hint: check /etc/security/limits.conf or /etc/security/limits.d/)" 
510                                 echo ""
511                                 read -p "Press ENTER to continue:" BLAH
512                         else
513                                 # Not a member of an audio group. Try to fix it.
514                                 
515                                 if ./${BUNDLE_DIR}/bin/sanityCheck -hasgroup audio > /dev/null && find /etc/security -type f -name "*.conf" | xargs grep -q "^@audio.*rtprio";
516                                 then
517                                         # add user to audio group
518                                         echo ""
519                                         echo "Adding user `whoami` to the audio group."
520                                         echo "This should allow you to run realtime tasks. Please re-login for this change to take affect."
521                                         echo ""
522                                         read -p "Press ENTER to continue:" BLAH
523
524                                         user=`whoami`
525                                         if ${SUPER} usermod -a -G audio $user;
526                                         then
527                                                 USER_GROUP_ADJUSTED="t"
528                                         else
529                                                 echo ""
530                                                 echo "!!! ERROR !!! - Not able to add user to the audio group (usermod failed)!"
531                                                 echo ""
532                                                 echo "Please add yourself to the audio group and re-login"
533                                                 echo ""
534                                                 read -p "Press ENTER to continue:" BLAH
535                                         fi
536
537                                 elif ./${BUNDLE_DIR}/bin/sanityCheck -hasgroup jackuser > /dev/null && find /etc/security -type f -name "*.conf" | xargs grep -q "^@jackuser.*rtprio";
538                                 then
539                                         # add user to jackuser group
540                                         echo ""
541                                         echo "Adding user `whoami` to the jackuser group."
542                                         echo "This should allow you to run realtime tasks. Please re-login for this change to take affect."
543                                         echo ""
544                                         read -p "Press ENTER to continue:" BLAH
545
546                                         user=`whoami`
547                                         if ${SUPER} usermod -a -G jackuser $user;
548                                         then
549                                                 USER_GROUP_ADJUSTED="t"
550                                         else
551                                                 echo ""
552                                                 echo "!!! ERROR !!! - Not able to add user to the jackuser group."
553                                                 echo ""
554                                                 echo "Please add yourself to the audio group and re-login"
555                                                 echo ""
556                                                 read -p "Press ENTER to continue:" BLAH
557                                         fi
558                                         
559
560                                 fi
561                         fi
562                 else
563                         # No audio group found on this system!
564                         echo ""
565                         echo "!!! WARNING !!! - The system does not seem to have an audio group (audio or jackuser)."
566                         echo ""
567                         echo "We will not attempt to fix this. Please configure your system to allow"
568                         echo "non-root users to execute realtime tasks."
569                         echo ""
570                         read -p "Press ENTER to continue:" BLAH
571                 fi
572         fi
573
574         if ! ./${BUNDLE_DIR}/bin/sanityCheck -freqscaling > /dev/null;
575         then
576                 echo ""
577                 echo "!!! WARNING !!! - Your system seems to use frequency scaling."
578                 echo "This can have a serious impact on audio latency. You have two choices:"
579                 echo "(1) turn it off, e.g. by chosing the 'performance' governor."
580                 echo "(2) Use the HPET clocksource by passing \"-c h\" to JACK"
581                 echo "(this second option only works on relatively recent computers)"
582                 echo ""
583                 read -p "Press ENTER to continue:" BLAH
584         fi
585
586         if [ "f" = $USER_GROUP_ADJUSTED ];
587         then
588                 if ! ./${BUNDLE_DIR}/bin/sanityCheck -memlock > /dev/null;
589                 then
590                         echo ""
591                         echo "!!! WARNING !!! - You are not allowed to lock memory."
592                         echo ""
593                         echo "We will not attempt to fix this. Please configure your system to allow"
594                         echo "non-root users to execute lock memory."
595                         echo ""
596                         read -p "Press ENTER to continue:" BLAH
597                 fi
598         fi
599 fi
600
601
602 ########################
603 # Install Complete
604 ########################
605
606 echo ""
607 echo "Cleaning up"
608 rm -rf ${BUNDLE_DIR}/
609
610 echo ""
611 echo "!!! Install Complete !!!"
612
613 if [ "t" = $USER_GROUP_ADJUSTED ];
614 then
615         echo "You will need to logout and then login again for all changes to be complete"
616 fi
617
618 echo ""
619 read -p "Press ENTER to exit installer:" BLAH
620
621