OSX - cocoaDialog
Sometimes it would be just nice to have a graphical user interface (GUI) for your own tiny scripts, but writing a full program using a graphic library is absolutely exaggerated. cocoaDialog could be the solution for some of these use cases.
What is cocoaDialog? cocoaDialog is a command line interface that allows the use of common GUI dialogs such as file selectors, text input, progress bars, confirmations and more.
I really like this program. It is easy, fun and can be integrated quickly in a script.The cool thing is that it can be used also by people without GUI programming skills. I want to show you such an example of how cocoaDialog could be used.
This is what you get.
1. Preparation
Go to https://mstratman.github.io/cocoadialog/ and get the latest version of cocoaDialog. If you want to download the stable or the beta version, that's up to you. Check the documentation for more info.
I downloaded the version 3.0-beta7. This is a dmg file which you open and then you drag 'n' drop the cocoaDialog app either to your applications directory (/Applications) or inside your app (see next chapter). This depends on if you want to have the cocoaDialog app only ones on your system and reuse it OR if you want to have it inside the app you are creating so that it becomes a single all in one package.
For my example I will use an existing command line tool named youtube-dl. For more info check https://rg3.github.io/youtube-dl/ or http://youtube-dl.org or https://github.com/rg3/youtube-dl/ With youtube-dl you can download videos from many video sites and it also allows extracting the audio track from the downloaded video.
2. The app folder
Create a directory with a name representing your app you want to create. In my case I named it YoutubeDL and I placed in /Users/USERNAME/Applications since OSX has a directory for user specific apps. Inside that folder create another folder named Contents. Inside Contents create 2 more folders named MacOS and Resources. Download this Info.plist file here and put it into the Contents folder.
Now it should look like this ...
Open the Info.plist file for editing and fill out the fields ...
CFBundleExecutable (this shall be the name of the script)
CFBundleIconFile (the name of the icon file we will create later)
CFBundleIdentifier (a unique identifier for your app)
CFBundleName (simply the app name)
CFBundleShortVersionString
CFBundleVersion
The CFBundleIdentifier normally consists of 3 parts separated by period. What I have seen so far is that the middle part (blurred) is the company name. I don't know if there is a syntax we have to follow or if it can be any string.
Later we will rename this app directory by appending ".app". This way OSX will recognize the folder as an application, automatically display the icon and it can be executed like any other application.
3. The icon
For the icon we need a icns file. Design your own icon (1024x1024) and save it (I think with alpha channel) as png. To convert from png to icns download the following script and call it with your png file as first parameter.
https://gist.github.com/marcotrosi/0a1a87e671d89e545dcd
I don't know why but once I had a file which I could not convert. I could not figure out what the problem was. Maybe it had to do with the alpha channel.
You can also download one of these files for testing.
YoutubeDL.png
YoutubeDL.icns
Put the icns file into the Resources folder and make sure it has the same name as given in the Info.plist file.
4. Pre-Testing
To understand everything a little bit better we will do some intermediate steps. I want to know how cocoaDialog works, I want to check if the created basic app is working as expected and I want to see what the environment looks like when running an app.
4.1. Testing cocoaDialog
To test cocoaDialog we need to run the command line tool which is inside the cocoaDialog app. Open the Terminal app and run the following command to create a bubble
/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog bubble --title "foo" --text "bar"
and this to test the OK message box
/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog ok-msgbox --text "foo" --informative-text "bar"
Let's break this down. As usual at first the tool name. Here cocoaDialog, but we are calling it with the absolute path. Second thing (but first tool argument) is the type of box you want to create (bubble or ok-msgbox). And then some box specific parameters follow.
For information read the cocoaDialog documentation
4.2. Testing the app
Create in the MacOS folder a new file with the exact name as given in the Info.plist file in the CFBundleExecutable tag. I named mine YoutubeDL. Put the following lines into the file.
#!/bin/bash set > /Users/${USER}/Desktop/youtubedl.log
First line is the shebang line, and with the second line we write all environment variables into a log file placed on the desktop.
And now we finally rename our app folder by appending .app. So the YoutubeDL folder becomes YoutubeDL.app. But you won't see it really. OSX hides the extension and replaces the folder icon with the icon we created. If this happens then you did everything correctly. You will also notice that if you try to rename it again the .app in the filename will not be visible and can not be changed with the usual Finder renaming shortcut (enter key). Press Cmd+i instead to open the info box and rename the folder in the "Name & Suffix" field. Of course command line works too - it's just a folder.
If we double-click the app icon we won't see a lot, but on your desktop the file youtubedl.log should appear. This means the app executed the YoutubeDL script. The app basically works.
In the beginning of this chapter I told you that I am interested in the environment when running the app. That's why I choose the set command in the bash script. Open the log file. Have a look at the PWD variable. Mine is set to /. I hope yours is too. This means the working directory is the root directory when an app gets executed this way. The variable would be different when started from command line. Furthermore the PATH variable shows me that my bashrc/profile file has not been loaded. This all may sound now logic to you, but actually it took me a while to figure out these simple facts. I tested everything on command line and was pretty confused when suddenly things didn't work when executed normally.
5. Creating the script
Theoretically you can start cocoaDialog in any language via system calls, but in bash this is pretty easy and we already did it. So let's stick with that.
If you wanna access a tool/program or a file you can do that with absolute or with relative paths. For tools there is even a third option under Bash, by just typing the tool name and the Bash finds the tool for you by searching in each path given in the PATH variable. Depending on where we place the tools and what we are intending to do with the app we have to decide wether to call a tool with absolute path, relative path or through the PATH variable. That's totally up to you.
For this Bash script let's assume (as prepared above) …
cocoaDialog is in /Applications
YoutubeDL is in /Users/USERNAME/Applications
youtube-dl is in /usr/local/bin
… and we are going to use absolute paths which is of course not dynamic but easy.
5.1. Version 1
This version downloads the video directly by taking the URL from the clipboard and informs with a bubble failure or success. Imagine you are watching a youtube video in Safari and you want to download it. Press Cmd+L, Cmd+C, Cmd+Space, type YoutubeDL, press Enter (select URL, copy URL, start YoutubeDL).
https://gist.github.com/marcotrosi/89f535a0052f8e3c8454
5.2. Version 2
In this version you can decide between full video and audio track only, and you can paste the URL manually in case you started YoutubeDL before copying the URL into clipboard.
We discovered earlier that the bashrc/profile files are not loaded and this leads now to the first problem. For the audio extraction youtube-dl uses ffmpeg. But the /usr/local/bin path is not part of the PATH variable. We fix this with a quick workaround in line 4.
https://gist.github.com/marcotrosi/ec4fa686682745d5021d
5.3. Version 3
To get rid of the workaround from version 2 we need a second file. The filename will be YoutubeDL and the actual script (like version 1 and 2) will be renamed to YoutubeDL.sh.
The YoutubeDL wrapper script starts a shell in login mode (-l), which means that the users normal environment is available, and then it executes the main script (-c). The PATH variable is now set as the user needs it and therefore we can remove the workaround from version 2.
Additionally I changed the audio format to MP3. Without the --audio-format option you get whatever format is inside the video file. I added a progressbar and fancy icons to the bubbles.
https://gist.github.com/marcotrosi/b5997d48b0a594f35959
Btw. if you want to put now cocoaDialog/youtube-dl inside your application you have to create the absolute path to them. But as the working directory is the root directory, the absolute path is the same as the relative path start from the working directory which is the root. Clear? :-) You can use for example
dirname $0
to get the full path to the MacOS folder, and this is a good starting point I think. Let's assume you put the cocoaDialog.app into the MacOS folder then you could replace the line
CocoaDialog='/Applications/cocoaDialog.app/Contents/MacOS/cocoaDialog'
with
CocoaDialog='$(dirname $0)/cocoaDialog.app/Contents/MacOS/cocoaDialog'
and now it should work no matter where I put the YoutubeDL application. I didn't test it but I would expect it. Of course this needs to be repeated for youtube-dl too.
I would like to know what you can do with cocoaDialog













