@@ -37,7 +37,6 @@ public class MainWindow : Window
37
37
TextBlock tb ;
38
38
Window mainWindow ;
39
39
Panel mainPanel ;
40
- Process videoProcess ; // handle to the video Player
41
40
42
41
// Engines
43
42
internal PlayListEngine playListEngine ;
@@ -121,6 +120,8 @@ private void InitializeComponent()
121
120
tb . Transitions . Add ( fadeTransition ) ;
122
121
tb . Padding = new Thickness ( 30 ) ;
123
122
123
+ VideoPlayer . MainPanelHandle = this . mainPanel ;
124
+ VideoPlayer . MainWindowHandle = this . mainWindow ;
124
125
125
126
string intro ;
126
127
if ( ( AppSettings . Default . Rotation == 0 ) || AppSettings . Default . Rotation == 180 )
@@ -156,7 +157,7 @@ public void GoToNextImage()
156
157
{
157
158
tb . Transitions . Clear ( ) ;
158
159
playListEngine . GoToNext ( ) ;
159
- PlayImageFile ( 500 , playListEngine . CurrentPlayListItem . Path ) ;
160
+ PlayFile ( playListEngine . CurrentPlayListItem . Path , 500 ) ;
160
161
lastUpdated = DateTime . Now ;
161
162
tb . Transitions . Add ( fadeTransition ) ;
162
163
}
@@ -167,7 +168,7 @@ public void GoToPreviousImage()
167
168
{
168
169
tb . Transitions . Clear ( ) ;
169
170
playListEngine . GoToPrevious ( ) ;
170
- PlayImageFile ( 500 , playListEngine . CurrentPlayListItem . Path ) ;
171
+ PlayFile ( playListEngine . CurrentPlayListItem . Path , 500 ) ;
171
172
lastUpdated = DateTime . Now ;
172
173
tb . Transitions . Add ( fadeTransition ) ;
173
174
}
@@ -183,7 +184,7 @@ public void GoToFirstImage()
183
184
}
184
185
Logger . LogComment ( "Waking up and continuing playing files.." ) ;
185
186
186
- PlayImageFile ( 500 , playListEngine . CurrentPlayListItem . Path ) ;
187
+ PlayFile ( playListEngine . CurrentPlayListItem . Path , 500 ) ;
187
188
lastUpdated = DateTime . Now ;
188
189
tb . Transitions . Add ( fadeTransition ) ;
189
190
}
@@ -347,90 +348,63 @@ private void Timer_Tick(object sender, EventArgs e)
347
348
}
348
349
349
350
UpdateInfoBar ( ) ;
351
+ bool GoToNext = false ;
352
+ if ( ( playListEngine . CurrentPlayListItem != null ) && ( playListEngine . CurrentPlayListItem . ItemType == PlayListItemType . Video ) )
353
+ {
354
+ if ( ! VideoPlayer . CheckStatus ( false ) )
355
+ {
356
+ // Video exited before we expected it to! Recover gracefully
357
+ GoToNext = true ;
358
+ }
359
+ }
360
+
350
361
351
- //
352
- // This is the main check for if we need to switch frames. First we check to see if the
353
- // amount of time that has transpired is over our tranistion time. If so, we check:
354
- // 1) Are we syncing to other frames? if so send those signals
355
- // 2) Is it an audio or video? Call appropriate play method based on that.
356
- //
357
- if ( ( DateTime . Now . Subtract ( lastUpdated ) . TotalMilliseconds > AppSettings . Default . SlideshowTransitionTime ) )
362
+ // check transpired time against transition time...
363
+ if ( ( DateTime . Now . Subtract ( lastUpdated ) . TotalMilliseconds > AppSettings . Default . SlideshowTransitionTime ) || GoToNext == true )
358
364
{
365
+ // See if a video is playing...
366
+ if ( VideoPlayer . CheckStatus ( true ) )
367
+ {
368
+ // Video is still playing, tick off the next timer interval for now.
369
+ slideTimer . Start ( ) ;
370
+ return ;
371
+ }
359
372
lastUpdated = DateTime . Now ;
360
373
playListEngine . GoToNext ( ) ;
361
374
Logger . LogComment ( "Next file is: " + playListEngine . CurrentPlayListItem . Path ) ;
362
375
363
376
// sync frame call
364
- if ( ( AppSettings . Default . IsSyncEnabled ) & & ( SyncedFrame . SyncEngine . syncedFrames . Count > 0 ) )
365
- {
366
- Logger . LogComment ( "SyncFrames enabled...sending sync signals.." ) ;
367
- // We have frames to sync! Send this off to them:
368
- try
369
- {
370
- SyncedFrame . SyncEngine . SyncFrames ( playListEngine . CurrentPlayListItem . Path ) ;
371
- }
372
- catch ( Exception exc )
373
- {
374
- // This is a 'backstop' to catch any nastiness from networking. The whole network blind call to
375
- // an IP thing is risky, and I've seen an instance where the try/catch in syncframes failed.
376
- // Adding this to try to catch that if it happens and to understand why. Also to not
377
- // bring down the entire app due to network flakiness.
378
- Logger . LogComment ( "ERROR: Excpetion trying to sync frames, caught in mainWindow. Excpetion: " + exc . ToString ( ) ) ;
379
- }
380
- }
381
-
382
- try
383
- {
384
- // TODO: Try to 'peek' at next file, if video, then slow down more
385
- if ( playListEngine . CurrentPlayListItem . ItemType == PlayListItemType . Video )
386
- {
387
- KillVideoPlayer ( ) ;
388
- PlayVideoFile ( playListEngine . CurrentPlayListItem . Path ) ;
389
- }
390
- else
391
- {
392
- PlayImageFile ( AppSettings . Default . FadeTransitionTime , playListEngine . CurrentPlayListItem . Path ) ;
393
- KillVideoPlayer ( ) ; // if a video is playing, get rid of it now that we've swapped images
394
- }
395
- }
396
- catch ( InvalidOperationException exc )
377
+ if ( ( AppSettings . Default . IsSyncEnabled ) & & ( SyncedFrame . SyncEngine . syncedFrames . Count > 0 ) )
397
378
{
398
- Logger . LogComment ( "IOE Exception: " + exc . ToString ( ) ) ;
399
- // We expect this if a process is no longer around
400
- }
401
- catch ( Exception exc )
402
- {
403
- Logger . LogComment ( "ERROR: Exception processing file.." + exc . ToString ( ) ) ;
379
+ SyncedFrame . SyncEngine . SyncFrames ( playListEngine . CurrentPlayListItem . Path ) ;
404
380
}
381
+ PlayFile ( playListEngine . CurrentPlayListItem . Path ) ;
405
382
}
406
383
slideTimer . Start ( ) ; // start next iterations...this prevents reentry...
407
384
408
385
}
409
386
public void PlayFile ( string path )
410
387
{
411
- // Externally exposed API to allow for frame syncing or automation scenarios.
412
- // note: The file that we try to play may not exist, if not, we should look at the folder and try to
413
- // find it, if that doesn't exist then show randome file from playlist
414
- //
415
- // Future use from Avalonia Gitter: How to load an image from network path..
416
- // var response = await httpClient.GetAsync(bitmapPath, HttpCompletionOption.ResponseContentRead);
417
- // var stream = await response.Content.ReadAsStreamAsync();
418
- // bitmap = new Bitmap(stream);
419
-
388
+ PlayFile ( path , AppSettings . Default . FadeTransitionTime ) ;
389
+ }
390
+
391
+ public void PlayFile ( string path , int transitionTime )
392
+ {
393
+ Logger . LogComment ( "PlayFile() called with TransitionTime=" + transitionTime + " and path: " + path ) ;
420
394
PlayListItemType type = PlayListEngineHelper . GetPlayListItemTypeFromPath ( path ) ;
395
+ VideoPlayer . KillVideoPlayer ( ) ; // Kill this...if this is called from gotonext / gotoprevious it can cause bad effects.
421
396
try
422
397
{
423
398
// TODO: Try to 'peek' at next file, if video, then slow down more
424
399
if ( type == PlayListItemType . Video )
425
400
{
426
- KillVideoPlayer ( ) ;
427
- PlayVideoFile ( path ) ;
401
+ VideoPlayer . PlayVideo ( path ) ;
428
402
}
429
403
else
430
404
{
431
- PlayImageFile ( AppSettings . Default . FadeTransitionTime , path ) ;
432
- KillVideoPlayer ( ) ; // if a video is playing, get rid of it now that we've swapped images
405
+ crossFadeTransition . SetImage ( path , AppSettings . Default . FadeTransitionTime ) ;
433
406
}
407
+ Logger . LogComment ( "Media is now set." ) ;
434
408
}
435
409
catch ( InvalidOperationException )
436
410
{
@@ -442,6 +416,8 @@ public void PlayFile(string path)
442
416
}
443
417
444
418
}
419
+
420
+
445
421
private void UpdateInfoBar ( )
446
422
{
447
423
Avalonia . Threading . Dispatcher . UIThread . InvokeAsync ( ( ) =>
@@ -504,131 +480,7 @@ private void UpdateInfoBar()
504
480
} // end if
505
481
} ) ;
506
482
}
507
- public void PlayImageFile ( int millisecondsDelay , string path )
508
- {
509
- Logger . LogComment ( "PlayImageFile() called with Delay=" + millisecondsDelay + " and path: " + path ) ;
510
- crossFadeTransition . SetImage ( path , AppSettings . Default . FadeTransitionTime ) ;
511
- Logger . LogComment ( "PlayImageFile: New Image now set" ) ;
512
- }
513
- private void PlayVideoFile ( string path )
514
- {
515
- Logger . LogComment ( "Entering PlayVideoFile with Path: " + path ) ;
516
- ProcessStartInfo pInfo = new ProcessStartInfo ( ) ;
517
- pInfo . WindowStyle = ProcessWindowStyle . Maximized ;
518
-
519
- // TODO: Parameterize omxplayer settings
520
- if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
521
- {
522
- Logger . LogComment ( "Linux Detected, setting up OMX Player" ) ;
523
- pInfo . FileName = "omxplayer" ;
524
- Logger . LogComment ( "Setting up Appsettings..." ) ;
525
- pInfo . Arguments = AppSettings . Default . OXMOrientnation + " --aspect-mode " + AppSettings . Default . VideoStretch + " " ;
526
-
527
- // Append volume command argument
528
- if ( ! AppSettings . Default . VideoVolume )
529
- {
530
- pInfo . Arguments += "--vol -6000 " ;
531
- }
532
-
533
- pInfo . Arguments += "\" " + path + "\" " ;
534
- Logger . LogComment ( "DF Playing: " + path ) ;
535
- Logger . LogComment ( "OMXPLayer args: " + pInfo . Arguments ) ;
536
- }
537
- else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
538
- {
539
- pInfo . UseShellExecute = true ;
540
- pInfo . FileName = "wmplayer.exe" ;
541
- pInfo . Arguments = "\" " + path + "\" " ;
542
- pInfo . Arguments += " /fullscreen" ;
543
- Logger . LogComment ( "Looking for media in: " + pInfo . Arguments ) ;
544
- }
545
-
546
-
547
- videoProcess = new Process ( ) ;
548
- videoProcess . StartInfo = pInfo ;
549
- Logger . LogComment ( "PlayVideoFile: Starting player..." ) ;
550
- videoProcess . Start ( ) ;
551
- Avalonia . Threading . Dispatcher . UIThread . InvokeAsync ( ( ) =>
552
- {
553
- mainPanel . Opacity = 0 ;
554
- } ) ;
555
-
556
- // Give video player time to start, then fade out to reveal it...
557
- System . Threading . Thread . Sleep ( 1100 ) ;
558
- Logger . LogComment ( "PlayVideoFile: Fading Foreground to reveal video player." ) ;
559
- Avalonia . Threading . Dispatcher . UIThread . InvokeAsync ( ( ) =>
560
- {
561
- mainWindow . Opacity = 0 ;
562
- } ) ;
563
-
564
- int timer = 0 ;
565
- Logger . LogComment ( "PlayVideoFile: Entering Timerloop" ) ;
566
- while ( ( videoProcess != null ) && ( ! videoProcess . HasExited ) )
567
- {
568
- timer += 1 ;
569
- System . Threading . Thread . Sleep ( 300 ) ;
570
- if ( timer > 400 )
571
- {
572
- // timeout to not 'hang'
573
- // TODO: Add a setting for this
574
- break ;
575
- }
576
-
577
- }
578
- Logger . LogComment ( "PlayVideoFile: Video has exited!" ) ;
579
- Avalonia . Threading . Dispatcher . UIThread . InvokeAsync ( ( ) =>
580
- {
581
- mainPanel . Opacity = 1 ;
582
- mainWindow . Opacity = 1 ;
583
- } ) ;
584
- }
585
-
586
- private void KillVideoPlayer ( )
587
- {
588
- Logger . LogComment ( "KillVideoPlayer - Entering Method." ) ;
589
- try
590
- {
591
- if ( videoProcess != null )
592
- {
593
- try
594
- {
595
- videoProcess . CloseMainWindow ( ) ;
596
- videoProcess = null ;
597
- }
598
- catch ( InvalidOperationException )
599
- {
600
- // expected if the process isn't there.
601
- }
602
- catch ( Exception exc )
603
- {
604
- Debug . WriteLine ( "Tried and failed to kill video process..." + exc . ToString ( ) ) ;
605
- Logger . LogComment ( "Tried and failed to kill video process. Exception: " + exc . ToString ( ) ) ;
606
- }
607
- }
608
-
609
- if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
610
- {
611
- // OMXPlayer processes can be a bit tricky. to kill them we use
612
- // killall - 9 omxplayer.bin
613
- // -q quiets this down in case omxplayer isn't running
614
483
615
- Helpers . RunProcess ( "killall" , "-q -9 omxplayer.bin" ) ;
616
- videoProcess = null ;
617
-
618
- }
619
- else
620
- {
621
- videoProcess . Close ( ) ;
622
- videoProcess . Dispose ( ) ;
623
- videoProcess = null ;
624
- }
625
- }
626
- catch ( Exception )
627
- {
628
- // Swallow. This may no longer be there depending on what kills it (OMX player will exit if the video
629
- // completes for instance
630
- }
631
- }
632
484
633
485
public void SetupWebServer ( )
634
486
{
0 commit comments