Commit 68012fb0dc73866ffa1103764ebeca834d56010f

Authored by Mateus Lustosa
1 parent 315b1e1e
Exists in devel

Fix concurrence problem

Assets/Scripts/PlayerManager.cs
@@ -5,21 +5,30 @@ using System.IO; @@ -5,21 +5,30 @@ using System.IO;
5 using System.Threading; 5 using System.Threading;
6 using System.Collections; 6 using System.Collections;
7 using System.Collections.Generic; 7 using System.Collections.Generic;
8 -using System.Runtime.InteropServices;  
9 -using System.Net.Sockets;  
10 -using System.Diagnostics;  
11 8
12 public class PlayerManager : GenericPlayerManager { 9 public class PlayerManager : GenericPlayerManager {
13 10
14 private Server server = null; 11 private Server server = null;
15 - private Semaphore serverSemaphore = null;  
16 -  
17 private volatile Queue<Message> messages = new Queue<Message>(); 12 private volatile Queue<Message> messages = new Queue<Message>();
18 - private volatile bool toFinalize = false; 13 +
  14 + private readonly Semaphore finalizationLocker = new Semaphore(0, 1);
  15 + private readonly object messageQueueLocker = new object();
  16 +
  17 + public Semaphore FinalizationLocker {
  18 + get { return this.finalizationLocker; }
  19 + }
  20 +
  21 + public object MessageQueueLocker {
  22 + get { return this.messageQueueLocker; }
  23 + }
19 24
20 public override void Start() 25 public override void Start()
21 { 26 {
22 base.Start(); 27 base.Start();
  28 + Screen.SetResolution(800, 600, false);
  29 +
  30 + Debug.Log("PM.S(): Setting args");
  31 +
23 string[] args = Environment.GetCommandLineArgs(); 32 string[] args = Environment.GetCommandLineArgs();
24 33
25 if (args.Length >= 5) 34 if (args.Length >= 5)
@@ -56,57 +65,65 @@ public class PlayerManager : GenericPlayerManager { @@ -56,57 +65,65 @@ public class PlayerManager : GenericPlayerManager {
56 ); 65 );
57 } 66 }
58 67
59 - serverSemaphore = new Semaphore(0, 1);  
60 - server = new Server(serverSemaphore, this);  
61 - Thread t = new Thread(new ThreadStart(server.startServer));  
62 - t.Start(); 68 + Debug.Log("PM.S(): Setting lockers");
63 69
64 - serverSemaphore.WaitOne(); 70 + // Starts thread to wait for app finalization
  71 + new Thread(new ThreadStart(waitFinalize)).Start();
65 72
66 - //UnityEngine.Debug.Log("Datapath: " + Application.dataPath); 73 + Debug.Log("PM.S(): Starting server");
67 74
68 - Screen.SetResolution(800, 600, false);  
69 - } 75 + // Start server
  76 + server = new Server(this);
  77 + new Thread(new ThreadStart(server.StartCommunication)).Start();
70 78
71 - protected void Update() {  
72 - if (toFinalize)  
73 - {  
74 - UnityEngine.Debug.Log("PM.U(): Update -> toFinalize == " + toFinalize);  
75 - Application.Quit();  
76 - } 79 + // Starts communication thread and wait for finalize
  80 + StartCoroutine(MessageChecker());
77 } 81 }
78 82
79 - public void enqueueMessage(Message message) {  
80 - //UnityEngine.Debug.Log("PlayerManager.enqueueMessage( " + message.Text + " )"); 83 + public void enqueueMessage(Message message)
  84 + {
  85 + UnityEngine.Debug.Log("PM.eM(): " + message.Text + ", " + message.Time);
81 messages.Enqueue(message); 86 messages.Enqueue(message);
82 } 87 }
83 88
84 - public void finishConnection() {  
85 - //UnityEngine.Debug.Log("PlayerManager.finishConnection()");  
86 - StartCoroutine(MessageChecker()); 89 + private void waitFinalize()
  90 + {
  91 + Debug.Log("PM.WF(): START");
  92 + FinalizationLocker.WaitOne();
  93 + Debug.Log("PM.WF(): Finalize command received");
  94 +
  95 + Application.Quit();
87 } 96 }
88 97
89 IEnumerator MessageChecker() 98 IEnumerator MessageChecker()
90 { 99 {
  100 + Debug.Log("PM.MC(): START");
  101 +
  102 + while (server.IsNotReady)
  103 + yield return null;
  104 +
  105 + Debug.Log("PM.MC(): Starting to read messages");
  106 +
91 CameraCapture.capture = true; 107 CameraCapture.capture = true;
92 foreach (Message message in messages) 108 foreach (Message message in messages)
93 { 109 {
94 while ((CameraCapture.frameNumber * 1000) / CameraCapture.frameRate < message.Time) 110 while ((CameraCapture.frameNumber * 1000) / CameraCapture.frameRate < message.Time)
95 yield return null; 111 yield return null;
96 112
97 - UnityEngine.Debug.Log("PM.MS(): Loading " + message.Text); 113 + UnityEngine.Debug.Log("PM.MC(): Loading " + message.Text);
98 base.playQueued(message.Text); 114 base.playQueued(message.Text);
99 } 115 }
100 116
101 while (base.isPlaying() || base.isLoading()) 117 while (base.isPlaying() || base.isLoading())
102 yield return null; 118 yield return null;
103 119
104 - UnityEngine.Debug.Log("PM.MS(): ALL DONE!");  
105 - server.sendFinalizeToCore(); 120 + UnityEngine.Debug.Log("PM.MC(): All done!");
  121 +
  122 + server.SendFinalizeToCore();
106 CameraCapture.capture = false; 123 CameraCapture.capture = false;
107 - UnityEngine.Debug.Log("PM.MS(): CameraCapture.capture == " + CameraCapture.capture);  
108 - toFinalize = true;  
109 - UnityEngine.Debug.Log("PM.MS(): toFinalize == " + toFinalize); 124 + UnityEngine.Debug.Log("PM.MC(): CameraCapture.capture == " + CameraCapture.capture);
  125 +
  126 + Application.Quit();
110 } 127 }
111 128
112 public override WWW loadAssetBundle(string aniName) 129 public override WWW loadAssetBundle(string aniName)
Assets/Scripts/PlayerManager/GenericPlayerManager.cs
@@ -18,17 +18,23 @@ @@ -18,17 +18,23 @@
18 * - Reprodução 18 * - Reprodução
19 * Quando não há acesso aos bundles dos sinais de pontuação, eles são ignorados. 19 * Quando não há acesso aos bundles dos sinais de pontuação, eles são ignorados.
20 * Ç adicionado como TYPE_WORD. 20 * Ç adicionado como TYPE_WORD.
  21 + *
  22 + * Versão 2.5
  23 + * - Sincronização
  24 + * Retira os LOCKERs.
  25 + * Os LOCKERs não impedem que duas Coroutines entrem na mesma sessão crítica.
  26 + * A soluação utiliza o estado loading na coroutine LoadAndPlay.
  27 + * - Código
  28 + * Retira namespaces não utilizados.
  29 + * Adiciona logs.
21 */ 30 */
22 31
23 //Log Dir http://docs.unity3d.com/Manual/LogFiles.html 32 //Log Dir http://docs.unity3d.com/Manual/LogFiles.html
  33 +
24 using UnityEngine; 34 using UnityEngine;
25 using System.Collections; 35 using System.Collections;
26 using System.Collections.Generic; 36 using System.Collections.Generic;
27 using System; 37 using System;
28 -using System.Threading;  
29 -using System.IO;  
30 -using System.Text;  
31 -using System.Runtime.InteropServices;  
32 using UnityEngine.UI; 38 using UnityEngine.UI;
33 39
34 public abstract class GenericPlayerManager : MonoBehaviour { 40 public abstract class GenericPlayerManager : MonoBehaviour {
@@ -66,6 +72,8 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -66,6 +72,8 @@ public abstract class GenericPlayerManager : MonoBehaviour {
66 // True quando é chamada a função de pausa 72 // True quando é chamada a função de pausa
67 private volatile bool paused = false; 73 private volatile bool paused = false;
68 74
  75 + private IEnumerator subtitlesSynchronizer;
  76 +
69 // Se diferente de null, não está reproduzindo animação de intervalo 77 // Se diferente de null, não está reproduzindo animação de intervalo
70 private AnimationState intervalAnimationState = null; 78 private AnimationState intervalAnimationState = null;
71 // Usado para pausar quando comandado 79 // Usado para pausar quando comandado
@@ -87,6 +95,8 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -87,6 +95,8 @@ public abstract class GenericPlayerManager : MonoBehaviour {
87 subtitles.DefaultLetterSpeed = new DefaultSignSpeed(3F, 4.3F); 95 subtitles.DefaultLetterSpeed = new DefaultSignSpeed(3F, 4.3F);
88 subtitles.DefaultNumberSpeed = new DefaultSignSpeed(1.5F, 2.9F); 96 subtitles.DefaultNumberSpeed = new DefaultSignSpeed(1.5F, 2.9F);
89 97
  98 + subtitlesSynchronizer = SubtitlesSynchronizer();
  99 +
90 AVATAR = GameObject.FindGameObjectWithTag("avatar"); 100 AVATAR = GameObject.FindGameObjectWithTag("avatar");
91 COMPONENT_ANIMATION = AVATAR.GetComponent<Animation>(); 101 COMPONENT_ANIMATION = AVATAR.GetComponent<Animation>();
92 102
@@ -175,8 +185,8 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -175,8 +185,8 @@ public abstract class GenericPlayerManager : MonoBehaviour {
175 /* Para carregamento e animações */ 185 /* Para carregamento e animações */
176 public void stopAll() 186 public void stopAll()
177 { 187 {
178 - StopCoroutine("loadAndPlay");  
179 - this.randomAnimations.unlockFor("loadAndPlay"); 188 + StopCoroutine("LoadAndPlay");
  189 + this.randomAnimations.unlockFor("GPM.LoadAndPlay");
180 loading = false; 190 loading = false;
181 191
182 stopAnimations(); 192 stopAnimations();
@@ -185,8 +195,8 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -185,8 +195,8 @@ public abstract class GenericPlayerManager : MonoBehaviour {
185 /* Para animações */ 195 /* Para animações */
186 public void stopAnimations() 196 public void stopAnimations()
187 { 197 {
188 - StopCoroutine("handleStates");  
189 - this.randomAnimations.unlockFor("handleStates"); 198 + StopCoroutine(subtitlesSynchronizer);
  199 + this.randomAnimations.unlockFor("GPM.SubtitlesSynchronizer");
190 this.subtitles.setText(""); 200 this.subtitles.setText("");
191 201
192 lock (this.animQueue) { this.animQueue.Clear(); } 202 lock (this.animQueue) { this.animQueue.Clear(); }
@@ -294,62 +304,39 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -294,62 +304,39 @@ public abstract class GenericPlayerManager : MonoBehaviour {
294 setPauseState( ! this.paused); 304 setPauseState( ! this.paused);
295 } 305 }
296 306
297 - private System.Object LOCKER_PLAY = new System.Object();  
298 -  
299 /* Play if anything loading or playing */ 307 /* Play if anything loading or playing */
300 public bool playIfEmpty(string gloss) 308 public bool playIfEmpty(string gloss)
301 { 309 {
302 - lock (LOCKER_PLAY)  
303 - {  
304 - if (this.loading || this.playing)  
305 - return false; 310 + if (this.loading || this.playing)
  311 + return false;
306 312
307 - StartCoroutine("loadAndPlay", gloss);  
308 - } 313 + StartCoroutine(LoadAndPlay(gloss));
309 314
310 return true; 315 return true;
311 } 316 }
312 317
313 - private System.Object LOCKER_GLOSS_WATING = new System.Object();  
314 - private int numGlossWating = 0;  
315 - public void setGlossWaiting(bool inc) { lock (LOCKER_GLOSS_WATING) { numGlossWating += inc ? 1 : -1; } }  
316 - public bool hasGlossWaiting() { lock (LOCKER_GLOSS_WATING) { return this.numGlossWating > 0; } }  
317 -  
318 - /* Enqueue animations for playing */ 318 + /* Enqueue animations */
319 public void playQueued(string gloss) 319 public void playQueued(string gloss)
320 { 320 {
321 - lock (LOCKER_PLAY)  
322 - {  
323 - Debug.Log("GPM.pQ(" + gloss + ")");  
324 - setGlossWaiting(true);  
325 - StartCoroutine("loadAndPlay", gloss);  
326 - } 321 + Debug.Log("GPM.pQ(" + gloss + ")");
  322 + StartCoroutine(LoadAndPlay(gloss));
327 } 323 }
328 324
329 /* Stop all and play */ 325 /* Stop all and play */
330 public void playNow(string gloss) 326 public void playNow(string gloss)
331 { 327 {
332 - lock (LOCKER_PLAY)  
333 - {  
334 - Debug.Log("GPM.pN(" + gloss + ")");  
335 - stopAll();  
336 - StartCoroutine("loadAndPlay", gloss);  
337 - } 328 + Debug.Log("GPM.pN(" + gloss + ")");
  329 + stopAll();
  330 + StartCoroutine(LoadAndPlay(gloss));
338 } 331 }
339 332
340 /* Reproduz animação de intervalo */ 333 /* Reproduz animação de intervalo */
341 public bool playIntervalAnimation(string name) 334 public bool playIntervalAnimation(string name)
342 { 335 {
343 - if ( ! Monitor.TryEnter(LOCKER_PLAY))  
344 - return false;  
345 -  
346 - lock (LOCKER_PLAY)  
347 - {  
348 - playDefaultAnimation(true);  
349 - this.intervalAnimationState = COMPONENT_ANIMATION.CrossFadeQueued(name, fadeLength, QueueMode.CompleteOthers);  
350 - playDefaultAnimation(false);  
351 - }  
352 - 336 + playDefaultAnimation(true);
  337 + this.intervalAnimationState = COMPONENT_ANIMATION.CrossFadeQueued(name, fadeLength, QueueMode.CompleteOthers);
  338 + playDefaultAnimation(false);
  339 +
353 return true; 340 return true;
354 } 341 }
355 342
@@ -443,7 +430,7 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -443,7 +430,7 @@ public abstract class GenericPlayerManager : MonoBehaviour {
443 return lastAnimationSubtitle; 430 return lastAnimationSubtitle;
444 } 431 }
445 432
446 - /* Instruções para reprodução de aninmação */ 433 + /* Instruções para reprodução de animação */
447 private struct ToPlay 434 private struct ToPlay
448 { 435 {
449 private short type; 436 private short type;
@@ -469,239 +456,229 @@ public abstract class GenericPlayerManager : MonoBehaviour { @@ -469,239 +456,229 @@ public abstract class GenericPlayerManager : MonoBehaviour {
469 context.playAnimation(this.type, this.name, this.subtitle, this.speed); 456 context.playAnimation(this.type, this.name, this.subtitle, this.speed);
470 } 457 }
471 } 458 }
472 -  
473 - private System.Object LOCKER_LOADING = new System.Object();  
474 - 459 +
475 /* Carrega animações e reproduz */ 460 /* Carrega animações e reproduz */
476 - private IEnumerator loadAndPlay(string gloss) 461 + private IEnumerator LoadAndPlay(string gloss)
477 { 462 {
478 - lock (LOCKER_LOADING)  
479 - {  
480 - Debug.Log("GPM.lAP(" + gloss + ")"); 463 + Debug.Log("GPM.LAP(" + gloss + ")");
481 464
482 - this.randomAnimations.lockFor("loadAndPlay");  
483 - this.loading = true;  
484 - setGlossWaiting(false);  
485 - // onPlayingStateChange(); 465 + while (loading) yield return null;
486 466
487 - string lastAnimationSubtitle = "";  
488 - bool spelled = false; 467 + this.loading = true;
  468 + // onPlayingStateChange();
  469 + this.randomAnimations.lockFor("GPM.LoadAndPlay");
489 470
490 - if ( ! this.playing)  
491 - StartCoroutine("handleStates"); 471 + string lastAnimationSubtitle = "";
  472 + bool spelled = false;
492 473
493 - String[] stringPos = gloss.Split(' '); 474 + StartCoroutine(subtitlesSynchronizer);
494 475
495 - Queue<ToPlay> toPlayQueue = new Queue<ToPlay>();  
496 - int wordsCount = 0;  
497 - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "", this)); 476 + String[] stringPos = gloss.Split(' ');
498 477
499 - foreach (string aniName in stringPos)  
500 - {  
501 - Debug.Log("GPM.lAP(" + gloss + "): Animation name: " + aniName); 478 + Queue<ToPlay> toPlayQueue = new Queue<ToPlay>();
  479 + int wordsCount = 0;
  480 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "", this));
  481 +
  482 + foreach (string aniName in stringPos)
  483 + {
  484 + Debug.Log("GPM.LAP(" + gloss + "): Animation name: " + aniName);
  485 +
  486 + wordsCount++;
  487 + if (String.IsNullOrEmpty(aniName)) continue;
502 488
503 - wordsCount++;  
504 - if (String.IsNullOrEmpty(aniName)) continue; 489 + bool nonexistent = nonexistentAssetBundles.Contains(aniName);
  490 + bool loaded = loadedAssetBundles.Contains(aniName);
505 491
506 - bool nonexistent = nonexistentAssetBundles.Contains(aniName);  
507 - bool loaded = loadedAssetBundles.Contains(aniName); 492 + if ( ! nonexistent && ! loaded)
  493 + {
  494 + // Função loadAssetBundle é definida pela classe filha
  495 + WWW www = loadAssetBundle(aniName);
508 496
509 - if ( ! nonexistent && ! loaded) 497 + if (www != null)
510 { 498 {
511 - // Função loadAssetBundle é definida pela classe filha  
512 - WWW www = loadAssetBundle(aniName); 499 + Debug.Log("GPM:LAP(" + gloss + "): www != null");
  500 + yield return www;
513 501
514 - if (www != null)  
515 - {  
516 - Debug.Log("GPM:lAP(" + gloss + "): www != null");  
517 - yield return www; 502 + AssetBundle bundle = null;
518 503
519 - AssetBundle bundle = null; 504 + if (www.error == null)
  505 + {
  506 + Debug.Log("GPM:LAP(" + gloss + "): www.error == null");
  507 + bundle = www.assetBundle;
520 508
521 - if (www.error == null) 509 + if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name))
522 { 510 {
523 - Debug.Log("GPM:lAP(" + gloss + "): www.error == null");  
524 - bundle = www.assetBundle; 511 + AnimationClip aniClip = bundle.mainAsset as AnimationClip;
  512 + bundle.Unload(false);
525 513
526 - if (bundle != null && ! String.IsNullOrEmpty(bundle.mainAsset.name)) 514 + if (aniClip)
527 { 515 {
528 - AnimationClip aniClip = bundle.mainAsset as AnimationClip;  
529 - bundle.Unload(false);  
530 -  
531 - if (aniClip)  
532 - {  
533 - COMPONENT_ANIMATION.AddClip(aniClip, aniName); 516 + COMPONENT_ANIMATION.AddClip(aniClip, aniName);
534 517
535 - loadedAssetBundles.Add(aniName);  
536 - loaded = true; 518 + loadedAssetBundles.Add(aniName);
  519 + loaded = true;
537 520
538 - Debug.Log("GPM:lAP(" + gloss + "): Bundle \"" + aniName + "\" loaded!");  
539 - }  
540 - else Debug.Log ("GPM:lAP(" + gloss + "): Sinal \"" + aniName + "\" foi não carregado corretamente."); 521 + Debug.Log("GPM:LAP(" + gloss + "): Bundle \"" + aniName + "\" loaded!");
541 } 522 }
  523 + else Debug.Log ("GPM:lAP(" + gloss + "): Sinal \"" + aniName + "\" foi não carregado corretamente.");
542 } 524 }
543 - else onConnectionError(gloss, aniName);  
544 } 525 }
545 else onConnectionError(gloss, aniName); 526 else onConnectionError(gloss, aniName);
546 } 527 }
  528 + else onConnectionError(gloss, aniName);
  529 + }
547 530
548 - // Reproduz palavra  
549 - if (loaded) 531 + // Reproduz palavra
  532 + if (loaded)
  533 + {
  534 + if (spelled)
550 { 535 {
551 - if (spelled)  
552 - {  
553 - // Default  
554 - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, lastAnimationSubtitle, this));  
555 - spelled = false;  
556 - }  
557 -  
558 - if (this.flags.Contains(aniName) || this.intervalAnimations.Contains(aniName))  
559 - {  
560 - lastAnimationSubtitle = "";  
561 - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_WORD, aniName, "", this));  
562 - }  
563 - else  
564 - {  
565 - lastAnimationSubtitle = aniName;  
566 - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_WORD, aniName, this));  
567 - } 536 + // Default
  537 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, lastAnimationSubtitle, this));
  538 + spelled = false;
568 } 539 }
569 540
570 - // Soletra palavra 541 + if (this.flags.Contains(aniName) || this.intervalAnimations.Contains(aniName))
  542 + {
  543 + lastAnimationSubtitle = "";
  544 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_WORD, aniName, "", this));
  545 + }
571 else 546 else
572 { 547 {
573 - // Se a animação não foi carregada e nem está marcada como não existente,  
574 - // adiciona ao set de animações não existentes  
575 - if ( ! nonexistent)  
576 - nonexistentAssetBundles.Add(aniName); 548 + lastAnimationSubtitle = aniName;
  549 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_WORD, aniName, this));
  550 + }
  551 + }
  552 +
  553 + // Soletra palavra
  554 + else
  555 + {
  556 + // Se a animação não foi carregada e nem está marcada como não existente,
  557 + // adiciona ao set de animações não existentes
  558 + if ( ! nonexistent)
  559 + nonexistentAssetBundles.Add(aniName);
577 560
578 - UnityEngine.Debug.Log("GPM:lAP(" + gloss + "): To spell: " + aniName); 561 + UnityEngine.Debug.Log("GPM:lAP(" + gloss + "): To spell: " + aniName);
579 562
580 - if (this.flags.Contains(aniName) || this.intervalAnimations.Contains(aniName))  
581 - { 563 + if (this.flags.Contains(aniName) || this.intervalAnimations.Contains(aniName))
  564 + {
  565 + toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F));
  566 + spelled = false;
  567 + }
  568 + else
  569 + {
  570 + // Se já houve o soletramento de alguma palavra, reproduz animação default
  571 + if (spelled)
582 toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F)); 572 toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F));
583 - spelled = false;  
584 - }  
585 else 573 else
586 - {  
587 - // Se já houve o soletramento de alguma palavra, reproduz animação default  
588 - if (spelled)  
589 - toPlayQueue.Enqueue(new ToPlay(Subtitle.TYPE_NONE, DEFAULT_ANIMATION_MIDDLE, "", 1.6F));  
590 - else  
591 - spelled = true; 574 + spelled = true;
592 575
593 - lastAnimationSubtitle = spellWord(toPlayQueue, aniName);  
594 - } 576 + lastAnimationSubtitle = spellWord(toPlayQueue, aniName);
595 } 577 }
596 -  
597 - if (toPlayQueue.Count > 4 || wordsCount == stringPos.Length)  
598 - while (toPlayQueue.Count > 0)  
599 - toPlayQueue.Dequeue().play(this);  
600 } 578 }
601 579
602 - // Default  
603 - playAnimation(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "");  
604 -  
605 - this.loading = false;  
606 - // onPlayingStateChange();  
607 - this.randomAnimations.unlockFor("loadAndPlay"); 580 + if (toPlayQueue.Count > 4 || wordsCount == stringPos.Length)
  581 + while (toPlayQueue.Count > 0)
  582 + toPlayQueue.Dequeue().play(this);
