commit
052944aa01
29 changed files with 2588 additions and 0 deletions
Unified View
Diff Options
-
2.gitignore
-
85config.js
-
25index.js
-
1328package-lock.json
-
32package.json
-
129server/booth.js
-
56server/index.js
-
5server/public/css/bootstrap.min.css
-
163server/public/css/cover.css
-
8server/public/css/style.css
-
10server/public/css/view.css
-
7server/public/js/bootstrap.min.js
-
4server/public/js/jquery-1.11.2.min.js
-
3server/public/js/socket.io-1.3.4.js
-
8server/public/js/socket.io.js
-
1server/public/js/socket.io.js.map
-
BINserver/public/rsc/common/294.GIF
-
BINserver/public/rsc/footer/cloclo.jpg
-
BINserver/public/rsc/footer/m-30ansv2.jpg
-
BINserver/public/rsc/footer/m-cloclo.jpg
-
BINserver/public/rsc/footer/m-clotilde60.jpg
-
BINserver/public/rsc/template/default.jpg
-
BINserver/public/waiting.gif
-
BINserver/public/waiting2.gif
-
172server/views/index.ejs
-
226server/views/scope.ejs
-
62server/views/test.ejs
-
107tools/tools-gphoto2.js
-
155tools/tools-photobooth.js
@ -0,0 +1,2 @@ |
|||||
|
*node_modules* |
||||
|
output/ |
||||
@ -0,0 +1,85 @@ |
|||||
|
const os = require('os') |
||||
|
const path = require('path') |
||||
|
const mkdirp = require('mkdirp') |
||||
|
|
||||
|
const config = { |
||||
|
background: '#ffffff', |
||||
|
margins: 0.005, |
||||
|
style: 'default', |
||||
|
nbPicture: 4, |
||||
|
cropSize: { |
||||
|
width: 900, |
||||
|
height: 1200 |
||||
|
}, |
||||
|
pictNames: [], |
||||
|
layout: [], |
||||
|
booths: {}, |
||||
|
paths: { |
||||
|
final: '', |
||||
|
template: '', |
||||
|
prebuilt: '', |
||||
|
original: '', |
||||
|
toprint: '' |
||||
|
}, |
||||
|
footer: 'm-30ansv2.jpg' |
||||
|
} |
||||
|
|
||||
|
config.server = { |
||||
|
ipAddress: getIpAddress(), |
||||
|
port: 3111 |
||||
|
} |
||||
|
|
||||
|
config.killZone = { |
||||
|
top: 2, |
||||
|
bottom: 2, |
||||
|
left: 25, |
||||
|
right: 25 |
||||
|
} |
||||
|
|
||||
|
// Init PATH
|
||||
|
config.paths.template = path.resolve(__dirname, './server/public/rsc/template') |
||||
|
config.footer = path.resolve(__dirname, './server/public/rsc/footer', config.footer) |
||||
|
config.paths.final = path.resolve(__dirname, './output/final') |
||||
|
config.paths.final_ld = path.resolve(__dirname, './output/final_ld') |
||||
|
config.paths.prebuilt = path.resolve(__dirname, './output/cache') |
||||
|
config.paths.original = path.resolve(__dirname, './output/original') |
||||
|
config.paths.toprint = path.resolve(__dirname, './output/toprint') |
||||
|
|
||||
|
mkdirp.sync(config.paths.final) |
||||
|
mkdirp.sync(config.paths.final_ld) |
||||
|
mkdirp.sync(config.paths.prebuilt) |
||||
|
mkdirp.sync(config.paths.original) |
||||
|
mkdirp.sync(config.paths.toprint) |
||||
|
|
||||
|
// Init pinctures names
|
||||
|
for (let index = 0; index < config.nbPicture; index++) { |
||||
|
config.pictNames.push('pict_' + index + '.jpg') |
||||
|
} |
||||
|
|
||||
|
module.exports = config |
||||
|
|
||||
|
function getIpAddress () { |
||||
|
let ipAddress = 'localhost' |
||||
|
// Get local server ip address
|
||||
|
let ifaces = os.networkInterfaces() |
||||
|
Object.keys(ifaces).forEach(function (ifname) { |
||||
|
let alias = 0 |
||||
|
|
||||
|
ifaces[ifname].forEach(function (iface) { |
||||
|
// skip over internal (i.e. 127.0.0.1) and non-ipv4 addresses
|
||||
|
if (iface.family !== 'IPv4' || iface.internal !== false) return |
||||
|
if (/wlan/i.test(ifname)) ipAddress = iface.address |
||||
|
|
||||
|
if (alias >= 1) { |
||||
|
// this single interface has multiple ipv4 addresses
|
||||
|
// console.log(`[-] network: ${ifname} : ${alias} - ${iface.address}`)
|
||||
|
} else { |
||||
|
// this interface has only one ipv4 adress
|
||||
|
// console.log(`[-] network: ${ifname} - ${iface.address}`)
|
||||
|
// console.log(ifname, iface.address)
|
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
return ipAddress |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
const gphoto2 = require('./tools/tools-gphoto2') |
||||
|
const server = require('./server') |
||||
|
|
||||
|
// gphoto2.init(function (pErr) {
|
||||
|
// console.log('DONE')
|
||||
|
let app = server() |
||||
|
// })
|
||||
|
|
||||
|
// // Initialize the library
|
||||
|
// BOB_var_gamepad.init()
|
||||
|
// // List the state of all currently attached devices
|
||||
|
// for (var i = 0, l = BOB_var_gamepad.numDevices(); i < l; i++) {
|
||||
|
// console.log(i, BOB_var_gamepad.deviceAtIndex(i));
|
||||
|
// }
|
||||
|
// // Create a game loop and poll for events
|
||||
|
// setInterval(BOB_var_gamepad.processEvents, 16);
|
||||
|
// // Scan for new gamepads as a slower rate
|
||||
|
// setInterval(BOB_var_gamepad.detectDevices, 500);
|
||||
|
// // Listen for button down events on all gamepads
|
||||
|
// BOB_var_gamepad.on("down", function (pId, pNum) {
|
||||
|
// BOB_cfg_config.io.emit('boothClick', {
|
||||
|
// id : pId,
|
||||
|
// num : pNum
|
||||
|
// });
|
||||
|
// })
|
||||
1328
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,32 @@ |
|||||
|
{ |
||||
|
"name": "bobinoscope-v2", |
||||
|
"version": "1.0.0", |
||||
|
"description": "Code for bobinoscope", |
||||
|
"main": "index.js", |
||||
|
"scripts": { |
||||
|
"test": "echo \"Error: no test specified\" && exit 1" |
||||
|
}, |
||||
|
"author": "P.BARRY", |
||||
|
"license": "ISC", |
||||
|
"dependencies": { |
||||
|
"async": "^2.6.1", |
||||
|
"body-parser": "^1.18.3", |
||||
|
"colors": "^1.3.1", |
||||
|
"cookie-parser": "^1.4.3", |
||||
|
"ejs": "^2.6.1", |
||||
|
"express": "^4.16.3", |
||||
|
"fs-extra": "^7.0.0", |
||||
|
"gamepad": "^1.6.0", |
||||
|
"gm": "^1.23.1", |
||||
|
"mkdirp": "^0.5.1", |
||||
|
"morgan": "^1.9.0", |
||||
|
"opn": "^5.3.0", |
||||
|
"socket.io": "^2.1.1", |
||||
|
"split-lines": "^2.0.0" |
||||
|
}, |
||||
|
"nodemonConfig": { |
||||
|
"ignore": [ |
||||
|
"webapp/*" |
||||
|
] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,129 @@ |
|||||
|
const express = require('express') |
||||
|
const router = express.Router() |
||||
|
const fs = require('fs-extra') |
||||
|
const gm = require('gm').subClass({ imageMagick: true }) |
||||
|
const path = require('path') |
||||
|
const gamepad = require('gamepad') |
||||
|
require('colors') |
||||
|
|
||||
|
const gphoto2 = require('../tools/tools-gphoto2') |
||||
|
const booth = require('../tools/tools-photobooth') |
||||
|
|
||||
|
const CFG = require('../config') |
||||
|
const CTX = { |
||||
|
__io: null, |
||||
|
io: function () { |
||||
|
return CTX.__io |
||||
|
}, |
||||
|
inProgress: 0, |
||||
|
testPath: '/tmp/bobinoscope-test.jpg' |
||||
|
} |
||||
|
|
||||
|
booth.init() |
||||
|
setGamepad() |
||||
|
|
||||
|
// router.use(function (req, res, next) {
|
||||
|
// console.log(req.url)
|
||||
|
// next()
|
||||
|
// })
|
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
// DSLR
|
||||
|
router.get('/dslr/takepicture/:boothId/:pictId', function (req, res, next) { |
||||
|
// return res.json({})
|
||||
|
gphoto2.takeOnePicture(req.params.boothId, req.params.pictId, function (pErr) { |
||||
|
res.json({ error: pErr, data: null }) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
router.get('/build/:boothId', function (req, res, next) { |
||||
|
console.log('Building') |
||||
|
// res.json({ok: 1})
|
||||
|
CTX.inProgress += 1 |
||||
|
CTX.io().emit('boothState') |
||||
|
booth.buildBooth(req.params.boothId, function (pErr) { |
||||
|
CTX.io().emit('boothState') |
||||
|
CTX.inProgress -= 1 |
||||
|
res.json({ error: pErr, data: null, boothId: req.params.boothId }) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
router.use('/build/result/low', express.static(CFG.paths.final_ld)) |
||||
|
router.use('/build/result', express.static(CFG.paths.final)) |
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
// PRINTER
|
||||
|
router.get('/list/:from', function (req, res, next) { |
||||
|
booth.getBoothList(req.params.from, function (pErr, pList) { |
||||
|
res.json({error: pErr, booths: pList, inProgress: CTX.inProgress}) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
router.get('/toprint', function (req, res, next) { |
||||
|
var todoPath = path.join(CFG.paths.toprint) |
||||
|
fs.readdir(todoPath, function (pErr, pList) { |
||||
|
res.json({error: pErr, todos: pList}) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
router.get('/print/:pictId', function (req, res, next) { |
||||
|
let srcPath = path.join(CFG.paths.final, req.params.pictId) |
||||
|
let dstPath = path.join(CFG.paths.toprint, req.params.pictId) |
||||
|
fs.copy(srcPath, dstPath, function (pErr) { |
||||
|
res.json({error: pErr}) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
// ////////////////////////////////////////////////////////////////////////////
|
||||
|
// TEST
|
||||
|
|
||||
|
router.get('/test/takepicture', function (req, res, next) { |
||||
|
let tmpPict = '/tmp/bobinoscope-test.tmp.jpg' |
||||
|
gphoto2.__takeOnePicture(tmpPict, function (pErr) { |
||||
|
if (pErr) return res.status(500).send(pErr) |
||||
|
gm(tmpPict) |
||||
|
.autoOrient() |
||||
|
.gravity('Center') |
||||
|
.write(CTX.testPath, function (pErr) { |
||||
|
if (pErr) console.log('Failed to resize picture', pErr) |
||||
|
res.json({ok: 1}) |
||||
|
}) |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
router.get('/test/takepicture/result', function (req, res, next) { |
||||
|
res.sendFile('/tmp/bobinoscope-test.jpg') |
||||
|
}) |
||||
|
|
||||
|
router.setSocketIo = function (pIo) { |
||||
|
CTX.__io = pIo |
||||
|
} |
||||
|
|
||||
|
function setGamepad () { |
||||
|
// Initialize the library
|
||||
|
gamepad.init() |
||||
|
// List the state of all currently attached devices
|
||||
|
// for (var i = 0, l = gamepad.numDevices(); i < l; i++) {
|
||||
|
// console.log(i, gamepad.deviceAtIndex(i))
|
||||
|
// }
|
||||
|
|
||||
|
if (!gamepad.numDevices()) { |
||||
|
console.log('[!] No gamepad found'.yellow) |
||||
|
} else { |
||||
|
console.log(`[!] ${gamepad.numDevices()} gamepad(s) found`.bgBlue) |
||||
|
// Create a game loop and poll for events
|
||||
|
setInterval(gamepad.processEvents, 16) |
||||
|
// Scan for new gamepads as a slower rate
|
||||
|
setInterval(gamepad.detectDevices, 500) |
||||
|
// Listen for button down events on all gamepads
|
||||
|
gamepad.on('down', function (pId, pNum) { |
||||
|
console.log(`[!] gamepad action received | ${pId}:${pNum}`.bgBlue) |
||||
|
CTX.io().emit('boothClick', { |
||||
|
id: pId, |
||||
|
num: pNum |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = router |
||||
@ -0,0 +1,56 @@ |
|||||
|
const path = require('path') |
||||
|
const express = require('express') |
||||
|
const app = express() |
||||
|
const logger = require('morgan') |
||||
|
const cookieParser = require('cookie-parser') |
||||
|
const bodyParser = require('body-parser') |
||||
|
|
||||
|
const booth = require('./booth') |
||||
|
|
||||
|
const CFG = require('../config') |
||||
|
const PKG = require('../package') |
||||
|
|
||||
|
// view engine setup
|
||||
|
app.set('views', path.join(__dirname, 'views')) |
||||
|
app.set('view engine', 'ejs') |
||||
|
app.use(logger('dev')) |
||||
|
app.use(bodyParser.json()) |
||||
|
app.use(bodyParser.urlencoded({ extended: false })) |
||||
|
app.use(cookieParser()) |
||||
|
app.use(express.static(path.join(__dirname, 'public'))) |
||||
|
|
||||
|
app.use('/booth', booth) |
||||
|
|
||||
|
app.get('/', (req, res) => { |
||||
|
res.render('index', { |
||||
|
serverIpAddress: CFG.server.ipAddress, |
||||
|
serverPort: CFG.server.port |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
app.get('/test', (req, res) => { |
||||
|
res.render('test', { |
||||
|
serverIpAddress: CFG.server.ipAddress, |
||||
|
serverPort: CFG.server.port |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
app.get('/bobinoscope', (req, res) => { |
||||
|
res.render('scope', { |
||||
|
serverIpAddress: CFG.server.ipAddress, |
||||
|
serverPort: CFG.server.port, |
||||
|
killZone: CFG.killZone, |
||||
|
renderingTime: 5000 |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
module.exports = function () { |
||||
|
let server = app.listen(CFG.server.port, () => { |
||||
|
console.log(`[-] Server running on: ${CFG.server.ipAddress}:${CFG.server.port}`) |
||||
|
}) |
||||
|
// Socket Io
|
||||
|
app.locals.io = require('socket.io')(server) |
||||
|
booth.setSocketIo(app.locals.io) |
||||
|
|
||||
|
return app |
||||
|
} |
||||
5
server/public/css/bootstrap.min.css
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,163 @@ |
|||||
|
/* |
||||
|
* Globals |
||||
|
*/ |
||||
|
|
||||
|
/* Links */ |
||||
|
a, |
||||
|
a:focus, |
||||
|
a:hover { |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
/* Custom default button */ |
||||
|
.btn-default, |
||||
|
.btn-default:hover, |
||||
|
.btn-default:focus { |
||||
|
color: #333; |
||||
|
text-shadow: none; /* Prevent inheritence from `body` */ |
||||
|
background-color: #fff; |
||||
|
border: 1px solid #fff; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Base structure |
||||
|
*/ |
||||
|
|
||||
|
html, |
||||
|
body { |
||||
|
height: 100%; |
||||
|
background-color: #333; |
||||
|
} |
||||
|
body { |
||||
|
color: #fff; |
||||
|
text-align: center; |
||||
|
text-shadow: 0 1px 3px rgba(0,0,0,.5); |
||||
|
} |
||||
|
|
||||
|
/* Extra markup and styles for table-esque vertical and horizontal centering */ |
||||
|
.site-wrapper { |
||||
|
display: table; |
||||
|
width: 100%; |
||||
|
height: 100%; /* For at least Firefox */ |
||||
|
min-height: 100%; |
||||
|
-webkit-box-shadow: inset 0 0 100px rgba(0,0,0,.5); |
||||
|
box-shadow: inset 0 0 100px rgba(0,0,0,.5); |
||||
|
} |
||||
|
.site-wrapper-inner { |
||||
|
display: table-cell; |
||||
|
vertical-align: top; |
||||
|
} |
||||
|
.cover-container { |
||||
|
margin-right: auto; |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
/* Padding for spacing */ |
||||
|
.inner { |
||||
|
padding: 30px; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Header |
||||
|
*/ |
||||
|
.masthead-brand { |
||||
|
margin-top: 10px; |
||||
|
margin-bottom: 10px; |
||||
|
} |
||||
|
|
||||
|
.masthead-nav > li { |
||||
|
display: inline-block; |
||||
|
} |
||||
|
.masthead-nav > li + li { |
||||
|
margin-left: 20px; |
||||
|
} |
||||
|
.masthead-nav > li > a { |
||||
|
padding-right: 0; |
||||
|
padding-left: 0; |
||||
|
font-size: 16px; |
||||
|
font-weight: bold; |
||||
|
color: #fff; /* IE8 proofing */ |
||||
|
color: rgba(255,255,255,.75); |
||||
|
border-bottom: 2px solid transparent; |
||||
|
} |
||||
|
.masthead-nav > li > a:hover, |
||||
|
.masthead-nav > li > a:focus { |
||||
|
background-color: transparent; |
||||
|
border-bottom-color: #a9a9a9; |
||||
|
border-bottom-color: rgba(255,255,255,.25); |
||||
|
} |
||||
|
.masthead-nav > .active > a, |
||||
|
.masthead-nav > .active > a:hover, |
||||
|
.masthead-nav > .active > a:focus { |
||||
|
color: #fff; |
||||
|
border-bottom-color: #fff; |
||||
|
} |
||||
|
|
||||
|
@media (min-width: 768px) { |
||||
|
.masthead-brand { |
||||
|
float: left; |
||||
|
} |
||||
|
.masthead-nav { |
||||
|
float: right; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Cover |
||||
|
*/ |
||||
|
|
||||
|
.cover { |
||||
|
padding: 0 20px; |
||||
|
} |
||||
|
.cover .btn-lg { |
||||
|
padding: 10px 20px; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Footer |
||||
|
*/ |
||||
|
|
||||
|
.mastfoot { |
||||
|
color: #999; /* IE8 proofing */ |
||||
|
color: rgba(255,255,255,.5); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/* |
||||
|
* Affix and center |
||||
|
*/ |
||||
|
|
||||
|
@media (min-width: 768px) { |
||||
|
/* Pull out the header and footer */ |
||||
|
.masthead { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
} |
||||
|
.mastfoot { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
/* Start the vertical centering */ |
||||
|
.site-wrapper-inner { |
||||
|
vertical-align: middle; |
||||
|
} |
||||
|
/* Handle the widths */ |
||||
|
.masthead, |
||||
|
.mastfoot, |
||||
|
.cover-container { |
||||
|
width: 100%; /* Must be percentage or pixels for horizontal alignment */ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media (min-width: 992px) { |
||||
|
.masthead, |
||||
|
.mastfoot, |
||||
|
.cover-container { |
||||
|
width: 700px; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
body { |
||||
|
padding: 50px; |
||||
|
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; |
||||
|
} |
||||
|
|
||||
|
a { |
||||
|
color: #00B7FF; |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
html, |
||||
|
body { |
||||
|
height: 100%; |
||||
|
background-color: #333; |
||||
|
} |
||||
|
body { |
||||
|
color: #fff; |
||||
|
text-align: center; |
||||
|
text-shadow: 0 1px 3px rgba(0,0,0,.5); |
||||
|
} |
||||
7
server/public/js/bootstrap.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
4
server/public/js/jquery-1.11.2.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
3
server/public/js/socket.io-1.3.4.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
8
server/public/js/socket.io.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1
server/public/js/socket.io.js.map
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,172 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<title>Bobinoscope</title> |
||||
|
<!-- Latest compiled and minified CSS --> |
||||
|
<link rel="stylesheet" href="/css/view.css"/> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="idMain" style="width:400px; margin: auto"> |
||||
|
<p>Cliquez sur le <i>bobinogramme</i> qui vous intéresse<br/>pour afficher le menu</p> |
||||
|
<div id="idViewLoading"> |
||||
|
<img src='/waiting.gif'/> |
||||
|
</div> |
||||
|
<div id="idViewContainer"> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="idMenu" style="display:none"> |
||||
|
<div id="idMenu-title">Bobinoscope</div> |
||||
|
<img id="idMenu-preview" src=""/> |
||||
|
<br/> |
||||
|
<div> |
||||
|
<button id="idMenu-btnDownload">Télécharger</button> |
||||
|
<button id="idMenu-btnPrint">Imprimer</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
<!-- Latest compiled and minified JQuery --> |
||||
|
<script src="/js/jquery-1.11.2.min.js"></script> |
||||
|
<!-- Getting the Socket.IO Client --> |
||||
|
<script src="/js/socket.io.js"></script> |
||||
|
</html> |
||||
|
|
||||
|
<style type="text/css"> |
||||
|
#idMenu { |
||||
|
background: #000; |
||||
|
opacity: 1; |
||||
|
position: fixed; |
||||
|
width: 100%; |
||||
|
padding: 1em; |
||||
|
top:0; |
||||
|
left:0; |
||||
|
bottom: 0; |
||||
|
right: 0; |
||||
|
font-size: 1.2em; |
||||
|
} |
||||
|
|
||||
|
.classBoothItem { |
||||
|
margin: 5px 0 |
||||
|
} |
||||
|
|
||||
|
#idMenu button{ |
||||
|
padding: 0.5em; |
||||
|
} |
||||
|
|
||||
|
#idMenu-title { |
||||
|
padding: 0.3em; |
||||
|
font-size: 1.3em; |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
|
<script type="text/javascript"> |
||||
|
|
||||
|
var socket = io('/'); |
||||
|
socket.on('connect', function() { |
||||
|
console.log("connect") |
||||
|
}) |
||||
|
socket.on('boothState', function (data) { |
||||
|
BOB_getBooths(); |
||||
|
}) |
||||
|
|
||||
|
$(document).ready(function() { |
||||
|
BOB_getBooths(); |
||||
|
|
||||
|
if( $(window).width() < 500 ) { |
||||
|
$('#idMain').css('width' ,'100%'); |
||||
|
$('#idMenu-preview').css('width', 60 * $(window).width() / 100 ) |
||||
|
} else { |
||||
|
$('#idMenu-preview').css('width', 500 ) |
||||
|
} |
||||
|
|
||||
|
$('#idMenu').click(function() { |
||||
|
$(this).fadeOut(); |
||||
|
}) |
||||
|
|
||||
|
$('#idMenu-btnDownload').click(function() { |
||||
|
if( confirm("Télécharger le bobinogramme ?\n\nPour les iPhone-istes, un nouvel onglet va s'ouvrir avec le bobinogramme voulu. Un click long sur celui-ci permet de la télécharger définitivement.") ) { |
||||
|
window.open("/booth/build/result/"+BOB_var_selectedBoothId, "_blank"); |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
$('#idMenu-btnPrint').click(function() { |
||||
|
console.log(BOB_var_printer.todos, BOB_var_selectedBoothId) |
||||
|
if( BOB_var_printer.todos.indexOf(BOB_var_selectedBoothId) === -1 ) { |
||||
|
if( confirm("Envoyer une demande d'impression du bobinogramme pour le livre d'Or?\n\nPour que tout le monde puisse y mettre sa bobine, ne faites qu'une seule demande par groupe.") ) { |
||||
|
$.get("/booth/print/"+BOB_var_selectedBoothId, function(pResponse) { |
||||
|
if( pResponse.error ) { |
||||
|
console.log("Printer: ", pResponse.error) |
||||
|
alert("Echec ! Essayez d'envoyer une nouvelle demande") |
||||
|
} else { |
||||
|
alert("Demande prise en compte !\n\nVotre bobinogramme sera disponible près du Livre d'Or d'ici 1 heure") |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
alert("Une demande a déjà été envoyée.\nVérifiez près du Livre d'Or si votre bobinogramme ne s'y trouve pas.") |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
var BOB_var_lastBooth = "0"; |
||||
|
var BOB_var_selectedBoothId = ""; |
||||
|
var BOB_var_printer = { |
||||
|
todos : [] |
||||
|
} |
||||
|
|
||||
|
function BOB_getBooths() { |
||||
|
var boothList = $(".classBoothItem"); |
||||
|
var jqBoothContainer = $('#idViewContainer'); |
||||
|
|
||||
|
$.get('/booth/toprint', function(pResponse) { |
||||
|
if( pResponse.error ) { |
||||
|
console.log('Printer: ', pResponse.error) |
||||
|
} else { |
||||
|
BOB_var_printer.todos = pResponse.todos |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
$.get('/booth/list/'+BOB_var_lastBooth, function (pResponse) { |
||||
|
if( pResponse.inProgress > 0 ) { |
||||
|
$('#idViewLoading').fadeIn(); |
||||
|
} else { |
||||
|
$('#idViewLoading').fadeOut(); |
||||
|
} |
||||
|
|
||||
|
pResponse.booths.forEach(function (pBoothName) { |
||||
|
var jqImg = $('<img>'); |
||||
|
var jqMenu = $('<div>'); |
||||
|
var jqBtnDownload = $('<button>'); |
||||
|
var jqBtnPrint = $('<button>'); |
||||
|
jqImg.css('width', '100%'); |
||||
|
jqImg.css('opacity', '0'); |
||||
|
jqImg.css('transition', 'opacity 1s'); |
||||
|
jqImg.data('booth', pBoothName); |
||||
|
jqImg.attr('src', "/booth/build/result/low/" + pBoothName); |
||||
|
jqImg.addClass('classBoothItem'); |
||||
|
|
||||
|
jqImg.on('click', function() { |
||||
|
BOB_var_selectedBoothId = pBoothName; |
||||
|
$('#idMenu-preview').attr('src', "/booth/build/result/low/" + pBoothName); |
||||
|
$('#idMenu').fadeIn(); |
||||
|
}) |
||||
|
|
||||
|
jqImg.on('load', function() { |
||||
|
jqImg.css('opacity', '1'); |
||||
|
}) |
||||
|
|
||||
|
if( pBoothName.localeCompare(BOB_var_lastBooth) > 0 ) { |
||||
|
BOB_var_lastBooth = pBoothName; |
||||
|
} |
||||
|
|
||||
|
jqBoothContainer.prepend(jqImg); |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
console.log('-----------------'); |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
@ -0,0 +1,226 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<title>Studio</title> |
||||
|
<!-- Latest compiled and minified CSS --> |
||||
|
<link rel="stylesheet" href="/css/bootstrap.min.css"> |
||||
|
<link rel="stylesheet" href="/css/cover.css"/> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="site-wrapper"> |
||||
|
<div class="site-wrapper-inner"> |
||||
|
<div class="cover-container"> |
||||
|
<div class="inner cover" style="height:900px;position:relative"> |
||||
|
|
||||
|
<div id="idBoothPanel" style="position:absolute;width:100%"> |
||||
|
<div style="padding-top:1em"> |
||||
|
<div id="idViewCountdown" style="font-size:20em; display:none"></div> |
||||
|
<div id="idViewTrigger" style="display:block"> |
||||
|
<h1 class="cover-heading">Prends ta bobine !</h1> |
||||
|
<br/><br/> |
||||
|
<div style="width:800px;height:600px;position:relative;display:none"> |
||||
|
<video id="player" autoplay="true" style="height:100%;width:100%;position:absolute;left:0;top:0"></video> |
||||
|
<div style="position:absolute;background:#3C0000;top:0;left:0;width:<%= killZone.left%>%;height:100%;opacity:0.9"></div> |
||||
|
<div style="position:absolute;background:#3C0000;top:0;right:0;width:<%= killZone.right%>%;height:100%;opacity:0.9"></div> |
||||
|
<div style="position:absolute;background:#3C0000;top:0;left:<%= killZone.left%>%;right:<%= killZone.right%>%;height:<%= killZone.top%>%;opacity:0.9"></div> |
||||
|
<div style="position:absolute;background:#3C0000;bottom:0;left:<%= killZone.left%>%;right:<%= killZone.right%>%;height:<%= killZone.bottom%>%;opacity:0.9"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="idViewGenerating" style="display:none"> |
||||
|
<h1 class="cover-heading">Bobinogramme <i>en cours de génération...</i></h1> |
||||
|
<br/><br/> |
||||
|
<h3>Merci de bien vouloir patienter<br/>une quinzaine de secondes</h3> |
||||
|
<br/> |
||||
|
<br/> |
||||
|
<div style="position:relative;width:100%;height:2px;background:#444"> |
||||
|
<div id="idProgressBar" style="background:#fff;height:2px; width:0%;transition: all 200ms ease"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="idViewBobinogramme" style="display:none"> |
||||
|
<img src="" height="600px"/> |
||||
|
<!-- <h3 class="cover-heading">Retrouve ton <b>bobinogramme</b> sur <br/>http://<%= serverIpAddress %>:<%= serverPort %></h3> --> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div id="idViewDoIt" style="font-size:8em; height:600px; display:none"> |
||||
|
Faites<br/> |
||||
|
<span id="idViewDoIt-theme" style="font-size:2em">le chat</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div id="idPictPreview" style="position:absolute;display:none;width:100%"> |
||||
|
<img src="" height="900px"> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="mastfoot"> |
||||
|
<div class="inner"> |
||||
|
<p>BW Bros.</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</body> |
||||
|
<!-- Latest compiled and minified JQuery --> |
||||
|
<script src="/js/jquery-1.11.2.min.js"></script> |
||||
|
<!-- Latest compiled and minified javaScript bootstrap--> |
||||
|
<script src="/js/bootstrap.min.js"></script> |
||||
|
<!-- Getting the Socket.IO Client --> |
||||
|
<script src="/js/socket.io.js"></script> |
||||
|
</html> |
||||
|
|
||||
|
<style type="text/css"> |
||||
|
* { |
||||
|
-webkit-box-sizing: border-box; |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
|
<script type="text/javascript"> |
||||
|
|
||||
|
var socket = io('/'); |
||||
|
|
||||
|
socket.on('connect', function() { |
||||
|
console.log("connect") |
||||
|
}) |
||||
|
|
||||
|
socket.on('boothClick', function(pData) { |
||||
|
BOB_runBooth(); |
||||
|
}); |
||||
|
|
||||
|
var BOB_var_context = { |
||||
|
boothOnGoing : false, |
||||
|
initTimer : 3, |
||||
|
onGoingTimer : 0, |
||||
|
boothId : null, |
||||
|
pictureId : 0 |
||||
|
} |
||||
|
|
||||
|
var BOB_var_themes = { |
||||
|
selectedId : 0, |
||||
|
list : [ |
||||
|
"le chat", |
||||
|
"le cuir moustache", |
||||
|
"le roi", |
||||
|
"le bouffon", |
||||
|
"le moussailon", |
||||
|
"le geek", |
||||
|
"l'amoureux", |
||||
|
] |
||||
|
} |
||||
|
|
||||
|
$(document).ready(function() { |
||||
|
$(document).keypress(function (e) { |
||||
|
if (e.which === 32) BOB_runBooth() |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
function BOB_runBooth() { |
||||
|
if( BOB_var_context.boothOnGoing === false ) { |
||||
|
var currentDate = new Date(); |
||||
|
BOB_var_context.boothOnGoing = true; |
||||
|
BOB_var_context.boothId = currentDate.getTime(); |
||||
|
BOB_var_context.pictureId = 0; |
||||
|
BOB_var_context.onGoingTimer = BOB_var_context.initTimer; |
||||
|
|
||||
|
$('#idViewTrigger').fadeOut(500, function() { |
||||
|
BOB_countdown(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function BOB_countdown() { |
||||
|
$('#idViewCountdown').fadeIn(); |
||||
|
$('#idViewCountdown').html(BOB_var_context.onGoingTimer); |
||||
|
// |
||||
|
if( BOB_var_context.onGoingTimer > 5 ) { |
||||
|
// $('#idViewDoIt').show(); |
||||
|
// $('#idViewDoIt-theme').hide(); |
||||
|
} else if( BOB_var_context.onGoingTimer > 2 ) { |
||||
|
// $('#idViewDoIt-theme').html( BOB_var_themes.list[BOB_var_themes.selectedId] ); |
||||
|
// $('#idViewDoIt-theme').show(); |
||||
|
} |
||||
|
|
||||
|
if( BOB_var_context.onGoingTimer > 0 ) { |
||||
|
setTimeout(function() { |
||||
|
BOB_var_context.onGoingTimer -= 1; |
||||
|
BOB_countdown(); |
||||
|
}, 1000) |
||||
|
} else { |
||||
|
$('#idViewCountdown').html("Smile"); |
||||
|
BOB_takeThe1Pictures(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function BOB_displayPictPreview(pBoothId, pPictureId, pCallback) { |
||||
|
$('#idViewCountdown').html(""); |
||||
|
$('#idPictPreview > img').attr('src', '/img/prebuilt/'+pBoothId+'/pict_'+pPictureId+'.jpg'); |
||||
|
$('#idBoothPanel').fadeOut(50, function() { |
||||
|
$('#idPictPreview').show(); |
||||
|
setTimeout(function() { |
||||
|
$('#idPictPreview').hide(); |
||||
|
$('#idBoothPanel').fadeIn(50, function() { |
||||
|
pCallback() |
||||
|
}) |
||||
|
}, 4000) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
var BOB_var_progressTimer = new Date(); |
||||
|
|
||||
|
function BOB_lauchFakeProgressBar() { |
||||
|
setTimeout(function() { |
||||
|
var progress = (new Date() - BOB_var_progressTimer) / <%= renderingTime %> * 100; |
||||
|
$('#idProgressBar').css('width', progress+'%'); |
||||
|
if( progress < 100 ) { |
||||
|
BOB_lauchFakeProgressBar(); |
||||
|
} |
||||
|
}, 500) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
function BOB_takeThe1Pictures() { |
||||
|
$.get('/booth/dslr/takepicture/'+BOB_var_context.boothId+'/'+BOB_var_context.pictureId, function(pResponse) { |
||||
|
if( pResponse.error ) { |
||||
|
if( confirm(pResponse.error) ) { |
||||
|
BOB_var_context.boothOnGoing = false; |
||||
|
$('#idViewCountdown').fadeOut(500, function() { |
||||
|
$('#idViewTrigger').fadeIn(); |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
BOB_var_context.pictureId += 1; |
||||
|
if( BOB_var_context.pictureId < 4 ) { |
||||
|
BOB_var_context.onGoingTimer = BOB_var_context.initTimer; |
||||
|
BOB_countdown(); |
||||
|
} else { |
||||
|
$('#idViewCountdown').fadeOut(500, function() { |
||||
|
BOB_var_progressTimer = new Date(); |
||||
|
$('#idProgressBar').css('width', '0'); |
||||
|
$('#idViewGenerating').fadeIn(); |
||||
|
BOB_lauchFakeProgressBar() |
||||
|
}) |
||||
|
$.get('/booth/build/'+BOB_var_context.boothId, function(pResponse) { |
||||
|
$('#idViewBobinogramme > img').attr('src', '/booth/build/result/low/'+pResponse.boothId+'.jpg'); |
||||
|
$('#idViewGenerating').fadeOut(500, function() { |
||||
|
$('#idViewBobinogramme').fadeIn(500, function() { |
||||
|
setTimeout(function(){ |
||||
|
BOB_var_context.boothOnGoing = false; |
||||
|
$('#idViewBobinogramme').fadeOut(500, function() { |
||||
|
$('#idViewTrigger').fadeIn(); |
||||
|
}); |
||||
|
}, 10000) |
||||
|
}) |
||||
|
}) |
||||
|
}); |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
@ -0,0 +1,62 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
<title>Bobinoscope</title> |
||||
|
<!-- Latest compiled and minified CSS --> |
||||
|
<link rel="stylesheet" href="/css/view.css"/> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="idMain" style="margin: auto"> |
||||
|
<p> |
||||
|
<button onclick="takePicture()">Prendre une photo</button> |
||||
|
</p> |
||||
|
<div id="idViewLoading"> |
||||
|
<img src='/waiting2.gif'/> |
||||
|
</div> |
||||
|
<div id="idViewContainer"> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</body> |
||||
|
<!-- Latest compiled and minified JQuery --> |
||||
|
<script src="/js/jquery-1.11.2.min.js"></script> |
||||
|
</html> |
||||
|
|
||||
|
<style type="text/css"> |
||||
|
#idViewContainer { |
||||
|
background-size: contain; |
||||
|
background-repeat: no-repeat; |
||||
|
background-position: center; |
||||
|
/* background-origin: */ |
||||
|
} |
||||
|
</style> |
||||
|
|
||||
|
<script type="text/javascript"> |
||||
|
|
||||
|
// var socket = io('http://<%= serverIpAddress %>:<%= serverPort %>'); |
||||
|
// socket.on('connect', function() { |
||||
|
// console.log("connect") |
||||
|
// }) |
||||
|
// socket.on('boothState', function (data) { |
||||
|
// BOB_getBooths(); |
||||
|
// }) |
||||
|
|
||||
|
$(document).ready(function() { |
||||
|
$('#idViewLoading').hide() |
||||
|
$('#idViewContainer').css('height', 90 * $(document).height() / 100) |
||||
|
// console.log() |
||||
|
}) |
||||
|
|
||||
|
function takePicture () { |
||||
|
$('#idViewLoading').fadeIn() |
||||
|
|
||||
|
$.get('/booth/test/takepicture', function (pResponse) { |
||||
|
$('#idViewLoading').fadeOut() |
||||
|
$('#idViewContainer').css('backgroundImage', 'url("/booth/test/takepicture/result?time='+(new Date()).getTime()+'")') |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
</script> |
||||
@ -0,0 +1,107 @@ |
|||||
|
const exec = require('child_process').exec |
||||
|
const path = require('path') |
||||
|
const async = require('async') |
||||
|
const splitLines = require('split-lines') |
||||
|
const mkdirp = require('mkdirp') |
||||
|
const fs = require('fs-extra') |
||||
|
|
||||
|
require('colors') |
||||
|
|
||||
|
var CFG = require('../config') |
||||
|
|
||||
|
let tools = {} |
||||
|
|
||||
|
function execGphoto2 (pArgs, pCallback) { |
||||
|
exec(`gphoto2 ${pArgs}`, function (pErr, pStdout, pStderr) { |
||||
|
if (pErr) { |
||||
|
console.log(`[!] Please install gphoto2`.red) |
||||
|
console.log(`sudo apt-get install gphoto2`) |
||||
|
process.exit(1) |
||||
|
} |
||||
|
let error = null |
||||
|
let outInLines = [] |
||||
|
if (/Error/i.test(pStderr)) { |
||||
|
error = pStderr |
||||
|
} |
||||
|
if (pStdout) { |
||||
|
outInLines = splitLines(pStdout) |
||||
|
} |
||||
|
pCallback(error, outInLines) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
tools.checkVersion = function (pCb) { |
||||
|
console.log('[-] Checking gphoto2 installation...'.bgBlue) |
||||
|
execGphoto2('--version', function (pErr, pStdout) { |
||||
|
console.log(`OK: ${pStdout[0]}`.green) |
||||
|
pCb() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
tools.checkCameraConnection = function (pCb) { |
||||
|
console.log('[-] Checking camera connection...'.bgBlue) |
||||
|
execGphoto2('--auto-detect', function (pErr, pStdout) { |
||||
|
let device = pStdout[2] |
||||
|
if (!device) { |
||||
|
console.log(`[!] Camera not connected`.red) |
||||
|
console.log('1. Connect camera via USB') |
||||
|
console.log('2. Turn on the camera') |
||||
|
process.exit(1) |
||||
|
} |
||||
|
console.log(`OK: ${device}`.green) |
||||
|
pCb() |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
tools.__takeOnePicture = function (pPath, pCb) { |
||||
|
execGphoto2(`--capture-image-and-download --filename=${pPath} --force-overwrite`, pCb) |
||||
|
} |
||||
|
|
||||
|
tools.takeOnePicture = function (pBoothId, pPictId, pCallback) { |
||||
|
let destPict = '/tmp/bobine.jpg' |
||||
|
var destPath = path.join(CFG.paths.original, pBoothId) |
||||
|
var pictOrig = path.join(destPath, CFG.pictNames[pPictId]) |
||||
|
|
||||
|
mkdirp.sync(path.join(CFG.paths.prebuilt, pBoothId)) |
||||
|
|
||||
|
tools.__takeOnePicture(destPict, function (pErr) { |
||||
|
// If error occurs
|
||||
|
if (pErr) return pCallback(pErr) |
||||
|
mkdirp(destPath, function () { |
||||
|
fs.copy(destPict, pictOrig, function (pErr) { |
||||
|
return pCallback(pErr, pictOrig) |
||||
|
}) |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
tools.init = function (pCb) { |
||||
|
let tasks = [] |
||||
|
tasks.push(tools.checkVersion) |
||||
|
tasks.push(tools.checkCameraConnection) |
||||
|
tasks.push(function (pCb) { |
||||
|
let output = '/tmp/bobine-dummy.jpg' |
||||
|
console.log('[-] Taking dummy photo...'.bgBlue) |
||||
|
tools.__takeOnePicture(output, function (pErr) { |
||||
|
if (pErr) { |
||||
|
console.log(`[!] Failed to take picture`.red) |
||||
|
console.log(pErr.grey) |
||||
|
console.log('1. Add one SDCard into the device') |
||||
|
console.log('2. Take one picture manually') |
||||
|
process.exit(1) |
||||
|
} |
||||
|
console.log(`OK: ${output}`.green) |
||||
|
pCb() |
||||
|
}) |
||||
|
|
||||
|
// opn(output)
|
||||
|
// .then(function () {
|
||||
|
// console.log('OK'.green)
|
||||
|
// pCb()
|
||||
|
// })
|
||||
|
}) |
||||
|
|
||||
|
async.waterfall(tasks, pCb) |
||||
|
} |
||||
|
|
||||
|
module.exports = tools |
||||
@ -0,0 +1,155 @@ |
|||||
|
var gm = require('gm').subClass({ imageMagick: true }) |
||||
|
var async = require('async') |
||||
|
var path = require('path') |
||||
|
var fs = require('fs') |
||||
|
var mkdirp = require('mkdirp') |
||||
|
|
||||
|
var CFG = require('../config') |
||||
|
|
||||
|
var tools = {} |
||||
|
|
||||
|
tools.getBoothList = function (pFrom, pCallback) { |
||||
|
fs.readdir(CFG.paths.final, function (pErr, pBoothList) { |
||||
|
var boothList = pBoothList ? pBoothList.sort() : [] |
||||
|
boothList = boothList.splice(boothList.indexOf(pFrom) + 1) |
||||
|
pCallback(pErr, boothList) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
tools.buildBooth = function (pBoothId, pCallback) { |
||||
|
// Create output prebuild directory
|
||||
|
mkdirp.sync(path.join(CFG.paths.prebuilt, pBoothId)) |
||||
|
// Resize pictures
|
||||
|
async.mapSeries(CFG.pictNames, |
||||
|
function (pPictName, pCb) { |
||||
|
var srcPict = path.join(CFG.paths.original, pBoothId, pPictName) |
||||
|
var dstPict = path.join(CFG.paths.prebuilt, pBoothId, pPictName) |
||||
|
|
||||
|
console.log('Resizing ' + dstPict) |
||||
|
|
||||
|
gm(srcPict) |
||||
|
.autoOrient() |
||||
|
.gravity('Center') |
||||
|
.resize(CFG.cropSize.width, CFG.cropSize.height, '^') |
||||
|
.crop(CFG.cropSize.width, CFG.cropSize.height) |
||||
|
.write(dstPict, function (pErr) { |
||||
|
if (pErr) console.log('Failed to resize picture', pErr) |
||||
|
pCb() |
||||
|
}) |
||||
|
}, |
||||
|
function (pErr) { |
||||
|
console.log('Building booth') |
||||
|
switch (CFG.style) { |
||||
|
default : |
||||
|
BOB_generateBooth(pBoothId, 'default', pCallback) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function BOB_generateBooth (pBoothId, pType, pCallback) { |
||||
|
var prebuiltPath = path.join(CFG.paths.prebuilt, pBoothId) |
||||
|
var finalPict = path.join(CFG.paths.final, pBoothId + '.jpg') |
||||
|
var finalLdPict = path.join(CFG.paths.final_ld, pBoothId + '.jpg') |
||||
|
var outPict = gm(CFG.booths[pType].template) |
||||
|
|
||||
|
var printedDate = new Date(parseInt(pBoothId)) |
||||
|
|
||||
|
outPict.fill(CFG.background) |
||||
|
outPict.drawRectangle(0, 0, CFG.booths[pType].resolution.width, CFG.booths[pType].resolution.height) |
||||
|
// Draw footer
|
||||
|
outPict.draw('image Over 0,2100 1600,250 \'' + CFG.footer + '\'') |
||||
|
|
||||
|
CFG.pictNames.forEach(function (pPictName, pIndex) { |
||||
|
var cmdDraw = 'image Over' |
||||
|
cmdDraw += ' ' + CFG.booths[pType].layout[pIndex].x |
||||
|
cmdDraw += ',' + CFG.booths[pType].layout[pIndex].y |
||||
|
cmdDraw += ' ' + CFG.booths[pType].layout[pIndex].width |
||||
|
cmdDraw += ',' + CFG.booths[pType].layout[pIndex].height |
||||
|
cmdDraw += ' \'' + path.join(prebuiltPath, pPictName) + '\'' |
||||
|
|
||||
|
// console.log(cmdDraw);
|
||||
|
outPict.draw(cmdDraw) |
||||
|
}) |
||||
|
|
||||
|
outPict.fill('#666') |
||||
|
outPict.pointSize(20) |
||||
|
outPict.draw('text 1250,2350 "' + printedDate.toUTCString() + '"') |
||||
|
|
||||
|
outPict.write(finalPict, function (pErr) { |
||||
|
if (pErr) { |
||||
|
console.log('Write outfile') |
||||
|
console.log(pErr) |
||||
|
pCallback(pErr) |
||||
|
} else { |
||||
|
gm(finalPict) |
||||
|
.resize(400, null) |
||||
|
.write(finalLdPict, function (pErr) { |
||||
|
pCallback(pErr) |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
module.exports = tools |
||||
|
|
||||
|
tools.init = function () { |
||||
|
BOB_updateConfig() |
||||
|
} |
||||
|
|
||||
|
// function (pConfig) {
|
||||
|
// CFG = pConfig
|
||||
|
// return tools
|
||||
|
// }
|
||||
|
|
||||
|
function BOB_updateConfig () { |
||||
|
fs.readdir(CFG.paths.template, function (pErr, pFiles) { |
||||
|
if (pErr) { |
||||
|
console.log('BOB_updateConfig', 'Path:', CFG.paths.template, pErr) |
||||
|
} else { |
||||
|
async.map(pFiles, |
||||
|
function (pFile, pCb) { |
||||
|
// Get name of template
|
||||
|
var boothName = pFile.split('.')[0] |
||||
|
// Init layouts object for the template
|
||||
|
CFG.booths[boothName] = { |
||||
|
name: boothName, |
||||
|
template: path.join(CFG.paths.template, pFile), |
||||
|
resolution: { width: 0, height: 0 }, |
||||
|
layout: [] |
||||
|
} |
||||
|
// Get reslution of current template
|
||||
|
gm(CFG.booths[boothName].template).size(function (pErr, pValue) { |
||||
|
if (pErr) { |
||||
|
console.log('[ERROR] Get template size', pErr) |
||||
|
} else { |
||||
|
CFG.booths[boothName].resolution = pValue |
||||
|
BOB_generatePictLayout(boothName) |
||||
|
} |
||||
|
pCb() |
||||
|
}) |
||||
|
}, |
||||
|
function (pErr) { |
||||
|
}) |
||||
|
} |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
function BOB_generatePictLayout (pBoothName) { |
||||
|
var index = 0 |
||||
|
var marginX = 20 |
||||
|
var marginY = 20 |
||||
|
|
||||
|
var pictWidth = (CFG.booths[pBoothName].resolution.width - 3 * marginX) / 2 |
||||
|
var pictHeight = parseInt(pictWidth * CFG.cropSize.height / CFG.cropSize.width) |
||||
|
|
||||
|
CFG.pictNames.forEach(function (pPictName, pIndex) { |
||||
|
CFG.booths[pBoothName].layout.push({ |
||||
|
x: marginX + (marginX + pictWidth) * (pIndex % 2), |
||||
|
y: marginY + (marginY + pictHeight) * parseInt(pIndex / 2), |
||||
|
width: pictWidth, |
||||
|
height: pictHeight |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
console.log('INIT DONE') |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save