Skip to content

Instantly share code, notes, and snippets.

@Brunas
Last active June 9, 2020 07:28
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Brunas/124c8ef19f67f4ebcfff to your computer and use it in GitHub Desktop.
Save Brunas/124c8ef19f67f4ebcfff to your computer and use it in GitHub Desktop.
Slide show widget

Description

This is Dashing widget to include slide show on your dashboard or one of its pages.

##Usage

Make sure to install RMagick gem to support image resizing. The widget also needs my slightly improved standard image widget. Put the slide_show.rb file in your /jobs folder and slide_show_settings.json to /assets/config/.

Make sure directory /assets/config and /assets/images/slide_show are accessible by Dashing user.

To include the widget in a dashboard, add the following snippet to the dashboard layout file:

<li data-row="1" data-col="1" data-sizex="4" data-sizey="2">
  <div data-id="SlideShow" data-view="Image" data-width="100%"></div>
</li>

There are 2 scheduler jobs used: First one gets randomized list of image files with pattern from source directory, resizes them to needed size and puts them to /assets/images/slide_show/<widget name>. It is executed at 5:00 and 18:00. Second randomly loops every 30 seconds through the files in /assets/images/slide_show/<widget name> and sends event with random file URL

##Settings

Mount your images directory to any directory on your server to be accessible by Dashing user. Amend /assets/config/slide_show_settings.json to have parameters specified.

There is no need to restart service if job is already running and settings file is amended.

