Notification sounds on RStudio server [duplicate] - r

When I run R scripts I go do something else on a different desktop. If I don't check frequently, I never know when something is finished. Is there a way to invoke a beep (like a system beep) or get R to play a sound or notify growl via some code at the end of my script?

I have a package (beepr) with the sole purpose of making notification sounds in R which should work cross-platform. Run the following to install beepr and make a sound:
install.packages("beepr")
library(beepr)
beep()
More info at github: https://github.com/rasmusab/beepr

alarm()
The alarm function. It works by sending \a to the console

On MacOSX you can let the computer speak:
system("say Just finished!")
and you can also change the artificial voice that will speak:
system("say -v Kathy Just finished!")
You can pick any voice that is available on your computer. On Yosemite you can see which voices are installed in System Preferences -> Dictation & Speech -> Text to Speech.

You should have it tweet when it's done: http://cran.r-project.org/web/packages/twitteR/index.html

alarm doesn't work on my Windows machine so I created a function that does actually make noise.
beep <- function(n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
}
This clearly could only work on Windows but I don't guarantee it will even run on an arbitrary Windows computer. I've only tested it on my machine but I figured I'd post it in case anybody has the same problem with alarm that I do.

cat('Hello world!\a')

How about something reasonably OS independent for OSes with GUIs and web-browsers? It even works on RStudio Server!
browseURL('https://www.youtube.com/watch?v=QH2-TGUlwu4')

Not only that, you can also also put some epic music from Youtube when the program is done looping :) (For Ubuntu/Debian:)
system("xdg-open 'http://www.youtube.com/watch?v=9jK-NcRmVcw'")

UPDATE:
With macOS 10.9 (Mavericks) and later, you can post notifications using plain AppleScript:
theTitle <- "A Title"
theMsg <- "A message here"
cmd <- paste("osascript -e ", "'display notification ", '"', theMsg, '"', ' with title ', '"', theTitle, '"', "'", sep='')
system(cmd)
This removes the need to install terminal-notifier, referenced below.
--
I've got terminal-notifier installed on my Mac to get desktop notifications from the command line. You can then wrap up a call to the system() command like this (change the path, obviously):
notify <- function(msgString='Message from R', titleString='Message from R', speakIt=FALSE) {
cmd <- paste('~/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier -message ', '"', msgString, '" -title "', titleString, '"', sep='')
system(cmd)
if (speakIt) {
system(paste('say', msgString))
}
}
You can call the function like this
notify("R is done", "Message from R", speakIt=TRUE)
to get a message like this:
Update: Included #VLC's say command.

Please use shell.exec("url") to open some YouTube clip on Windows

Or if you're using GNU/Linux distro and have pcspkr module blacklisted (PC speaker was always annoying me), try combining system with some auditive/visual notification, e.g.
system("aplay -t wav /usr/share/sounds/phone.wav") # for auditive bell (an I mean it literary)
system("zenity --title=\"R script info\" --text=\"Script has finished with zero exit status\" --info") # for GTK dialog
You can check zenity manual if you prefer alert in, say, notification area... But, with system function, you can do pretty much anything: send an email, run some other script, reboot the machine, sudo rm -rf *.*, etc. anything... and I mean it.
But this stands only IF you're running GNU/Linux (or UNIX) distribution, otherwise, stick to Windows specific commands, though in that case, I can't give you much info...

Inspired by beepr, this is the function I'm currently using for these kind of problems :D
work_complete <- function() {
cat("Work complete. Press esc to sound the fanfare!!!\n")
on.exit(beepr::beep(3))
while (TRUE) {
beepr::beep(4)
Sys.sleep(1)
}
}

How about playing some music?
shell.exec("foo/Born.to.be.wild.mp3")

take a look at this package: RPushBullet
An R interface to the Pushbullet messaging service which provides fast
and efficient notifications (and file transfer) between computers,
phones and tablets
RPushbullet is completely free and multi platform. As for your question, you can use this library to send a Push to your browser, but obviously it becomes amazing when you need something than can notify you while you are away.
Moreover, the creator of the R package is the same of the well known Rcpp, Dirk Eddelbuettel. I'd say it's worth a shot!

