fc0f27d77ce0f9d1842fda2255a4d7067581b7b3
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / controls / video-view / video-view-impl.cpp
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "video-view-impl.h"
20
21 // EXTERNAL INCLUDES
22 #include <cstring>
23 #include <dali/public-api/object/type-registry.h>
24 #include <dali/public-api/object/type-registry-helper.h>
25 #include <dali/public-api/common/stage.h>
26 #include <dali/devel-api/scripting/scripting.h>
27 #include <dali/public-api/adaptor-framework/native-image-source.h>
28 #include <dali/integration-api/adaptors/adaptor.h>
29
30 // INTERNAL INCLUDES
31 #include <dali-toolkit/public-api/controls/video-view/video-view.h>
32 #include <dali-toolkit/public-api/visuals/visual-properties.h>
33 #include <dali-toolkit/devel-api/visual-factory/visual-factory.h>
34 #include <dali-toolkit/internal/visuals/visual-string-constants.h>
35 #include <dali-toolkit/internal/visuals/visual-base-impl.h>
36 #include <dali-toolkit/internal/visuals/visual-factory-impl.h>
37
38 namespace Dali
39 {
40
41 namespace Toolkit
42 {
43
44 namespace Internal
45 {
46
47 namespace
48 {
49
50 BaseHandle Create()
51 {
52   return Toolkit::VideoView::New();
53 }
54
55 DALI_TYPE_REGISTRATION_BEGIN( Toolkit::VideoView, Toolkit::Control, Create );
56
57 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "video", MAP, VIDEO )
58 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "looping", BOOLEAN, LOOPING )
59 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "muted", BOOLEAN, MUTED )
60 DALI_PROPERTY_REGISTRATION( Toolkit, VideoView, "volume", MAP, VOLUME )
61
62 DALI_SIGNAL_REGISTRATION( Toolkit, VideoView, "finished", FINISHED_SIGNAL )
63
64 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "play", ACTION_VIDEOVIEW_PLAY )
65 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "pause", ACTION_VIDEOVIEW_PAUSE )
66 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "stop", ACTION_VIDEOVIEW_STOP )
67 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "forward", ACTION_VIDEOVIEW_FORWARD )
68 DALI_ACTION_REGISTRATION( Toolkit, VideoView, "backward", ACTION_VIDEOVIEW_BACKWARD )
69
70 DALI_TYPE_REGISTRATION_END()
71
72 const char* const VOLUME_LEFT( "volumeLeft" );
73 const char* const VOLUME_RIGHT( "volumeRight" );
74 const char* const RENDERING_TARGET( "renderingTarget" );
75 const char* const WINDOW_SURFACE_TARGET( "windowSurfaceTarget" );
76 const char* const NATIVE_IMAGE_TARGET( "nativeImageTarget" );
77
78 } // anonymous namepsace
79
80 VideoView::VideoView()
81 : Control( ControlBehaviour( ACTOR_BEHAVIOUR_DEFAULT | DISABLE_STYLE_CHANGE_SIGNALS ) ),
82   mCurrentVideoPlayPosition( 0 ),
83   mIsNativeImageTarget( true ),
84   mIsPlay( false ),
85   mIsPause( false )
86 {
87   mVideoPlayer = Dali::VideoPlayer::New();
88 }
89
90 VideoView::~VideoView()
91 {
92 }
93
94 Toolkit::VideoView VideoView::New()
95 {
96   VideoView* impl = new VideoView();
97   Toolkit::VideoView handle = Toolkit::VideoView( *impl );
98
99   impl->Initialize();
100
101   return handle;
102 }
103
104 void VideoView::OnInitialize()
105 {
106   Any source;
107   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
108   mNativeImage = Dali::NativeImage::New( *nativeImageSourcePtr );
109
110   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
111   mVideoPlayer.FinishedSignal().Connect( this, &VideoView::EmitSignalFinish );
112 }
113
114 void VideoView::SetUrl( const std::string& url )
115 {
116   if( mUrl != url || !mPropertyMap.Empty() )
117   {
118     mUrl = url;
119     mPropertyMap.Clear();
120   }
121
122   if( mIsNativeImageTarget )
123   {
124     Actor self( Self() );
125     Internal::InitializeVisual( self, mVisual, mNativeImage );
126   }
127
128   mVideoPlayer.SetUrl( mUrl );
129 }
130
131 void VideoView::SetPropertyMap( Property::Map map )
132 {
133   mPropertyMap = map;
134
135   Actor self( Self() );
136   Internal::InitializeVisual( self, mVisual, mPropertyMap );
137
138   Property::Value* widthValue = mPropertyMap.Find( "width" );
139   if( widthValue )
140   {
141     int width;
142     if( widthValue->Get( width ) )
143     {
144       mVideoSize = ImageDimensions( width, mVideoSize.GetHeight() );
145     }
146   }
147
148   Property::Value* heightValue = mPropertyMap.Find( "height" );
149   if( heightValue )
150   {
151     int height;
152     if( heightValue->Get( height ) )
153     {
154       mVideoSize = ImageDimensions( mVideoSize.GetWidth(), height );
155     }
156   }
157
158   Property::Value* target = map.Find( RENDERING_TARGET );
159   std::string targetType;
160
161   if( target && target->Get( targetType ) && targetType == WINDOW_SURFACE_TARGET )
162   {
163     this->SetWindowSurfaceTarget();
164   }
165   else if( target && target->Get( targetType ) && targetType == NATIVE_IMAGE_TARGET )
166   {
167     this->SetNativeImageTarget();
168   }
169
170   RelayoutRequest();
171 }
172
173 std::string VideoView::GetUrl()
174 {
175   return mUrl;
176 }
177
178 void VideoView::SetLooping(bool looping)
179 {
180   mVideoPlayer.SetLooping( looping );
181 }
182
183 bool VideoView::IsLooping()
184 {
185   return mVideoPlayer.IsLooping();
186 }
187
188 void VideoView::Play()
189 {
190   mVideoPlayer.Play();
191   mIsPlay = true;
192   mIsPause = false;
193 }
194
195 void VideoView::Pause()
196 {
197   mVideoPlayer.Pause();
198   mIsPlay = false;
199   mIsPause = true;
200 }
201
202 void VideoView::Stop()
203 {
204   mVideoPlayer.Stop();
205   mIsPlay = false;
206   mIsPause = false;
207 }
208
209 void VideoView::Forward( int millisecond )
210 {
211   int curPos = mVideoPlayer.GetPlayPosition();
212
213   int nextPos = curPos + millisecond;
214
215   mVideoPlayer.SetPlayPosition( nextPos );
216 }
217
218 void VideoView::Backward( int millisecond )
219 {
220   int curPos = mVideoPlayer.GetPlayPosition();
221
222   int nextPos = curPos - millisecond;
223   nextPos = ( nextPos < 0 )? 0: nextPos;
224
225   mVideoPlayer.SetPlayPosition( nextPos );
226 }
227
228 void VideoView::SetMute( bool mute )
229 {
230   mVideoPlayer.SetMute( mute );
231 }
232
233 bool VideoView::IsMuted()
234 {
235   return mVideoPlayer.IsMuted();
236 }
237
238 void VideoView::SetVolume( float left, float right )
239 {
240   mVideoPlayer.SetVolume( left, right );
241 }
242
243 void VideoView::GetVolume( float& left, float& right )
244 {
245   mVideoPlayer.GetVolume( left, right );
246 }
247
248 Dali::Toolkit::VideoView::VideoViewSignalType& VideoView::FinishedSignal()
249 {
250   return mFinishedSignal;
251 }
252
253 void VideoView::EmitSignalFinish()
254 {
255   if ( !mFinishedSignal.Empty() )
256   {
257     Dali::Toolkit::VideoView handle( GetOwner() );
258     mFinishedSignal.Emit( handle );
259   }
260 }
261
262 bool VideoView::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
263 {
264   bool ret = false;
265
266   Dali::BaseHandle handle( object );
267   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
268
269   if( !videoView )
270   {
271     return ret;
272   }
273
274   VideoView& impl = GetImpl( videoView );
275
276   if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PLAY ) == 0 )
277   {
278     impl.Play();
279     ret = true;
280   }
281   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_PAUSE ) == 0 )
282   {
283     impl.Pause();
284     ret = true;
285   }
286   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_STOP ) == 0 )
287   {
288     impl.Stop();
289     ret = true;
290   }
291   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_FORWARD ) == 0 )
292   {
293     int millisecond = 0;
294     if( attributes["videoForward"].Get( millisecond ) )
295     {
296       impl.Forward( millisecond );
297       ret = true;
298     }
299   }
300   else if( strcmp( actionName.c_str(), ACTION_VIDEOVIEW_BACKWARD ) == 0 )
301   {
302     int millisecond = 0;
303     if( attributes["videoBackward"].Get( millisecond ) )
304     {
305       impl.Backward( millisecond );
306       ret = true;
307     }
308   }
309
310   return ret;
311 }
312
313 bool VideoView::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
314 {
315   Dali::BaseHandle handle( object );
316
317   bool connected( true );
318   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( handle );
319
320   if( 0 == strcmp( signalName.c_str(), FINISHED_SIGNAL ) )
321   {
322     videoView.FinishedSignal().Connect( tracker, functor );
323   }
324   else
325   {
326     // signalName does not match any signal
327     connected = false;
328   }
329
330   return connected;
331 }
332
333 void VideoView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
334 {
335   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
336
337   if( videoView )
338   {
339     VideoView& impl = GetImpl( videoView );
340
341     switch( index )
342     {
343       case Toolkit::VideoView::Property::VIDEO:
344       {
345         std::string videoUrl;
346         Property::Map map;
347
348         if( value.Get( videoUrl ) )
349         {
350           impl.SetUrl( videoUrl );
351         }
352         else if( value.Get( map ) )
353         {
354           Property::Value* shaderValue = map.Find( Toolkit::Visual::Property::SHADER, CUSTOM_SHADER );
355
356           if( map.Count() > 1u || !shaderValue )
357           {
358             impl.SetPropertyMap( map );
359           }
360           else if( impl.mVisual && map.Count() == 1u && shaderValue )
361           {
362             Property::Map shaderMap;
363             if( shaderValue->Get( shaderMap ) )
364             {
365               Internal::Visual::Base& visual = Toolkit::GetImplementation( impl.mVisual );
366               visual.SetCustomShader( shaderMap );
367               if( videoView.OnStage() )
368               {
369                 visual.SetOffStage( videoView );
370                 visual.SetOnStage( videoView );
371               }
372             }
373           }
374         }
375         break;
376       }
377       case Toolkit::VideoView::Property::LOOPING:
378       {
379         bool looping;
380         if( value.Get( looping ) )
381         {
382           impl.SetLooping( looping );
383         }
384         break;
385       }
386       case Toolkit::VideoView::Property::MUTED:
387       {
388         bool mute;
389         if( value.Get( mute ) )
390         {
391           impl.SetMute( mute );
392         }
393         break;
394       }
395       case Toolkit::VideoView::Property::VOLUME:
396       {
397         Property::Map map;
398         float left, right;
399         if( value.Get( map ) )
400         {
401           Property::Value* volumeLeft = map.Find( VOLUME_LEFT );
402           Property::Value* volumeRight = map.Find( VOLUME_RIGHT );
403           if( volumeLeft && volumeLeft->Get( left ) && volumeRight && volumeRight->Get( right ) )
404           {
405             impl.SetVolume( left, right );
406           }
407         }
408         break;
409       }
410     }
411   }
412 }
413
414 Property::Value VideoView::GetProperty( BaseObject* object, Property::Index propertyIndex )
415 {
416   Property::Value value;
417   Toolkit::VideoView videoView = Toolkit::VideoView::DownCast( Dali::BaseHandle( object ) );
418
419   if( videoView )
420   {
421     VideoView& impl = GetImpl( videoView );
422
423     switch( propertyIndex )
424     {
425       case Toolkit::VideoView::Property::VIDEO:
426       {
427         if( !impl.mUrl.empty() )
428         {
429           value = impl.mUrl;
430         }
431         else if( !impl.mPropertyMap.Empty() )
432         {
433           value = impl.mPropertyMap;
434         }
435         break;
436       }
437       case Toolkit::VideoView::Property::LOOPING:
438       {
439         value = impl.IsLooping();
440         break;
441       }
442       case Toolkit::VideoView::Property::MUTED:
443       {
444         value = impl.IsMuted();
445         break;
446       }
447       case Toolkit::VideoView::Property::VOLUME:
448       {
449         Property::Map map;
450         float left, right;
451
452         impl.GetVolume( left, right );
453         map.Insert( VOLUME_LEFT, left );
454         map.Insert( VOLUME_RIGHT, right );
455         value = map;
456         break;
457       }
458     }
459   }
460
461   return value;
462 }
463
464 void VideoView::SetDepthIndex( int depthIndex )
465 {
466   if( mVisual )
467   {
468     mVisual.SetDepthIndex( depthIndex );
469   }
470 }
471
472 void VideoView::OnStageConnection( int depth )
473 {
474   if( mVisual )
475   {
476     CustomActor self = Self();
477     Toolkit::GetImplementation(mVisual).SetOnStage( self );
478   }
479
480   Control::OnStageConnection( depth );
481 }
482
483 void VideoView::OnStageDisconnection()
484 {
485   if( mVisual )
486   {
487     CustomActor self = Self();
488     Toolkit::GetImplementation(mVisual).SetOffStage( self );
489   }
490
491   Control::OnStageDisconnection();
492 }
493
494 Vector3 VideoView::GetNaturalSize()
495 {
496   Vector3 size;
497   size.x = mVideoSize.GetWidth();
498   size.y = mVideoSize.GetHeight();
499
500   if( size.x > 0 && size.y > 0 )
501   {
502     size.z = std::min( size.x, size.y );
503     return size;
504   }
505   else
506   {
507     return Control::GetNaturalSize();
508   }
509 }
510
511 float VideoView::GetHeightForWidth( float width )
512 {
513   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
514   {
515     return GetHeightForWidthBase( width );
516   }
517   else
518   {
519     return Control::GetHeightForWidthBase( width );
520   }
521 }
522
523 float VideoView::GetWidthForHeight( float height )
524 {
525   if( mVideoSize.GetWidth() > 0 && mVideoSize.GetHeight() > 0 )
526   {
527     return GetWidthForHeightBase( height );
528   }
529   else
530   {
531     return Control::GetWidthForHeightBase( height );
532   }
533 }
534
535 void VideoView::SetWindowSurfaceTarget()
536 {
537   Actor self = Self();
538   int curPos = mVideoPlayer.GetPlayPosition();
539
540   if( mVisual )
541   {
542     Toolkit::GetImplementation(mVisual).SetOffStage(self);
543     mVisual.Reset();
544   }
545
546   mVideoPlayer.SetRenderingTarget( Dali::Adaptor::Get().GetNativeWindowHandle() );
547   mVideoPlayer.SetUrl( mUrl );
548
549   mIsNativeImageTarget = false;
550
551   if( mIsPlay )
552   {
553     mVideoPlayer.Play();
554   }
555   if( mIsPause )
556   {
557     mVideoPlayer.Play();
558     mVideoPlayer.Pause();
559   }
560   mVideoPlayer.SetPlayPosition( curPos );
561 }
562
563 void VideoView::SetNativeImageTarget()
564 {
565   Actor self( Self() );
566   int curPos = mVideoPlayer.GetPlayPosition();
567
568   Any source;
569   Dali::NativeImageSourcePtr nativeImageSourcePtr = Dali::NativeImageSource::New( source );
570   mNativeImage = Dali::NativeImage::New( *nativeImageSourcePtr );
571
572   mVideoPlayer.SetRenderingTarget( nativeImageSourcePtr );
573   mVideoPlayer.SetUrl( mUrl );
574
575   Internal::InitializeVisual( self, mVisual, mNativeImage );
576   mIsNativeImageTarget = true;
577
578   if( mIsPlay )
579   {
580     mVideoPlayer.Play();
581   }
582
583   if( mIsPause )
584   {
585     mVideoPlayer.Play();
586     mVideoPlayer.Pause();
587   }
588   mVideoPlayer.SetPlayPosition( curPos );
589 }
590
591 } // namespace Internal
592
593 } // namespace Toolkit
594
595 } // namespace Dali