var express = require('express'); var multer = require('multer'); var mongoose = require('mongoose'); require('./db/config').connect(mongoose); var db = require('./db/api'); var redis = require('redis'); var path = require('path'); var socket = require('dgram'); var uuid = require('node-uuid'); var bodyParser = require("body-parser"); var fs = require('fs'); var app = express(); var redisClient = redis.createClient(); var Video = require('./db/schemas/video').init(mongoose); var server = require('http').createServer(app); var client = socket.createSocket('udp4'); var jsettings = JSON.parse(fs.readFileSync('config/settings.conf', 'utf8')); var filesManager = require('./helpers/files'); var screenShotGenerator = require('./helpers/ffmpeg'); var urlencodedParser = bodyParser.urlencoded({ extended: false }); var upload = multer({dest: 'uploads/'}); app.use(function(request, response, next) { response.setHeader('Access-Control-Allow-Origin', "*"); response.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE'); response.setHeader('Access-Control-Allow-Headers', 'Content-Type'); next(); }); app.use('/libras', express.static('libras')); app.use('/video', express.static('video')); app.use('/ad', express.static('ad')); app.use('/img', express.static('img')); app.use('/srt', express.static('srt')); redisClient.on('connect', function (data) { console.log("Conexão com o redis iniciada com sucesso."); }); var time_os = setInterval(function() { monitor_time(); }, 1); var current_time = 0, rsync_interval = 2000, sync_broadcast, start_time = 0, playback = 0, newTime = false, newVideoTime = 0, differenceTime = 0; var offset = 0; var uid_token = jsettings.token; var client_port = jsettings.client_port; // /* Home page */ // app.get('/', function(request, response) // { // fs.readFile("views/manager.html", function(err, data){ // response.writeHead(200, {'Content-Type': 'text/html'}); // response.write(data); // response.end(); // }); // }); app.post('/api/videos/add', upload.array('files', 3), function (request, response) { if (request.files === undefined) { response.status(300).send('Wrong files.'); } else { var nVideo = new Video(); filesManager(nVideo, request.body.type, request.files, function (nVideo) { console.log("nvideo: " + nVideo); nVideo.id = uuid.v4(); nVideo.author = request.body.author; nVideo.title = request.body.title; nVideo.year = request.body.year; nVideo.category = request.body.category; screenShotGenerator(nVideo.video, nVideo.id, function (url) { nVideo.img = url; db.create(nVideo, function (data) { console.log("[Info] " + data.title + " added to videos."); response.status(200).json("Added"); }) }) }); } }); app.get('/api/status', function (request, response) { redisClient.get('video', function (err, actualVideo) { if (actualVideo != "null" && actualVideo != undefined) { redisClient.get('video-started', function (err, videoStatus) { redisClient.get('video-title', function (err, videoTitle) { redisClient.get('video-id', function (err, videoId) { response.status(200).json({started: videoStatus, video: videoTitle, id: videoId, videoUrl: actualVideo}); }); }); }); } else { response.status(404).send("No video preloaded.") } }); }); app.get('/api/videos/list', function (request, response) { db.read_all(Video, function (videos) { response.status(200).send(videos); }); }); app.post('/api/videos/reset', function (request, response) { db.remove_all(Video, function (data) { response.status(200).send("All videos has been removed."); }); }); app.get('/api/users/reset', function(request, response) { redisClient.ltrim('clients', 1, 0, function (err, data) { console.log('[Info] A lista de clientes foi resetada.'); response.status(200).send('Clients list cleaned.'); }); }); app.get('/api/users/list', function (request, response) { redisClient.lrange('clients', 0, -1, function (err, clientList) { response.status(200).send(JSON.stringify(clientList)); }); }); app.delete('/api/users/:id', function (request, response) { redisClient.get('video-started', function (err, startedStatus) { if (startedStatus === "null") { response.status(500).send('Video in execution.'); } else { db.remove(Video, request.params.id, function (callback) { if (callback != null) { response.status(200).send('Video deleted.'); } else { response.status(500).send(''); } }); } }); }); app.get('/api/entry/:user', function(request, response) { var addr_client = request.connection.remoteAddress; console.log('[Info] Conexão iniciada de: ' + addr_client); redisClient.lrange('clients', 0, -1, function (err, clientsList) { if (clientsList != null) { console.log("indexOf" + clientsList.indexOf(addr_client)); if (clientsList.indexOf(addr_client) == '-1') { redisClient.lpush('clients', addr_client.toString()); console.log("[Info] Novo usuário " + addr_client); } else { console.log("[Info] Usuário " + addr_client + " já está na lista de clientes."); } } else { console.log("[Info] Novo usuário " + addr_client); redisClient.lpush('clients', addr_client.toString()); } getUserInfo(request, response); }); }); app.get('/api/preload/cancel', function (request, response) { redisClient.get('video', function (err, actualVideo) { if (actualVideo != "undefined" && actualVideo != "null") { redisClient.set('video', "null"); redisClient.set('video-id', "null"); redisClient.set('video-deaf', "null"); redisClient.set('video-blind', "null"); redisClient.set('video-started', "false"); redisClient.set('video-title', "null"); newVideoTime = 0; newTime = false; response.status(200).send("Preload canceled."); } else { response.status(401).send("No video preloaded."); } }); }); app.get('/api/start', function (request, response) { redisClient.get('video', function (err, videorunning) { if (videorunning != "null" && videorunning != undefined) { redisClient.set('video-started', "true"); redisClient.lrange('clients', 0, -1, function (err, clientList) { console.log(clientList); if (clientList != null) { start_time = get_current_time(); var message = new Buffer(get_start_message()); console.log("[Info] Mandando mensagem para todos os clientes..."); clientList.forEach(function (iClient) { client.send(message, 0, message.length, client_port, iClient, function (err) { console.log("[Info-Start] Mensagem enviada para o cliente " + iClient); if (err) { client.close(); console.log('[Erro] O socket foi fechado'); } }); }); } else { console.log("[Info] Não há clientes conectados."); } response.status(200).send('Success started.') }); } else { console.log("[Info] Não há videos em pré-load."); response.status(404).send("No video pre-loaded."); } }); }); app.get('/api/preload/:id', function(request, response) { redisClient.get('video', function (err, videorunning) { if (videorunning === "null" || videorunning === undefined) { db.find(Video, request.params.id, function (data) { console.log("[Info] Pré-load video: " + data[0].title + " // Video: " + data[0].video + " // Libras: " + data[0].libras + " // AD: " + data[0].ad); redisClient.set('video', data[0].video); redisClient.set('video-id', data[0].id); redisClient.set('video-title', data[0].title); redisClient.set('video-deaf', data[0].libras === undefined ? "null" : data[0].libras); redisClient.set('video-blind', data[0].ad === undefined ? "null" : data[0].ad); response.status(200).send("Success"); }); } else { console.log("[Info] Já existe vídeo em execução."); response.status(404).send('YAAA VIDEO.'); } }); }); app.get('/api/stop', function(request, response) { redisClient.get('video', function (err, videorunning) { if (videorunning != "null" && videorunning != undefined) { console.log("[Info] Video em execução: " + videorunning); start_time = get_current_time(); var message = new Buffer(get_stop_message()); console.log("[Info] Mandando mensagem de parar para todos os clientes..."); redisClient.lrange('clients', 0, -1, function (err, clientList) { if (clientList != null) { clientList.forEach(function (iClient) { client.send(message, 0, message.length, client_port, iClient, function (err) { console.log("[Info-Stop] Mensagem enviada para " + iClient); if (err) { client.close(); console.log('[Erro] O socket foi fechado.'); } }); }); } else { console.log("[Info] Não há clientes conectados."); } console.log("[Info] Video "+ videorunning + " parado com sucesso."); redisClient.set('video', "null"); redisClient.set('video-id', "null"); redisClient.set('video-deaf', "null"); redisClient.set('video-blind', "null"); redisClient.set('video-started', "false"); redisClient.set('video-title', "null"); newVideoTime = 0; newTime = false; response.status(200).send('Sucessfull stopped.'); }); } else { response.status(404).send('No video.'); console.log("[Info] Não há vídeo em execução."); } }); }); app.get('/api/rsync', function (request, response) { response.status(200).send(JSON.stringify({value: rsync_interval})); }); app.post('/api/rsync', urlencodedParser, function (request, response) { if (request.body.rsynctime) { redisClient.set('rsync-interval', Number(request.body.rsynctime), function (err, data) { response.status(200).send(JSON.stringify({"status": "Sync time successfull changed."})); rsync_interval = Number(request.body.rsynctime); start_sync(Number(request.body.rsynctime)); }); } else { response.status(406).send(JSON.stringify({"error": "Invalid sync time."})); } }); app.post('/api/time', urlencodedParser, function (request, response) { redisClient.get('video-started', function (err, vStarted) { if (vStarted === "true") { if (request.body.time) { newTime = true; differenceTime = Number(request.body.time); send_sync_broadcast(); response.status(200).send(JSON.stringify({"status": "Time successfull changed."})); } else { response.status(406).send(JSON.stringify({"error": "Invalid time."})); } } else { response.status(406).send(JSON.stringify({"error": "No video selected."})); } }); }); function monitor_time() { var time_now = new Date(); current_time = time_now.getTime(); } function send_sync_broadcast() { console.log("[Info] Sincronizando..."); get_time_elapsed(function (time) { console.log("[Info] Sync " + time); redisClient.get('video-started', function (err, vStarted) { if (vStarted === "true") { redisClient.lrange('clients', 0, -1, function (err, clientList) { console.log(clientList); if (clientList != null) { var message_packet = new Buffer(get_sync_message_data(Number(time))); clientList.forEach(function (cList) { client.send(message_packet, 0, message_packet.length, client_port, cList, function(err) { if (err) { client.close(); console.log('[Error] Socket closed'); } }); }); } }); } }); }); } function get_current_time() { var date = new Date(); var current = date.getTime(); return current; } function get_time_elapsed(callback) { redisClient.get('video-started', function (err, vStarted) { if (vStarted === "true") { if (newTime) { newVideoTime = newVideoTime + differenceTime; newTime = false; } callback((current_time - start_time) + newVideoTime); } else { callback(0); } }); } function get_sync_message_data(time) { return JSON.stringify({type: "SYNC", server_uid: uid_token, pts: time.toString()}); } function get_start_message() { return JSON.stringify({type: "START", server_uid: uid_token, offset: offset}); } function get_stop_message() { return JSON.stringify({type: "STOP", server_uid: uid_token}); } function start_sync(interval) { clearInterval(sync_broadcast); sync_broadcast = setInterval(function() { send_sync_broadcast(); }, interval); } function getUserInfo(request, response) { var user_content; var time = 0; get_time_elapsed(function (time) { redisClient.get('video-id', function (err, videoId) { db.find(Video, videoId, function (videoInfo) { if (videoInfo.length >= 1) { redisClient.get("video-"+request.params.user, function (err, content) { response.json({ uid: uid_token, content: '/'+content, author: videoInfo[0].author, title: videoInfo[0].title, year: videoInfo[0].year, // duration: videoInfo[0].duration, img: '/'+videoInfo[0].img, pts: time }); response.end(); }); } else { response.status(404).json({ message: "No video preloaded." }) } }); }) }); } // Start server server.listen(jsettings.server_port, jsettings.server_ip, function () { redisClient.get('rsync-interval', function (err, data) { if (data != null && data != undefined) { rsync_interval = Number(data); } start_sync(rsync_interval); }); });