require 'net/http'
require 'rmagick'
class SlideShow
SETTINGS_FILE = "assets/config/slide_show_settings.json"
CURRENT_DIR = Dir.pwd
DEBUG = 0
def debug
DEBUG
end
# function to validate json
def valid_json? (json)
JSON.parse(json)
return true
rescue JSON::ParserError
return false
end
def get_settings
str = IO.read(SETTINGS_FILE)
return [] if not str or str.empty? or not valid_json?(str)
JSON.parse(str)
end
def get_dir_file_list(directory, pattern, exceptionDirs = [])
# Take directory files using pattern and delete exception subdirectories
Dir[directory+'/'+pattern].delete_if { |x| exceptionDirs.any? { |d| x =~ /#{d}/ } }
end
def resize_images(files, widget, directory, maxImageSize, quality = 50, fileCount = 100)
return if not files or files.length == 0
files[0..fileCount].each do |f|
newFile = f.sub directory, CURRENT_DIR+"/assets/images/slide_show/#{widget}"
next if File.exists?(newFile)
FileUtils.mkdir_p File.dirname(newFile)
img = Magick::Image.read(f).first
newImg = img.change_geometry(maxImageSize[0].to_s+'x'+maxImageSize[1].to_s) { |cols, rows, i|
newImg = i.resize(cols, rows)
newImg.write(newFile){ self.quality = quality }
}
end
end
def get_file_list(widget, settings)
widgetFileDir = CURRENT_DIR+"/assets/images/slide_show/#{widget}"
files = (get_dir_file_list(widgetFileDir, settings['pattern']).shuffle)[0..30]
return files if files and files.length > 0
# no files yet - get new list from source location and resize it
# take just 15 files not to freeze everything
resize_images(
get_dir_file_list(settings['directory'], settings['pattern'], settings['subDirectoryExceptions']).shuffle,
widget,
settings['directory'],
settings['maxImageSize'],
settings['quality'],
15)
# return 10 files not to make everything last too long
(get_dir_file_list(widgetFileDir, settings['pattern']).shuffle)[0..10]
end
def make_web_friendly(widget, directory, file)
file.sub directory, "/assets/slide_show/#{widget}" if file
end
end
@SS = SlideShow.new()
SCHEDULER.cron '* 5/18 * * *' do |job|
settings = @SS.get_settings
settings.each do |widget, project|
puts DateTime.now.to_s+" Resizing images for #{widget}, #{project.to_s}"
@SS.resize_images(
@SS.get_dir_file_list(project['directory'], project['pattern'], project['subDirectoryExceptions']).shuffle,
widget,
project['directory'],
project['maxImageSize'],
project['quality'])
end
end
@files = nil
SCHEDULER.every '30s', :first_in => 0 do |job|
settings = @SS.get_settings
settings.each do |widget, project|
@files = { widget => @SS.get_file_list(widget, project) } if not @files or not @files[widget] or @files[widget].length == 0
file = @files[widget][rand(@files[widget].length)]
puts DateTime.now.to_s+" Working with #{widget}, #{project.to_s}, #{file}" if @SS.debug > 0
img = Magick::Image::read(file).first
send_event(widget, {
image: @SS.make_web_friendly(widget, Dir.pwd+"/assets/images/slide_show/#{widget}", file),
image_width: img.columns,
image_height: img.rows
})
end
end
{"SlideShow":{"directory":"/mnt/images/Public TV","pattern":"**/*.{jpg,JPG,gif,GIF,png,PNG}","maxImageSize":[1920,1080],"quality":50,"subDirectoryExceptions":["very bad party","personal employee pictures","something very private"]}}
@ilikenwf
Copy link

Any ideas why this is happening? Seems to be the call at https://gist.github.com/Brunas/124c8ef19f67f4ebcfff#file-slide_show-rb-L76

scheduler caught exception:
undefined method `sub' for nil:NilClass
/opt/dashing/depts/jobs/slide_show.rb:51:in `make_web_friendly'
/opt/dashing/depts/jobs/slide_show.rb:76:in `block (2 levels) in <top (required)>'
/opt/dashing/depts/jobs/slide_show.rb:71:in `each'
/opt/dashing/depts/jobs/slide_show.rb:71:in `block in <top (required)>'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:230:in `call'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:230:in `trigger_block'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/jobs.rb:204:in `block in trigger'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:430:in `call'
/var/lib/gems/1.9.1/gems/rufus-scheduler-2.0.24/lib/rufus/sc/scheduler.rb:430:in `block in trigger_job'

@Brunas
Copy link
Author

Brunas commented Sep 7, 2015

@ilikenwf,

Thanks for your comment. The error occurs when there are no images taken from source directory and resized. Fixed that by adding retrieval/resizing in get_file_list function.

Also, added quality parameter to make slide show images not too big for some browsers like one in Sony smart TV.

@slize
Copy link

slize commented Sep 20, 2015

Hey Brunas,

I faced a decent problem while trying to use your slideshow. Actually, the images did not slide through. Hence, I did some checking. You missed the array-operator in three lines, which causes the ... something.length to result in the size of "1". On the basis of this, the rand() function is called. It will also return "0". Therefore, the first image in the line will always be chosen. There won't be any slideshow.

Here are the lines of "slide_show.rb" you need to adopt:

line 88:
original: file = @files[widget][rand(@files.length)]
new: file = @files[widget][rand(@files[widget].length)]

line 92:
original: .... Dir.pwd+"/assets/images/slide_show/#{widget}", @files[widget][rand(@files.length)]),
new: .... Dir.pwd+"/assets/images/slide_show/#{widget}", file),

Apart from that, thanks for the widget. It really helps me a lot :) 👍

@Brunas
Copy link
Author

Brunas commented Sep 24, 2015

@slize,

Thanks for nice words and especially for your excellent QA work! Yesterday I started wondering myself, why those pictures are always the same ;). Code updated.

@Hartigon
Copy link

Hartigon commented Feb 7, 2016

Hi , thanks for your nice gadget but it generates a script leak memory for each new pictures.

@tkcharlie
Copy link

Hi Brunas,
I've been trying to get this to work but just can't get there,
can you give me a clue as to why I'd get this error when starting dashing

/Users/tkcharlie/ce_dashboard/jobs/slide_show.rb:90:in read' /Users/tkcharlie/ce_dashboard/jobs/slide_show.rb:90:inblock (2 levels) in <top (required)>'
/Users/tkcharlie/ce_dashboard/jobs/slide_show.rb:86:in each' /Users/tkcharlie/ce_dashboard/jobs/slide_show.rb:86:inblock in <top (required)>'

@stigert
Copy link

stigert commented Aug 25, 2018

I've been trying to get this to work for days, but it's not happening. It keeps getting RMagick error messages. Is it possible to get this widget without the resizing part?

@GuinnessStoutly
Copy link

Hi Brunas, Thanks for the widget. It's working, however there is still a problem with image duplications. Another question, how to stop the shuffling? Thanks.

@mandelbrotmedia
Copy link

Hi,

thanks for that great widget!
Is there a way to stop the randomized slideshow? Would be nice to display the images in a fixed order.

thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment