Last active
September 6, 2017 03:25
-
-
Save savetheclocktower/a7b0923c89dc43d8c1561cf60233437c to your computer and use it in GitHub Desktop.
Scripts for Nostalgia-Tron series, part 10
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'pathname' | |
begin | |
require 'inifile' | |
require 'nokogiri' | |
rescue LoadError => e | |
puts "This script requires nokogiri and inifile:" | |
puts " $ gem install nokogiri inifile" | |
exit 1 | |
end | |
CATVER_PATH = Pathname.new(ARGV[0] || '/home/pi/catver.ini') | |
CATVER = IniFile::load(CATVER_PATH) | |
CATEGORIES = CATVER['Category'] | |
GAMELIST_DIR = Pathname.new('/home/pi/.emulationstation/gamelists/arcade') | |
GAMELIST_BACKUP_PATH = GAMELIST_DIR.join("gamelist.xml.#{Time.now.to_i}.bak") | |
GAMELIST_CURRENT_PATH = GAMELIST_DIR.join('gamelist.xml') | |
# Backup current gamelist.xml. | |
GAMELIST_BACKUP_PATH.open('w') do |f| | |
f.write(GAMELIST_CURRENT_PATH.read) | |
end | |
GAMELIST_XML = Nokogiri::XML(GAMELIST_CURRENT_PATH.read) | |
# Traverse the gamelist. | |
GAMELIST_XML.css('gameList > game').each do |g| | |
path_node = g.at_css('path') | |
basename = Pathname.new(path_node).basename('.zip').to_s | |
genre_node = g.at_css('genre') | |
current_genre = g.at_css('genre').content rescue "(none)" | |
new_genre = CATEGORIES[basename] | |
puts "GAME: #{basename}" | |
# Do we need to do anything for this game? | |
if new_genre == current_genre | |
puts " genre is up to date" | |
next | |
end | |
# Do we have a genre to give it? | |
unless new_genre && !new_genre.empty? | |
puts " no genre found in INI" | |
next | |
end | |
# This game has a genre. Write it to the XML. | |
# Create the node if it didn't exist before. | |
if !genre_node | |
genre_node = Nokogiri::XML::Node.new('genre', GAMELIST_XML) | |
g.add_child(genre_node) | |
end | |
genre_node.content = new_genre | |
puts " Current genre: #{current_genre}" | |
puts " New genre: #{new_genre}" | |
end | |
# Write out the XML to a | |
GAMELIST_CURRENT_PATH.open('w') do |f| | |
GAMELIST_XML.write_xml_to(f) | |
end | |
puts "...done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'pathname' | |
begin | |
require 'nokogiri' | |
rescue LoadError => e | |
puts "This script requires nokogiri:" | |
puts " $ gem install nokogiri" | |
exit 1 | |
end | |
SYSTEM = 'arcade' | |
def screenshot_path_for_game(system, game) | |
Pathname.new("/home/pi/screens/#{system}/#{game}.png") | |
end | |
GAMELIST_DIR = Pathname.new("/home/pi/.emulationstation/gamelists/#{SYSTEM}") | |
GAMELIST_BACKUP_PATH = GAMELIST_DIR.join("gamelist.xml.#{Time.now.to_i}.bak") | |
GAMELIST_CURRENT_PATH = GAMELIST_DIR.join('gamelist.xml') | |
# Backup current gamelist.xml. | |
GAMELIST_BACKUP_PATH.open('w') do |f| | |
f.write(GAMELIST_CURRENT_PATH.read) | |
end | |
GAMELIST_XML = Nokogiri::XML(GAMELIST_CURRENT_PATH.read) | |
# Traverse the gamelist. | |
GAMELIST_XML.css('gameList > game').each do |g| | |
path_node = g.at_css('path') | |
basename = Pathname.new(path_node).basename('.zip').to_s | |
art_node = g.at_css('image') | |
current_art = art_node.content rescue nil | |
new_art = screenshot_path_for_game(SYSTEM, basename) | |
puts "GAME: #{basename}" | |
if new_art == current_art | |
puts " no change needed" | |
next | |
end | |
# Does the screenshot exist? | |
if new_art.file? | |
# Update the artwork's modified time so we can more easily tell which | |
# artwork files we aren't using later on. | |
path.touch | |
else | |
puts " could not find screenshot at #{new_art}" | |
next | |
end | |
# Create the `image` element if needed. | |
if !art_node | |
art_node = Nokogiri::XML::Node.new('image', GAMELIST_XML) | |
g.add_child(art_node) | |
end | |
art_node.content = new_art.to_s | |
puts " changed art path to #{new_art}" | |
end | |
# Write out the XML. | |
GAMELIST_CURRENT_PATH.open('w') do |f| | |
GAMELIST_XML.write_xml_to(f) | |
end | |
puts "...done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'nokogiri' | |
require 'optparse' | |
require 'pathname' | |
SYSTEMS = ARGV | |
NAME_MAP = { | |
'arcade' => 'Arcade Games', | |
'daphne' => 'Laserdisc Games' | |
} | |
GAMELIST_ROOT = Pathname.new('/home/pi/.emulationstation/gamelists/') | |
output = [] | |
$options = { | |
require: ['name', 'genre', 'developer'] | |
} | |
opts = OptionParser.new do |o| | |
o.banner = "Usage: make-game-list [options] [systems]" | |
o.separator "" | |
o.on('-r', '--require=FOO,BAR', "Skip games that lack any of these fields (default: name, genre, developer)") do |value| | |
$options[:require] = value.split(',') | |
end | |
end | |
begin | |
opts.parse! | |
rescue OptionParser::InvalidArgument => e | |
STDERR.puts("#{e.message}\n\n") | |
STDERR.puts(opts) | |
exit 1 | |
end | |
def fails_requirements?(meta) | |
$options[:require].any? { |k| meta[k.to_sym].nil? } | |
end | |
def html_for_game(game) | |
id = File.basename( game.at_css('path').content, '.zip' ) | |
name = game.at_css('name').content | |
date = game.at_css('releasedate').content rescue nil | |
year = date.nil? ? nil : date[0..3] | |
genre = game.at_css('genre').content rescue nil | |
developer = game.at_css('developer').content rescue nil | |
description = game.at_css('desc').content rescue nil | |
return '' if fails_requirements?({ | |
name: name, | |
year: year, | |
genre: genre, | |
developer: developer | |
}) | |
%Q[ | |
<tr> | |
<td data-game="#{id}" data-value="#{name}"> | |
<a href="#" class="game-link" data-toggle="popover" data-title="#{name}">#{name}</a> | |
<div class="game-description">#{description}</div> | |
</td> | |
<td>#{year || '?'}</td> | |
<td>#{genre || '?'}</td> | |
<td>#{developer || '?'}</td> | |
</tr> | |
] | |
end | |
def html_for_system(path) | |
xml = Nokogiri::XML( path.open ) | |
system = path.dirname.basename.to_s | |
games = xml.css('gameList > game') | |
%Q[ | |
<h2 class="system-title">#{NAME_MAP[system] || system}</h2> | |
<table class="table table-bordered table-collapsed table-striped sortable"> | |
<thead> | |
<tr> | |
<th data-defaultsort="asc">Game</th> | |
<th>Year</th> | |
<th>Genre</th> | |
<th>Manufacturer</th> | |
</tr> | |
</thead> | |
<tbody> | |
#{games.map(&method(:html_for_game)).join("\n")} | |
</tbody> | |
</table> | |
] | |
end | |
SYSTEMS.each do |system| | |
path = GAMELIST_ROOT.join(system, 'gamelist.xml') | |
output << html_for_system(path) | |
end | |
output = output.join("\n") | |
content = <<-HTML | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Nostalgia-Tron Games List</title> | |
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=News+Cycle:700|Oxygen"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> | |
<style type="text/css" media="screen"> | |
h1, h2, h3:not(.popover-title) { | |
font-family: 'News Cycle', sans-serif; | |
} | |
h3.popover-title { | |
font-weight: bold; | |
} | |
h2.system-title { | |
margin: 2.5rem 0 2rem; | |
} | |
body { | |
font-family: 'Oxygen', sans-serif; | |
padding-top: 3rem; | |
padding-bottom: 3rem; | |
} | |
.popover { | |
font-family: 'Oxygen', sans-serif; | |
} | |
.game-description { | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
#{output} | |
</div> | |
<script type="text/javascript"> | |
$(function () { | |
// When we open a popover, hide any others that may be open. | |
$('a.game-link').click(function (e) { | |
e.preventDefault(); | |
var $others = $('[data-toggle="popover"]').not(e.target); | |
$others.popover('hide'); | |
$(e.target).popover('toggle'); | |
}); | |
// Make popovers wider. | |
$('a.game-link').on('show.bs.popover', function () { | |
$(this).data("bs.popover").tip().css("max-width", "600px"); | |
}); | |
// Hide a popover whenever someone clicks off. | |
$('body').click(function (e) { | |
var $anchor = $(e.target).closest('a.game-link'); | |
var $popover = $(e.target).closest('.popover'); | |
if ($anchor.length > 0 || $popover.length > 0) return; | |
$('[data-toggle="popover"]').popover('hide'); | |
}); | |
$('[data-toggle="popover"]').popover({ | |
html: true, | |
trigger: 'manual', | |
container: 'body', | |
placement: 'auto bottom', | |
content: function () { | |
var text = $(this).closest('td').find('.game-description').text(); | |
text = "<p>" + text + "</p>"; | |
text = text.replace(/\\n\\s*\\n/g, "</p>\\n<p>"); | |
return text; | |
} | |
}); | |
}); | |
</script> | |
</body> | |
</html> | |
HTML | |
puts content |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
print_help_and_exit() { | |
echo "Usage: quit-emulationstation [options]" | |
echo "" | |
echo "Exits EmulationStation gracefully (if it is running)." | |
exit 0 | |
} | |
while true ; do | |
case "$1" in | |
-h) print_help_and_exit ;; | |
*) break ;; | |
esac | |
shift | |
done | |
pid=`ps -ef | awk '/emulationstation\/emulationstation$/ {print $2}'` | |
if [ -z $pid ]; then | |
echo "EmulationStation doesn't appear to be running." | |
exit 1 | |
else | |
printf "Quitting EmulationStation..." | |
kill $pid && echo -e "done.\n" | |
exit 0 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment