Run a shell script from a click on an image in a presentation

I’m a bit frustrated with Libre Office Impress. I have an image of a button on a slide.

If I right click and select Interaction, select Run Program, browse to the path of the script (755) and select Okay. When I click I get the editor with the script. Not the desired outcome.

If I right click and select Interaction, select Run Macro, browse to the path of the Macro and select Okay. I get this:

vnd.sun.star.script:Standard.RunScript.Test?language=Basic&location=document

Sub Test()
	wStyle = 0
	
	Shell("/home/me/bin/run_test.sh", wStyle)
End Sub

Click on the image and it runs the script run_test.sh. The script will properly run.

I set up a second image with Interaction but this time I try to pass arguments to the Macro. I get this

vnd.sun.star.script:Standard.RunScript.execProg?language=Basic&location=document&prog=my_prog.bat&arg1=foo

Sub execProg(urlStr)
    Shell("/home/me/bin/run_script.sh", 0, urlStr)
End Sub

When I click I get the infamous: “wrong number of parameters”

When I do an I’net search on the topic I don’t get any good results. I’ve tried the various ways but I can’t get Run Program to work and I can’t get Run Macro & pass arguments. I do get Run Macro with no arguments to work but that means each interaction requires its own script. Does anyone have any suggestions? RTM seems to point no where useful.

Amazing technique. I’ve tested this with

sub main()  ’ attached as “run macro”
call execProg(“run_script.sh”)
msgbox(“done”)
end sub

Sub execProg(urlStr)
Shell("~/run_script.sh", 0, urlStr)
End Sub

where run_script.sh contains
#!/bin/bash
nano $1
and this works fine for LibO 6.4.7 and linuxmint 20
It opens the editor with the bash script itself to be displayed. Without the #!bin/bash nothing happens.

I don’t work with impress, so I don’t know, what is passed as information to a called macro. But I’m quite sure, you will get an object in LibreOffice, not a string. (Otherwise i will try my handler to get a unicorn).

You may check the code in this german discussion at libreoffice-forum.de

The macro is called via a button and gets the event. From there it gets the model and the suggestion in the thread is to put additional information here the needed Cell in the tag-field to pass it to the macro.
I sugfest to use MRI to find out your options.

sub blah( event )
osheet = Thiscomponent.Sheets.getbyname("Tabelle1")
buttonobject = event.Source.Model
sCellname = buttonobject.tag'additional information

Additional: your “wrong number of parameters” hints you will not get an event passed. So you have to find out wich additional informations are available…

Your Main() doesn’t pass an arguement. With your method I’ll need a different macro string for each script I want to call. Which is actually what I’m doing now.

The issue I’m trying to resolve is passing an argument to sub Main(url) where I add an arg to the end of the Macro string in Interaction:

vnd.sun.star.script:Standard.RunScript.Main?language=Basic&location=document**&prog=my_prog.bat&arg1=foo**

so Main would need something like this: Main(url) but that doesn’t work. I can’t seem to find a way to get the macro string so I can parse the arguments.

@linuxha,

Consider using image buttons instead of images. Your macro can determine the button pressed and modify the parameter as needed. Your Sub Main(url) needs something to call it with this specified parameter. You could have a routine call it such as:

Sub image_button1
    my_parameter = " -p 8"
    Main(my_parameter)
End sub

and each button is attached to one of these. For one routine, use image buttons if graphics are necessary.

@linuxha,

After some testing, it appears there is a bug with Image buttons. This works with a single image button on the page but causes differing problems with more than one on a page. Possibly this bug → tdf#46579

Would say your only choice at this point is the sub I presented in the comment.

The hickup is that triggering the event does not pass an event object to test(), as is the case with a form.
A workaround is to add a name to the image (right click > name > give the argument(s) you want to pass) and in test, use the ‘thiscomponent’ object.
May be further processing is needed to convert the name, arg1_arg2_arg3 into a variable sArgs = (arg1, arg2, arg3)
For reliable code: if there is more than one object on a page, you will have to cycle through the objects as well (getByIndex(i) and f.i. check for a common prefix (IMG) you use: Name = “IMG_arg1_arg2”

Hope you are familiar, and have already installed, the mri extension, it is a must to be able to track down the object function names you need (in this case there is only one image on the slide). Mri is a class browser (and more) because browsing objects is only possible during runtime.

( I know the ask.interface is confusing, but answers are limited to working solutions. You should have commented my comment.)

sub MRI(obj as object)
	Globalscope.BasicLibraries.LoadLibrary( "MRILib" )
	oMRI = CreateUnoService( "mytools.Mri" )
	oMRI.inspect(obj)
end sub

sub test()         REM tested for two slides and object 0 is attached to this macro
	Dim oIMG As object, sName As string, nPages As integer, iCurrentPage As integer
	Dim bLoop As boolean

	nPages = thiscomponent.getDrawPages().getCount()
	i = 0 : bLoop = True
	REM find the active current slide
	While bLoop
		i = i + 1
		iCurrentPage = thiscomponent.getCurrentController().getCurrentPage().Number
		If i = iCurrentPage Then bLoop = False		
	Wend
	sName = "page" & trim$(i)
	REM assume only one image on the page : index(0) is attached to test(), otherwise make loop here
    REM nObjects = thiscomponent.getDrawPages().getByName(sName).getCount()
	oIMG = thiscomponent.getDrawPages().getByName(sName).getByIndex(0)
	sName = oIMG.getName()
	If sName <> "" Then call execProg(sName)
end sub

@parsely,

The problem as I see it is not knowing what item is pressed. When using images and ‘on click’ interaction, there is nothing I have thus found which specifies which image on the page is actually selected - even looping through won’t help.

It occurs to me the better solution is to used image buttons instead and then can use oEvent and check name of control.

Yes,good remark, I stayed to close to the original situation, so this solution is limited to more objects on a page and only one is connected to a macro. Looping is required if the macro is not always attached to the first object. Your suggestion allows for more actions on one page / easier programming, the button name can be used to pass the arg list. Anyhow, within 19 hrs there are options to realise this.
BTW how to get an image button on the slide?

I do not see how looping could be of any help with multiple selections on a single page.

Original question does talk of multiple objects but does not define where they are - could all be on one or on many pages.

Edit:

You stated:

Anyhow, within 19 hrs there are options to realise this.

What does that have to do with anything posted? Are there time limits now?

and:

BTW how to get an image button on the slide?

It is just another control just like a regular button or text field etc.

Edit #2:

One final note. I chose not to even answer this post first without getting myself up to speed on the issue but more importantly, I believed you had the beginnings of a correct direction in your original comment. That was also my initial thought (re-posted in comment under other answer) but held back until you went off in a different direction which I still cannot see how it will work with more than one item on a single page.

But don’t be concerned, I will not post as such in future.

After some testing, it appears there is a bug with Image buttons. This works with a single image button on the page but causes differing problems with more than one on a page. No consistency from one execution to another. Possibly this bug → tdf#46579

The 19 hours remark is referring to the first line in the question, where a judgement about Impress is given. I would be frustrated if there is no solution at all. I’m always amazed, and impressed, that there is a community of volunteers that is able to provide answers that sometimes requires in depth knowledge of specific details. The remark is intended as a tribute to “the wisdom of the crowd”

" I chose not to even answer this post first without getting myself up to speed on the issue" > agreed and will try to be more cautious in the future. I’m on the learning curve

@linuxha,

Struggled a bit with Image controls. There is some buggy behavior when using controls in general in Impress.

Did manage to put two samples together - one with images and the other with Image buttons. Best to start the slide show to see it operate. Demos display message boxes but have done some testing with Shell and running parameters to the script.

Sample using Images ---- MacrosAndImages.odp

Sample using ImageButtons ------ MacrosAndImageButton.odp

Edit:

To complete this, here is what I used to pass parameters to the script file.

Used the second sample from above and replaced the macro with this:

Sub button_released(oEvent)
    Dim my_control As String
    my_control = oEvent.Source.Model.Name
    If my_control = "IB1" Then sURL = " -q 5"
    If my_control = "IB2" Then sURL = " -p"
    x = Shell ("/YOUR_DIRECTORY/run.sh" & sURL)
    Print x
End Sub

Note: if x = 0 then command ran without problem.

Also used this script ( name as run.sh). Copied from Bash parameters and parameter expansions:

#!/bin/bash
echo "OPTIND starts at $OPTIND" >>/YOUR_DIRECTORY/testdata.dat
while getopts ":pq:" optname
  do
    case "$optname" in
      "p")
        echo "Option $optname is specified" >>/YOUR_DIRECTORY/testdata.dat
        ;;
      "q")
        echo "Option $optname has value $OPTARG" >>/YOUR_DIRECTORY/testdata.dat
        ;;
      "?")
        echo "Unknown option $OPTARG"
        ;;
      ":")
        echo "No argument value for option $OPTARG"
        ;;
      *)
      # Should not occur
        echo "Unknown error while processing options"
        ;;
    esac
    echo "OPTIND is now $OPTIND"
  done

Make certain you change directory names in both of the above according to your system.

This all done on Ubuntu 20.04.x with LO v7.1.2.2.

First I want to thank everyone for posting. I’m learning a lot. :slight_smile:

I’m going to give everything a try just need time to do it. Hopefully in the next few days. My presentation (Smart Home @ TCF NJ 2022) is a bit of a ways off but it’s going to take me quite some time to get everything working properly. The presentation and the interactions will make it easier to automate the entire presentation. Which is a good thing as I have so much material that I have to whittle down to fit into the time allotted. :slight_smile:

The Sample using ImageButtons ------ MacrosAndImageButton.odp is perfect. I have one script and one common place to edit. I can add the Image Buttons as needed.

Huge Thanks I really doubt I would have found that one.

@linuxha,

Just be aware of the comments I have already made. This was difficult to get working and tends to be buggy. To me if you compare the amount of code needed between my two samples it is about the same. If with images, the main routine is set correctly, the calling routines (one for each image) are minimal. My choice is for the images and not the image buttons.

However this is ultimately your choice. Just trying to point out what I see.

Yes, ran into one of the bugs. It doesn’t work in Presentation mode. :frowning: It works when I’m preparing the page (and I’ve turned of the design mode).

I’ve resorted to naming each script in interaction (that works Presentation mode). The actual script will kick off some side automation where 2 ESP32/MQTT/MP3 players will carry on a dialog from Red Dwarf (Anyone like any toast?). Node-Red will control the flow (I hope). Still working on the software details. I have the hardware parts but still need to assemble them.

It doesn’t work in Presentation mode

The posted sample does work for me in presentation mode.

Edit:

Sample is set to run in a window not full screen. Window works for me but full screen doesn’t.