Do this:
song <- function() {
for(i in 1:2) {
for(i in 1:4) {
for(i in 1:4) {
beep(7)
Sys.sleep(0.25)
beep()
Sys.sleep(0.22)
}
beep(2)
}
beep(11)
}
beep(4)
}
song()
You can jam out to it.

How about using Windows SpeechSynthesizer?
message <- "job done!"
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
paste0("$speak.Speak('", message, "');\"")
))
This may by nicely used in iterating operations and read something like "First job done", "Second job done" etc.:
say_something <- function(message) {
message <- paste0("$speak.Speak('", message, "');\"")
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
message
))
}
operations <- c("1st.", "2nd.", "3rd.")
lapply(operations, function(x) say_something(message=paste(x, "job done")))
*Note, that this uses system defaul language settings. The example is based on english lector, it can be changed using SelectVoice method. To check available lectors use:
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
"$speak.GetInstalledVoices().VoiceInfo")
)
That gives:
Gender : Female
Age : Adult
Name : Microsoft Paulina Desktop
Culture : pl-PL
Id : TTS_MS_PL-PL_PAULINA_11.0
Description : Microsoft Paulina Desktop - Polish
SupportedAudioFormats : {}
AdditionalInfo : {[Age, Adult], [Gender, Female], [Language, 415], [Name, Microsoft Paulina Desktop]...}
Gender : Male
Age : Adult
Name : Microsoft David Desktop
Culture : en-US
Id : TTS_MS_EN-US_DAVID_11.0
Description : Microsoft David Desktop - English (United States)
SupportedAudioFormats : {}
AdditionalInfo : {[Age, Adult], [Gender, Male], [Language, 409], [Name, Microsoft David Desktop]...}
Finally a function to select the lector by his "name" like "David", "Paulina" or "Hazel":
say_something <- function(message , voice) {
voice <- paste0("\"$speak.SelectVoice('Microsoft ", voice, " Desktop');" )
message <- paste0("$speak.Speak('", message, "');\"")
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
voice,
message
))
}
operations <- c("1st.", "2nd.", "3rd.")
lapply(operations, function(x) say_something(message=paste(x, "job done"), voice="David"))

Dason's answer is great, obviously, because it will work on basically any Windows machine without requiring anything except R itself.
But one thing I have been wondering is how to make these functions actually beep after a code is run.
If you do something like this:
beepR <- function(x, n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
return(x)
}
You can just pipe anything to it and it will return whatever you piped, so you can do like. See the example below.
fa <- psych::fa(x, 1) |> beepR()
I'm using here the native pipe |> that was introduced in R 4.1, but you can use the %>% pipe from the maggitr package if you like; they work the exact same way. Anyway, that will beep as soon as the analysis ends, and the variable fa will contain the results of the factor analysis.
Of course, here I used the beep function that Dason provided you, but you could just as easily add anything where I indicated below.
beepR <- function(x){
# your code here #
return(x)
}
If you wish to add that function every time RStudio opens, refer to RStudio's Managing R with .Rprofile, .Renviron, Rprofile.site, Renviron.site, rsession.conf, and repos.conf to learn how to use a .Rprofile file.

You can use notify-send command:
system("notify-send \"R script finished running\"")

Because of these many ideas, I have created a solution without Internet access, because I work with a VPN client with Windows. So it plays a typical Windows sound, which is usually on any Windows operating system.
#Function with loop, press Esc to stopp
alarm2 <- function(){
while(TRUE){
system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
Sys.sleep(1)
}
}
Function without loop
alarm3 <- function(){
system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
Sys.sleep(1)
}

The following code produces a beep and does not depend on a .mp3 or .wav file:
switch(Sys.info()[['sysname']],
Linux = {
system('play -n synth 0.1 tri 1000.0')}
)

Combining some ideas on the thread, I implement this:
options(error = function() {
if (interactive()) {
# require("beepr"); beep(10)
system("mplayer /usr/share/sounds/freedesktop/stereo/dialog-warning.oga ")
system("notify-send -u normal 'R session' 'An error occured!'")
}
})
I regularly use stop() on interactive session like Rstudio, on scripts I am working and want to re-run to a point. This way I can switch to another desktop while waiting. I may test it to '.Rprofile'

Related

ulimit different between ubuntu terminal and call from R

