#!/bin/bash # muxsa-kvm2png # # part of muxsa, https://git-nks-public.tik.uni-stuttgart.de/edu/muxsa # # this script makes a series of screenshots from a KVM virtual machine # and saves them as PNG files. It will press the PgDown key after each # screenshot. Intended usage: dump a presentation (e.g., Powerpoint # running in a Windows VM) into a series of PNG files, for further # processing with the muxsa tool chain. # MIT License # # Copyright (c) 2023 Sebastian Kiesel # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. ############################################################################ echo "This is muxsa-kvm2png." # various parameters can be set as an environment variable (export XX="y z") # or can be set in our RC file. Otherwise we will assign default values below. if [ -r "${HOME}/.muxsarc" ] ; then echo "Found ${HOME}/.muxsarc ... will source it." . "${HOME}/.muxsarc" fi echo "Will work with these settings:" echo "MUXSA_KVM2PNG_VM_NAME=${MUXSA_KVM2PNG_VM_NAME:="win10-office"}" echo "MUXSA_KVM2PNG_SIZE_X=${MUXSA_KVM2PNG_SIZE_X:="1920"}" echo "MUXSA_KVM2PNG_SIZE_Y=${MUXSA_KVM2PNG_SIZE_Y:="1080"}" echo "MUXSA_KVM2PNG_EXTRA_X=${MUXSA_KVM2PNG_EXTRA_X:="0"}" echo "MUXSA_KVM2PNG_EXTRA_Y=${MUXSA_KVM2PNG_EXTRA_Y:="0"}" echo "MUXSA_KVM2PNG_SLIDE_PREFIX=${MUXSA_KVM2PNG_SLIDE_PREFIX:=""}" echo "MUXSA_KVM2PNG_SLIDE_NUMBER_START=${MUXSA_KVM2PNG_SLIDE_NUMBER_START:="0"}" echo "MUXSA_KVM2PNG_SLIDE_NUMBER_END=${MUXSA_KVM2PNG_SLIDE_NUMBER_END:="9999"}" echo "MUXSA_KVM2PNG_FORCE_OVERWRITE=${MUXSA_KVM2PNG_FORCE_OVERWRITE:=""}" echo "MUXSA_KVM2PNG_BUGFIX_SHOOT_TWICE=${MUXSA_KVM2PNG_BUGFIX_SHOOT_TWICE:=""}" echo "MUXSA_KVM2PNG_SLEEP=${MUXSA_KVM2PNG_SLEEP:="3"}" echo "MUXSA_KVM2PNG_MD5_LAST_SLIDE=${MUXSA_KVM2PNG_MD5_LAST_SLIDE:="092eb68a91b4d2a73833f00a01dc5cb0"}" echo ############################################################################ TMP_FILE="$(mktemp -t muxsa-kvm2png-XXXXXXXXXX.ppm)" if [ ! -w "${TMP_FILE}" ] ; then echo "Error: cannot create tmp_file. abort." exit 1 fi trap 'rm -f -- "${TMP_FILE}"' EXIT ############################################################################ muxsa-kvm2png-screenshot-to-tmp () { echo "muxsa-kvm2png: screenshot ${MUXSA_KVM2PNG_VM_NAME} ${TMP_FILE}" virsh -c qemu:///system "screenshot ${MUXSA_KVM2PNG_VM_NAME} ${TMP_FILE}" if [ $? -ne 0 ] ; then echo "muxsa-kvm2png: screenshot failed. abort." exit 1 fi # the first sceenshot after a resolution change is sometimes garbled # workaround: save it twice if [ "${MUXSA_KVM2PNG_BUGFIX_SHOOT_TWICE}" ] ; then virsh -c qemu:///system \ "screenshot ${MUXSA_KVM2PNG_VM_NAME} ${TMP_FILE}" if [ $? -ne 0 ] ; then echo "muxsa-kvm2png: screenshot failed. abort." exit 1 fi fi # get the size in pixels of the screenshot we have taken # (needs identify from imagemagick), and ... TMP_SZ_X=$(identify -format "%w" "${TMP_FILE}") TMP_SZ_Y=$(identify -format "%h" "${TMP_FILE}") # ... compare to desired size if [ ${TMP_SZ_X} -eq ${MUXSA_KVM2PNG_SIZE_X} -a \ ${TMP_SZ_Y} -eq ${MUXSA_KVM2PNG_SIZE_Y} ] ; then echo "Screenshot is ${TMP_SZ_X} x ${TMP_SZ_Y} - as desired. good." TMP_SZ_OK=1 else echo "Warning: Screenshot is ${TMP_SZ_X} x ${TMP_SZ_Y} but desired"\ "size is ${MUXSA_KVM2PNG_SIZE_X} x ${MUXSA_KVM2PNG_SIZE_Y} ." TMP_SZ_OK="" fi } ############################################################################ echo "Performing a test screenshot to check image size." muxsa-kvm2png-screenshot-to-tmp if [ ! "${TMP_SZ_OK}" ] ; then echo "We will try to adjust the size of the spicy window." case "$(read -p "Press q [return] to abort or [return] to continue: ")" in n|N|q|Q) echo "muxsa-kvm2png aborted." exit 1; ;; esac xdotool search --class spicy windowsize %@ \ $(( ${MUXSA_KVM2PNG_SIZE_X} + ${MUXSA_KVM2PNG_EXTRA_X} )) \ $(( ${MUXSA_KVM2PNG_SIZE_Y} + ${MUXSA_KVM2PNG_EXTRA_Y} )) sleep 5 echo "Performing another test screenshot to check image size." muxsa-kvm2png-screenshot-to-tmp if [ ! "${TMP_SZ_OK}" ] ; then echo "Screenshot still does not have the desired size in pixels." echo "Maybe, resizing the spicy window has failed." echo "Or maybe, you need to adjust MUXSA_KVM2PNG_EXTRA_X / _Y" # extra size accounts for menus of the spicy window. # if the desired size is larger than the actual size, that # difference has to be added to the current extra size echo "Current MUXSA_KVM2PNG_EXTRA_X value: ${MUXSA_KVM2PNG_EXTRA_X}" echo "Try: $(( ${MUXSA_KVM2PNG_SIZE_X} - ${TMP_SZ_X} + \ ${MUXSA_KVM2PNG_EXTRA_X} ))" echo "Current MUXSA_KVM2PNG_EXTRA_Y value: ${MUXSA_KVM2PNG_EXTRA_Y}" echo "Try: $(( ${MUXSA_KVM2PNG_SIZE_Y} - ${TMP_SZ_Y} + \ ${MUXSA_KVM2PNG_EXTRA_Y} ))" echo "You can set these as environment variables or in ~/.muxsarc" echo "muxsa-kvm2png aborted." exit 1; fi fi echo "Successfully took test screenshot with the right size." ############################################################################ cat < "$OUTFILE" if [ $? -ne 0 ] ; then echo "Converting and saving screenshot failed. abort." exit 1 fi if [ "${MUXSA_KVM2PNG_MD5_LAST_SLIDE}" ] ; then if md5sum "${OUTFILE}" | \ grep -q "^${MUXSA_KVM2PNG_MD5_LAST_SLIDE}" ; then echo "Screenshot's md5sum = MUXSA_KVM2PNG_MD5_LAST_SLIDE. end." break fi fi if [ "${SLIDE_NUMBER}" -gt "${MUXSA_KVM2PNG_SLIDE_NUMBER_END}" ] ; then echo "Maximum slide number reached. abort." exit 1 fi echo "Sending PgDown and sleeping briefly" virsh -c qemu:///system "send-key ${MUXSA_KVM2PNG_VM_NAME} KEY_PAGEDOWN" sleep "${MUXSA_KVM2PNG_SLEEP}" done echo "muxsa-kvm2png finished successfully!" ############################################################################