608 } 583 }
609 - }  
610 584
611 - private System.Object LOCKER_PLAYING = new System.Object(); 585 + // Default
  586 + playAnimation(Subtitle.TYPE_NONE, DEFAULT_ANIMATION, "");
  587 +
  588 + this.randomAnimations.unlockFor("GPM.LoadAndPlay");
  589 + this.loading = false;
  590 + // onPlayingStateChange();
  591 + }
612 592
613 /* Sincroniza as legendas com as animações. */ 593 /* Sincroniza as legendas com as animações. */
614 - IEnumerator handleStates() 594 + private IEnumerator SubtitlesSynchronizer()
615 { 595 {
616 - lock (LOCKER_PLAYING)  
617 - {  
618 - UnityEngine.Debug.Log("GPM:hS()"); 596 + UnityEngine.Debug.Log("GPM.SS()");
619 597
620 - this.randomAnimations.lockFor("handleStates");  
621 - this.playing = true;  
622 - onPlayingStateChange(); 598 + this.randomAnimations.lockFor("GPM.SubtitlesSynchronizer");
  599 + this.playing = true;
  600 + onPlayingStateChange();
623 601
624 - bool isNotEmpty;  
625 - lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; } 602 + bool isNotEmpty;
  603 + lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; }
626 604
627 - // Animação anterior a atual  
628 - AnimationReference endedAnimation = null; 605 + // Animação anterior a atual
  606 + AnimationReference endedAnimation = null;
629 607
630 - // Enquanto estiver executando a corotina "loadAndPlay"  
631 - // ou existir animações na fila de reprodução  
632 - while (loading || isNotEmpty) 608 + // Enquanto estiver executando a corotina "loadAndPlay"
  609 + // ou existir animações na fila de reprodução
  610 + while (loading || isNotEmpty)
  611 + {
  612 + // Se não houver animações na fila, espera
  613 + if (isNotEmpty)
633 { 614 {
634 - // Se não houver animações na fila, espera  
635 - if (isNotEmpty) 615 + // Pega primeira animação
  616 + AnimationReference reference;
  617 + lock (this.animQueue) { reference = this.animQueue.Peek(); }
  618 +
  619 + // Se estiver sendo reproduzida
  620 + if (COMPONENT_ANIMATION.IsPlaying(reference.name))
636 { 621 {
637 - // Pega primeira animação  
638 - AnimationReference reference;  
639 - lock (this.animQueue) { reference = this.animQueue.Peek(); } 622 + Debug.Log("GPM.SS(): Playing " + reference.name);
  623 + this.subtitles.setText(reference.subtitle);
640 624
641 - // Se estiver sendo reproduzida  
642 - if (COMPONENT_ANIMATION.IsPlaying(reference.name)) 625 + // Animação seguinte
  626 + AnimationReference next = null;
  627 + lock (this.animQueue)
643 { 628 {
644 - Debug.Log("GPM:hS(): Playing " + reference.name);  
645 - this.subtitles.setText(reference.subtitle);  
646 -  
647 - // Animação seguinte  
648 - AnimationReference next = null;  
649 - lock (this.animQueue)  
650 - {  
651 - this.animationPlaying = this.animQueue.Dequeue(); 629 + this.animationPlaying = this.animQueue.Dequeue();
652 630
653 - if (this.animQueue.Count > 0)  
654 - next = this.animQueue.Peek();  
655 - } 631 + if (this.animQueue.Count > 0)
  632 + next = this.animQueue.Peek();
  633 + }
656 634
657 - while (true) 635 + while (true)
  636 + {
  637 + // Se a próxima animação estiver sendo reproduzida (no fade)
  638 + if (next != null && COMPONENT_ANIMATION.IsPlaying(next.name))
658 { 639 {
659 - // Se a próxima animação estiver sendo reproduzida (no fade)  
660 - if (next != null && COMPONENT_ANIMATION.IsPlaying(next.name))  
661 - {  
662 - // Se a animação anterior a atual não tiver acabado,  
663 - // espera acabar e só então conta o tempo  
664 - if (endedAnimation != null)  
665 - while (COMPONENT_ANIMATION.IsPlaying(endedAnimation.name))  
666 - yield return null;  
667 -  
668 - // Tempo para pular para a legenda da próxima animação  
669 - yield return new WaitForSeconds(0.4F); 640 + // Se a animação anterior a atual não tiver acabado,
  641 + // espera acabar e só então conta o tempo
  642 + if (endedAnimation != null)
  643 + while (COMPONENT_ANIMATION.IsPlaying(endedAnimation.name))
  644 + yield return null;
670 645
671 - // Deprecated  
672 - // yield return WaitForContinuousMillis.Wait(this, 300);  
673 -  
674 - endedAnimation = reference;  
675 - break;  
676 - } 646 + // Tempo para pular para a legenda da próxima animação
  647 + yield return new WaitForSeconds(0.4F);
677 648
678 - else if (COMPONENT_ANIMATION.IsPlaying(reference.name))  
679 - yield return null; 649 + // Deprecated
  650 + // yield return WaitForContinuousMillis.Wait(this, 300);
680 651
681 - else break; 652 + endedAnimation = reference;
  653 + break;
682 } 654 }
683 655
684 - reference = null; 656 + else if (COMPONENT_ANIMATION.IsPlaying(reference.name))
  657 + yield return null;
  658 +
  659 + else break;
685 } 660 }
686 661
687 - // Se a animação não tiver sido liberada e seu AnimationState for nulo,  
688 - // a animação será liberada  
689 - if (reference != null && reference.state == null)  
690 - lock (this.animQueue) { this.animQueue.Dequeue(); }  
691 - else  
692 - yield return null; 662 + reference = null;
693 } 663 }
694 - else yield return null;  
695 664
696 - lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; } 665 + // Se a animação não tiver sido liberada e seu AnimationState for nulo,
  666 + // a animação será liberada
  667 + if (reference != null && reference.state == null)
  668 + lock (this.animQueue) { this.animQueue.Dequeue(); }
  669 + else
  670 + yield return null;
697 } 671 }
698 - UnityEngine.Debug.Log("GPM:sH(): All done.");  
699 -  
700 - this.subtitles.setText(""); 672 + else yield return null;
701 673
702 - resetStates();  
703 - this.randomAnimations.unlockFor("handleStates"); 674 + lock (this.animQueue) { isNotEmpty = this.animQueue.Count > 0; }
704 } 675 }
  676 + UnityEngine.Debug.Log("GPM.SS(): All done.");
  677 +
  678 + this.subtitles.setText("");
  679 +
  680 + resetStates();
  681 + this.randomAnimations.unlockFor("GPM.SubtitlesSynchronizer");