I am trying to create mapbox tiles using mapboxapi::tippecanoe() in R. Unfortunately, my work computer runs Windows 10, which greatly complicates what I am trying to do. Tippecanoe is a Unix executable, so I downloaded and installed Ubuntu and am running it on a Windows subsystem for Linux. To get tippecanoe to launch, I had to edit the source code of mapboxapi::tippecanoe() to pass arguments to WSL. I then ran into an issue where Tippecanoe would give me an error that it could not open database files. Some research on Github led me to believe that this was related the number of open files limit in Ubuntu. After a lot of digging, I was able to increase ulimit -n to 65535 for on my ubuntu terminal. As soon as I launch Ubuntu, if I type in ulimit -n, I get 65535. However, when I call `sytem2("wsl", "ulimit -n"), I get the default value of 1024. I thought this was due to the user that R was calling in Ubuntu, but running system2("wsl", "whoami") returned the username for who I increased both the hard and soft nofile limits for. I am really stumped. Apologies for not pasting a reproducible example, but I am not sure how to make one for this situation. Any help would be much appreciated. Thanks!
Well after a whole lot of tinkering, this ended up being mostly a straightforward R code issue. The ulimit issue may still have been a problem, but actually I need to fix the R code in mapboxapi::tippecanoe(). Because mapboxapi::tippecanoe()uses the system() command to call tippecanoe, not only did I need to change the call to invoke wsl through a login shell using system2("wsl", "- d Ubuntu -lc 'tippecanoe <arguments to tippecanoe>'"), but I also needed to change the paths that R sent to tippecanoe to be linux paths instead of Window paths. If anyone else is having trouble with this, here is the tweaked mapboxapi::tippecanoe() command code that actually worked for me:
tippecanoe2<-function (input, output, layer_name, min_zoom = NULL,
max_zoom = NULL, drop_rate = NULL, overwrite = TRUE, other_options = NULL,
keep_geojson = FALSE)
{
check_install <- system2("wsl", "tippecanoe -v") == 0
linux_dir<-paste(getwd(), layer_name, sep="/")#make a directory in your linux directory for the .mbtiles
parsed<-strsplit(linux_dir, split="/") #parse the windows directory path
n<-length(parsed[[1]])
dir_out<-paste("",parsed[[1]][n-1], parsed[[1]][n], sep="/") #construct the linux directory path
dir.create(linux_dir)
op<-options(useFancyQuotes = FALSE)
if (!check_install) {
rlang::abort(c("tippecanoe is not installed or cannot be found by the application you are using to run mapboxapi.",
"If you haven't installed tippecanoe, please visit https://github.com/mapbox/tippecanoe for installation instructions.",
"If you have installed tippecanoe, run `Sys.getenv('PATH')` and make sure your application can find tippecanoe. If it cannot, adjust your PATH accordingly."))
}
opts <- c()
if (!is.null(min_zoom)) {
opts <- c(opts, sprintf("-Z%s", min_zoom))
}
if (!is.null(max_zoom)) {
opts <- c(opts, sprintf("-z%s", max_zoom))
}
if (is.null(min_zoom) && is.null(max_zoom)) {
opts <- c(opts, "-zg")
}
if (!is.null(drop_rate)) {
opts <- c(opts, sprintf("-r%s", drop_rate))
}
else {
opts <- c(opts, "-as")
}
if (overwrite) {
opts <- c(opts, "-f")
}
collapsed_opts <- paste0(opts, collapse = " ")
if (!is.null(other_options)) {
extra_opts <- paste0(other_options, collapse = " ")
collapsed_opts <- paste(collapsed_opts, extra_opts)
}
dir <- linux_dir
if (any(grepl("^sf", class(input)))) {
input <- sf::st_transform(input, 4326)
if (is.null(layer_name)) {
layer_name <- stringi::stri_rand_strings(1, 6)
}
if (keep_geojson) {
outfile <- paste0(layer_name, ".geojson")
path <- file.path(dir_out, outfile)
sf::st_write(input, path, quiet = TRUE, delete_dsn = TRUE,
delete_layer = TRUE)
}
else {
tmp <- tempdir("//wsl$/Ubuntu/tmp")#Here you would need to tweak to the file path for your linux distribution's temporary directory
tempfile <- paste0(layer_name, ".geojson")
path <- file.path(tmp, tempfile)
sf::st_write(input, path, quiet = TRUE, delete_dsn = TRUE,
delete_layer = TRUE)
}
call <- sprintf("tippecanoe -o %s/%s %s %s", dir_out, output,
collapsed_opts, path)
call2<-paste("-d Ubuntu /bin/bash -lc", sQuote(call, op), sep=" ")
system2("wsl", call2)
}
else if (inherits(input, "character")) {
if (!is.null(layer_name)) {
collapsed_opts <- paste0(collapsed_opts, " -l ",
layer_name)
}
call <- sprintf("tippecanoe -o %s/%s %s %s", dir_out, output,
collapsed_opts, input)
call2<-paste("-d Ubuntu /bin/bash -lc", sQuote(call, op), sep=" ")
system2("wsl", call2)
}
}

Deployed R app with Shiny crash with 'could not find function "httpdPort"'

I have an application built with Shiny (a tutorial, where ui.R and server.R are taken from here: http://shiny.rstudio.com/tutorial/lesson1/).
I have these two files in shiny-frontend folder, and if I runApp("shiny-frontend") locally in RStudio - everything works great and I see the tutorial in my browser.
Now I want the same app to be put into Bluemix via cloudfoundry. I'm using this: http://www.ibm.com/developerworks/library/ba-rtwitter-app/ as a tutorial, but struggling with an error.
I have a start.r file which I run as R -f ./start.r --gui-none --no-save. I'm using https://github.com/virtualstaticvoid/heroku-buildpack-r buildpack.
My start.r looks like this (taken from the bluemix tutorial with a very minor modifications):
library(shiny)
if (Sys.getenv('VCAP_APP_PORT') == "") {
print("Running Shiny")
runApp("shiny-frontend")
} else {
# In case we're on Cloudfoundry, run this:
print('running on CF')
# Starting Rook server during CF startup phase - after 60 seconds start the actual Shiny server
library(Rook)
myPort <- as.numeric(Sys.getenv('VCAP_APP_PORT'))
myInterface <- Sys.getenv('VCAP_APP_HOST')
status <- -1
# R 2.15.1 uses .Internal, but the next release of R will use a .Call.
# Either way it starts the web server.
if (as.integer(R.version[["svn rev"]]) > 59600) {
status <- .Call(tools:::startHTTPD, myInterface, myPort)
} else {
status <- .Internal(startHTTPD(myInterface, myPort))
}
if (status == 0) {
unlockBinding("httpdPort", environment(tools:::startDynamicHelp))
assign("httpdPort", myPort, environment(tools:::startDynamicHelp))
s <- Rhttpd$new()
s$listenAddr <- myInterface
s$listenPort <- myPort
s$print()
Sys.sleep(60)
s$stop()
}
# run shiny server
sink(stderr())
options(bitmapType='cairo')
getOption("bitmapType")
print("test")
write("prints to stderr", stderr())
write("prints to stdout", stdout())
write(port, stdout())
runApp('shiny-frontend',port=myPort,host="0.0.0.0",launch.browser=F)
}
And my init.r, looks like this:
install.packages("shiny", clean=T)
install.packages("Rook", clean=T)
Then when I run, everything is deployed correctly, but then when I try to go by the route, I see an error in the log:
* ERR Calls: <Anonymous> -> startDynamicHelp
* ERR Execution halted
* ERR Error in startDynamicHelp(FALSE) : could not find function "httpdPort"
I also noticed that assigned port is different every time, which is weird and the route in bluemix dashboard does not mention it. But I output the port to the log, and use that number.
Also the way I'm doing it seems a bit too complicated, so if anybody could suggest any easier way, I'd appreciate it
it took me a while to understand that this error is thrown by R because it can not find the function (not the value) httpdPort. Instead of binding httpdPort to a function you are binding it to a value. The line s$stop() is the one causing trouble. It calls startDynamicHelp that assumes that httpdPort is a function defined in the environment tools.
To fix this issue you can change the block if (status == 0){...} in your code to:
if (status == 0) {
getSettable <- function(default){
function(obj = NA){if(!is.na(obj)){default <<- obj};
default}
}
myHttpdPort <- getSettable(myPort)
unlockBinding("httpdPort", environment(tools:::startDynamicHelp))
assign("httpdPort", myHttpdPort, environment(tools:::startDynamicHelp))
s <- Rhttpd$new()
s$listenAddr <- myInterface
s$listenPort <- myPort
s$print()
Sys.sleep(60)
s$stop()
}

Pause R script to input a filename

I have an R script that does some simple elaboration of data in .CSV files and I want to be able to input a filename from keyboard each time.
The system I am using at the moment is first define a function ans save it as "usr_filename.R":
usr.filename <- function()
{
readline("Please enter filename: ")
}
data.filename <- usr.filename()
And then call it from within my script:
#Input filename
source("usr_filename.R")
This system works, but only as long as the script is run line by line in R Studio; if I try to run the whole script at once by selecting it all and clicking "Run", the result is:
usr.filename
function()
{
readline("Please enter filename: ")
}
So I tried using a different function, with readLines:
usr.filename2 <- function()
{
data.filename <- readLines(prompt="Please enter filename: ", n=-1)
}
But also this solution does not work. Anyone can help me resolving this problem?
R version 3.0.3 (2014-03-06) - Rstudio: Version 0.98.501 - Windows 7 Professional 32bit SP1
Why not use the file.choose() function to select a file?

system open RStudio close connection

I'm attempting to use R to open a .Rproj file used in RStudio. I have succeeded with the code below (stolen from Ananda here). However, the connection to open RStudio called from R is not closed after the file is opened. How can I sever this "connection" after the .Rproj file is opened? (PS this has not been tested on Linux or Mac yet).
## Create dummy .Rproj
x <- c("Version: 1.0", "", "RestoreWorkspace: Default", "SaveWorkspace: Default",
"AlwaysSaveHistory: Default", "", "EnableCodeIndexing: Yes",
"UseSpacesForTab: No", "NumSpacesForTab: 4", "Encoding: UTF-8",
"", "RnwWeave: knitr", "LaTeX: pdfLaTeX")
loc <- file.path(getwd(), "Bar.rproj")
cat(paste(x, collapse = "\n"), file = loc)
## wheresRStudio function to find RStudio location
wheresRstudio <-
function() {
myPaths <- c("rstudio", "~/.cabal/bin/rstudio",
"~/Library/Haskell/bin/rstudio", "C:\\PROGRA~1\\RStudio\\bin\\rstudio.exe",
"C:\\RStudio\\bin\\rstudio.exe")
panloc <- Sys.which(myPaths)
temp <- panloc[panloc != ""]
if (identical(names(temp), character(0))) {
ans <- readline("RStudio not installed in one of the typical locations.\n
Do you know where RStudio is installed? (y/n) ")
if (ans == "y") {
temp <- readline("Enter the (unquoted) path to RStudio: ")
} else {
if (ans == "n") {
stop("RStudio not installed or not found.")
}
}
}
temp
}
## function to open .Rproj files
open_project <- function(Rproj.loc) {
action <- paste(wheresRstudio(), Rproj.loc)
message("Preparing to open project!")
system(action)
}
## Test it (it works but does no close)
open_project(loc)
It's not clear what you're trying to do exactly. What you've described doesn't really sound to me like a "connection" -- it's a system call.
I think what you're getting at is that after you run open_project(loc) in your above example, you don't get your R prompt back until you close the instance of RStudio that was opened by your function. If that is the case, you should add wait = FALSE to your system call.
You might also need to add an ignore.stderr = TRUE in there to get directly back to the prompt. I got some error about "QSslSocket: cannot resolve SSLv2_server_method" on my Ubuntu system, and after I hit "enter" it took me back to the prompt. ignore.stderr can bypass that (but might also mean that the user doesn't get meaningful errors in the case of serious errors).
In other words, I would change your open_project() function to the following and see if it does what you expect:
open_project <- function(Rproj.loc) {
action <- paste(wheresRstudio(), Rproj.loc)
message("Preparing to open project!")
system(action, wait = FALSE, ignore.stderr = TRUE)
}

Is there a way to make R beep/play a sound at the end of a script?

When I run R scripts I go do something else on a different desktop. If I don't check frequently, I never know when something is finished. Is there a way to invoke a beep (like a system beep) or get R to play a sound or notify growl via some code at the end of my script?
I have a package (beepr) with the sole purpose of making notification sounds in R which should work cross-platform. Run the following to install beepr and make a sound:
install.packages("beepr")
library(beepr)
beep()
More info at github: https://github.com/rasmusab/beepr
alarm()
The alarm function. It works by sending \a to the console
On MacOSX you can let the computer speak:
system("say Just finished!")
and you can also change the artificial voice that will speak:
system("say -v Kathy Just finished!")
You can pick any voice that is available on your computer. On Yosemite you can see which voices are installed in System Preferences -> Dictation & Speech -> Text to Speech.
You should have it tweet when it's done: http://cran.r-project.org/web/packages/twitteR/index.html
alarm doesn't work on my Windows machine so I created a function that does actually make noise.
beep <- function(n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
}
This clearly could only work on Windows but I don't guarantee it will even run on an arbitrary Windows computer. I've only tested it on my machine but I figured I'd post it in case anybody has the same problem with alarm that I do.
cat('Hello world!\a')
How about something reasonably OS independent for OSes with GUIs and web-browsers? It even works on RStudio Server!
browseURL('https://www.youtube.com/watch?v=QH2-TGUlwu4')
Not only that, you can also also put some epic music from Youtube when the program is done looping :) (For Ubuntu/Debian:)
system("xdg-open 'http://www.youtube.com/watch?v=9jK-NcRmVcw'")
UPDATE:
With macOS 10.9 (Mavericks) and later, you can post notifications using plain AppleScript:
theTitle <- "A Title"
theMsg <- "A message here"
cmd <- paste("osascript -e ", "'display notification ", '"', theMsg, '"', ' with title ', '"', theTitle, '"', "'", sep='')
system(cmd)
This removes the need to install terminal-notifier, referenced below.
--
I've got terminal-notifier installed on my Mac to get desktop notifications from the command line. You can then wrap up a call to the system() command like this (change the path, obviously):
notify <- function(msgString='Message from R', titleString='Message from R', speakIt=FALSE) {
cmd <- paste('~/terminal-notifier/terminal-notifier.app/Contents/MacOS/terminal-notifier -message ', '"', msgString, '" -title "', titleString, '"', sep='')
system(cmd)
if (speakIt) {
system(paste('say', msgString))
}
}
You can call the function like this
notify("R is done", "Message from R", speakIt=TRUE)
to get a message like this:
Update: Included #VLC's say command.
Please use shell.exec("url") to open some YouTube clip on Windows
Or if you're using GNU/Linux distro and have pcspkr module blacklisted (PC speaker was always annoying me), try combining system with some auditive/visual notification, e.g.
system("aplay -t wav /usr/share/sounds/phone.wav") # for auditive bell (an I mean it literary)
system("zenity --title=\"R script info\" --text=\"Script has finished with zero exit status\" --info") # for GTK dialog
You can check zenity manual if you prefer alert in, say, notification area... But, with system function, you can do pretty much anything: send an email, run some other script, reboot the machine, sudo rm -rf *.*, etc. anything... and I mean it.
But this stands only IF you're running GNU/Linux (or UNIX) distribution, otherwise, stick to Windows specific commands, though in that case, I can't give you much info...
Inspired by beepr, this is the function I'm currently using for these kind of problems :D
work_complete <- function() {
cat("Work complete. Press esc to sound the fanfare!!!\n")
on.exit(beepr::beep(3))
while (TRUE) {
beepr::beep(4)
Sys.sleep(1)
}
}
How about playing some music?
shell.exec("foo/Born.to.be.wild.mp3")
take a look at this package: RPushBullet
An R interface to the Pushbullet messaging service which provides fast
and efficient notifications (and file transfer) between computers,
phones and tablets
RPushbullet is completely free and multi platform. As for your question, you can use this library to send a Push to your browser, but obviously it becomes amazing when you need something than can notify you while you are away.
Moreover, the creator of the R package is the same of the well known Rcpp, Dirk Eddelbuettel. I'd say it's worth a shot!
Do this:
song <- function() {
for(i in 1:2) {
for(i in 1:4) {
for(i in 1:4) {
beep(7)
Sys.sleep(0.25)
beep()
Sys.sleep(0.22)
}
beep(2)
}
beep(11)
}
beep(4)
}
song()
You can jam out to it.
How about using Windows SpeechSynthesizer?
message <- "job done!"
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
paste0("$speak.Speak('", message, "');\"")
))
This may by nicely used in iterating operations and read something like "First job done", "Second job done" etc.:
say_something <- function(message) {
message <- paste0("$speak.Speak('", message, "');\"")
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
message
))
}
operations <- c("1st.", "2nd.", "3rd.")
lapply(operations, function(x) say_something(message=paste(x, "job done")))
*Note, that this uses system defaul language settings. The example is based on english lector, it can be changed using SelectVoice method. To check available lectors use:
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
"$speak.GetInstalledVoices().VoiceInfo")
)
That gives:
Gender : Female
Age : Adult
Name : Microsoft Paulina Desktop
Culture : pl-PL
Id : TTS_MS_PL-PL_PAULINA_11.0
Description : Microsoft Paulina Desktop - Polish
SupportedAudioFormats : {}
AdditionalInfo : {[Age, Adult], [Gender, Female], [Language, 415], [Name, Microsoft Paulina Desktop]...}
Gender : Male
Age : Adult
Name : Microsoft David Desktop
Culture : en-US
Id : TTS_MS_EN-US_DAVID_11.0
Description : Microsoft David Desktop - English (United States)
SupportedAudioFormats : {}
AdditionalInfo : {[Age, Adult], [Gender, Male], [Language, 409], [Name, Microsoft David Desktop]...}
Finally a function to select the lector by his "name" like "David", "Paulina" or "Hazel":
say_something <- function(message , voice) {
voice <- paste0("\"$speak.SelectVoice('Microsoft ", voice, " Desktop');" )
message <- paste0("$speak.Speak('", message, "');\"")
system2(command = "PowerShell",
args = c("-Command",
"\"Add-Type -AssemblyName System.Speech;",
"$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer;",
voice,
message
))
}
operations <- c("1st.", "2nd.", "3rd.")
lapply(operations, function(x) say_something(message=paste(x, "job done"), voice="David"))
Dason's answer is great, obviously, because it will work on basically any Windows machine without requiring anything except R itself.
But one thing I have been wondering is how to make these functions actually beep after a code is run.
If you do something like this:
beepR <- function(x, n = 3){
for(i in seq(n)){
system("rundll32 user32.dll,MessageBeep -1")
Sys.sleep(.5)
}
return(x)
}
You can just pipe anything to it and it will return whatever you piped, so you can do like. See the example below.
fa <- psych::fa(x, 1) |> beepR()
I'm using here the native pipe |> that was introduced in R 4.1, but you can use the %>% pipe from the maggitr package if you like; they work the exact same way. Anyway, that will beep as soon as the analysis ends, and the variable fa will contain the results of the factor analysis.
Of course, here I used the beep function that Dason provided you, but you could just as easily add anything where I indicated below.
beepR <- function(x){
# your code here #
return(x)
}
If you wish to add that function every time RStudio opens, refer to RStudio's Managing R with .Rprofile, .Renviron, Rprofile.site, Renviron.site, rsession.conf, and repos.conf to learn how to use a .Rprofile file.
You can use notify-send command:
system("notify-send \"R script finished running\"")
Because of these many ideas, I have created a solution without Internet access, because I work with a VPN client with Windows. So it plays a typical Windows sound, which is usually on any Windows operating system.
#Function with loop, press Esc to stopp
alarm2 <- function(){
while(TRUE){
system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
Sys.sleep(1)
}
}
Function without loop
alarm3 <- function(){
system("cmd.exe",input="C:/Windows/WinSxS/amd64_microsoft-windows-shell-sounds_31bf3856ad364e35_10.0.17134.1_none_fc93088a1eb3fd11/tada.wav")
Sys.sleep(1)
}
The following code produces a beep and does not depend on a .mp3 or .wav file:
switch(Sys.info()[['sysname']],
Linux = {
system('play -n synth 0.1 tri 1000.0')}
)
Combining some ideas on the thread, I implement this:
options(error = function() {
if (interactive()) {
# require("beepr"); beep(10)
system("mplayer /usr/share/sounds/freedesktop/stereo/dialog-warning.oga ")
system("notify-send -u normal 'R session' 'An error occured!'")
}
})
I regularly use stop() on interactive session like Rstudio, on scripts I am working and want to re-run to a point. This way I can switch to another desktop while waiting. I may test it to '.Rprofile'

Resources