705 } 682 }
706 683
707 public void resetStates() 684 public void resetStates()
Assets/Scripts/Server.cs
@@ -15,116 +15,119 @@ using System; @@ -15,116 +15,119 @@ using System;
15 using System.IO; 15 using System.IO;
16 using System.Net; 16 using System.Net;
17 using System.Net.Sockets; 17 using System.Net.Sockets;
18 -using System.Text;  
19 -using System.Threading;  
20 18
21 public class Server { 19 public class Server {
22 20
23 - TcpClient client;  
24 - NetworkStream stream;  
25 - TcpListener server;  
26 - Semaphore serverSemaphore;  
27 - PlayerManager inspector;  
28 - Int32 port = 5555;  
29 -  
30 - public Server(Semaphore ss, PlayerManager inspec){  
31 - serverSemaphore = ss;  
32 - inspector = inspec;  
33 - } // constructor  
34 -  
35 - public void startServer(){  
36 - try{  
37 - IPAddress localAddr = IPAddress.Parse("0.0.0.0");  
38 - server = new TcpListener (localAddr, port);  
39 - server.Start(); // Starts listening for incoming connection requests.  
40 - client = server.AcceptTcpClient(); // Accepts a pending connection request.  
41 - stream = client.GetStream(); 21 + public readonly string ADDRESS = "0.0.0.0";
  22 + public readonly Int32 PORT = 5555;
42 23
43 - serverSemaphore.Release (); // Releases InspectorScript.Start() [Connection]  
44 - getPTSFromCore();  
45 - } 24 + private TcpClient client;
  25 + private NetworkStream stream;
  26 + private TcpListener server;
  27 + private bool isReady = false;
46 28
47 - catch(SocketException e){  
48 - Debug.Log(e);  
49 - closeConnections();  
50 - Application.Quit();  
51 - }  
52 - catch(IOException e){  
53 - Debug.Log(e);  
54 - closeConnections();  
55 - Application.Quit(); 29 + private PlayerManager manager;
  30 +
  31 + public Server(PlayerManager manager)
  32 + {
  33 + this.manager = manager;
  34 +
  35 + try {
  36 + // Starts listening for incoming connection requests
  37 + server = new TcpListener(IPAddress.Parse(ADDRESS), PORT);
  38 + server.Start();
  39 +
  40 + // Accepts a pending connection request
  41 + Debug.Log("S(): Waiting client");
  42 + client = server.AcceptTcpClient();
  43 + stream = client.GetStream();
56 } 44 }
57 - catch(Exception e){ 45 + catch (Exception e)
  46 + {
58 Debug.Log(e); 47 Debug.Log(e);
59 - closeConnections();  
60 - Application.Quit(); 48 + CloseConnections();
  49 + manager.FinalizationLocker.Release();
  50 +
  51 + throw e;
61 } 52 }
62 - } // startServer 53 + }
  54 +
  55 + public bool IsNotReady {
  56 + get { return !isReady; }
  57 + }
63 58
64 - // Receives glosa and pts from Core  
65 - void getPTSFromCore() 59 + /**
  60 + * Starts receiving of glosa and time from server.
  61 + * Stops when receive "FINALIZE".
  62 + */
  63 + public void StartCommunication()
66 { 64 {
  65 + Debug.Log("S.SC()");
  66 +
67 try 67 try
68 { 68 {
69 Byte[] bytes = new Byte[1024]; 69 Byte[] bytes = new Byte[1024];
70 - String data = null;  
71 - int i;  
72 - Byte[] sendToCore;  
73 -  
74 - /*Loop to receive all the data from Core  
75 - util get the string "FINALIZE\0"  
76 - '\0' for c++*/  
77 -  
78 - Debug.Log("getPTSFromCore"); 70 + int size;
79 71
80 - while ((i = stream.Read(bytes, 0, bytes.Length)) != 0) 72 + while ((size = stream.Read(bytes, 0, bytes.Length)) != 0)
81 { 73 {
82 - data = System.Text.UTF8Encoding.UTF8.GetString(bytes, 0, i); 74 + String data = System.Text.UTF8Encoding.UTF8.GetString(bytes, 0, size);
83 75
84 - sendToCore = System.Text.UTF8Encoding.UTF8.GetBytes("OK\0"); // allows Core to send next stream 76 + // Notify the core that the message was received
  77 + Byte[] sendToCore = System.Text.UTF8Encoding.UTF8.GetBytes("OK\0");
85 stream.Write(sendToCore, 0, sendToCore.Length); 78 stream.Write(sendToCore, 0, sendToCore.Length);
86 79
87 Message message = new Message(data); 80 Message message = new Message(data);
88 81
89 - Debug.Log("gPFC: received: " + message.Text); 82 + Debug.Log("S.SC(): Received: " + message.Text);
90 83
91 if (message.Text.Equals("FINALIZE")) 84 if (message.Text.Equals("FINALIZE"))
92 { 85 {
93 - inspector.finishConnection(); 86 + isReady = true;
94 break; 87 break;
95 } 88 }
96 - else  
97 - inspector.enqueueMessage(message); 89 + else manager.enqueueMessage(message);
98 } 90 }
99 91
100 - Debug.Log("~~ getPTSFromCore"); 92 + Debug.Log("S.SC(): END");
101 } 93 }
102 catch (Exception e) 94 catch (Exception e)
103 { 95 {
104 - throw new Exception(e.Source); 96 + Debug.Log(e);
  97 +
  98 + if (!this.isReady)
  99 + {
  100 + CloseConnections();
  101 + manager.FinalizationLocker.Release();
  102 + }
  103 +
  104 + throw e;
105 } 105 }
106 - } // getPTSFromCore 106 + }
107 107
108 - public void sendFinalizeToCore(){  
109 - Byte[] sendToCore = System.Text.UTF8Encoding.UTF8.GetBytes("FINALIZE\0"); // ativar para o core 108 + public void SendFinalizeToCore()
  109 + {
  110 + Byte[] sendToCore = System.Text.UTF8Encoding.UTF8.GetBytes("FINALIZE\0");
110 stream.Write(sendToCore, 0, sendToCore.Length); 111 stream.Write(sendToCore, 0, sendToCore.Length);
111 - //closeConnections();  
112 - }  
113 - public void closeConnections(){  
114 112
  113 + CloseConnections();
  114 + }
  115 +
  116 + private void CloseConnections()
  117 + {
115 try { 118 try {
116 client.Close(); 119 client.Close();
117 stream.Close(); 120 stream.Close();
118 server.Stop(); 121 server.Stop();
119 } 122 }
120 - catch(SocketException e){ 123 + catch (SocketException e) {
121 Debug.Log(e); 124 Debug.Log(e);
122 - closeConnections(); 125 + CloseConnections();
123 } 126 }
124 - catch(IOException e){ 127 + catch (IOException e) {
125 Debug.Log(e); 128 Debug.Log(e);
126 - closeConnections(); 129 + CloseConnections();
127 } 130 }
128 - } // closeConnections 131 + }
129 132
130 } 133 }
131 \ No newline at end of file 134 \ No newline at end of file