Merge lp:~phablet-team/media-hub/video-support into lp:media-hub
- video-support
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 28 |
Proposed branch: | lp:~phablet-team/media-hub/video-support |
Merge into: | lp:media-hub |
Prerequisite: | lp:~sergiusens/media-hub/packaging |
Diff against target: |
2005 lines (+1032/-65) 30 files modified
CMakeLists.txt (+2/-0) debian/control (+3/-0) debian/media-hub.conf (+1/-1) debian/media-hub.install (+1/-0) debian/rules (+4/-0) debian/usr.bin.media-hub-server (+98/-0) include/core/media/player.h (+15/-3) src/core/media/CMakeLists.txt (+6/-2) src/core/media/apparmor.h (+51/-0) src/core/media/engine.h (+8/-0) src/core/media/gstreamer/engine.cpp (+86/-8) src/core/media/gstreamer/engine.h (+8/-0) src/core/media/gstreamer/playbin.h (+181/-20) src/core/media/mpris/player.h (+4/-0) src/core/media/player_implementation.cpp (+64/-7) src/core/media/player_implementation.h (+4/-0) src/core/media/player_skeleton.cpp (+192/-6) src/core/media/player_skeleton.h (+10/-0) src/core/media/player_stub.cpp (+167/-3) src/core/media/player_stub.h (+9/-0) src/core/media/server/server.cpp (+28/-0) src/core/media/service.cpp (+1/-1) src/core/media/track_list_implementation.cpp (+13/-0) src/core/media/track_list_implementation.h (+1/-0) src/core/media/track_list_skeleton.cpp (+15/-3) src/core/media/track_list_skeleton.h (+2/-1) tests/acceptance-tests/service.cpp (+1/-1) tests/unit-tests/CMakeLists.txt (+15/-1) tests/unit-tests/libmedia-mock.cpp (+26/-0) tests/unit-tests/test-gstreamer-engine.cpp (+16/-8) |
To merge this branch: | bzr merge lp:~phablet-team/media-hub/video-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Ricardo Mendoza (community) | Needs Fixing | ||
Jamie Strandboge | Pending | ||
Ubuntu Phablet Team | code | Pending | |
Review via email: mp+212905@code.launchpad.net |
This proposal supersedes a proposal from 2014-03-26.
Commit message
* Merged with EOS branch from tvoss
* Added on_frame_available listener and callback
* Create a decoding session and pass it to the hybris layer
* Allow playback to work again after a client quits or dies
* Added two new properties to see if the opened media is video or audio
* Background playlist support
Description of the change
* Merged with EOS branch from tvoss
* Added on_frame_available listener and callback
* Create a decoding session and pass it to the hybris layer
* Allow playback to work again after a client quits or dies
* Added two new properties to see if the opened media is video or audio
* Background playlist support
PS Jenkins bot (ps-jenkins) wrote : | # |
- 37. By Jim Hodapp
-
Merged with Sergio's packaging changes. Added a copyright header to server.cpp. Removed any includes for decoding_service.h since it's not being used right now.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:37
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 38. By Jim Hodapp
-
Didn't mean to #include <visibility.h> in previous commit, undo that.
- 39. By Jim Hodapp
-
Enable libhyris-dev as a build-dep
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:39
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 40. By Jim Hodapp
-
Get rid of the visibility attribute.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:40
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:41
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 41. By Jim Hodapp
-
Add libproperties-
cpp-dev as a Depends: for libmedia-hub-dev - 42. By Jim Hodapp
-
Merged with upstream changes to disable all unit-tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:42
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Ricardo Mendoza (ricmm) wrote : | # |
91 +include_
99 + -lmedia
libmedia-dev ships a pkg config file for this
495 + std::cout << "IGBPWrapperHybris: " << igbp << std::endl;
496 + SurfaceTextureC
497 + std::cout << "SurfaceTexture
Those couts are probably not needed anymore, even if we are keeping a good chunk of debug info
863 + seeked_
864 + {
865 + std::cout << "value: " << value << std::endl;
866 + //dbus.
867 + });
Lets try and get rid of those ^
1166 + throw std::runtime_
Odd error message from context
- 43. By Jim Hodapp
-
Made ricmm's change recommendations and enabled the tests that still work properly.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:43
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 44. By Jim Hodapp
-
Snap to the preceeding key unit after doing a seek.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:44
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 45. By Jim Hodapp
-
Mock decoding_
service_ set_client_ death_cb so that the unittests don't crash when running on a non-target device.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:45
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 46. By Jim Hodapp
-
Enable the seeked_to signal
- 47. By Jim Hodapp
-
Merged with ricmm's EOS fix branch
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:47
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 48. By Jim Hodapp
-
Initial version of apparmor security context arbitration for open_uri. This does not yet check the trust store
- 49. By Jim Hodapp
-
Refine the apparmor arbitration a bit. Whitelist music-app explicitly until the trust store lands.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:48
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:49
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 50. By Jim Hodapp
-
Only start when dbus is started instead of preventing media-hub from being able to be stopped
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:50
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 51. By Jim Hodapp
-
Enable streaming sources to work with media-hub
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:51
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 52. By Jim Hodapp
-
Allow apps to access their own media files in /opt
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:52
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 53. By Jim Hodapp
-
Merged with jdstrand's changes to confine media-hub with apparmor
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:53
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 54. By Jim Hodapp
-
Slightly improve the get_position_
duration_ works unit test
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:54
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 55. By Jim Hodapp
-
Make sure the camer-app can play the click sound when a user captures a picture
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:55
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2014-02-14 07:19:31 +0000 | |||
3 | +++ CMakeLists.txt 2014-04-17 21:13:23 +0000 | |||
4 | @@ -25,6 +25,8 @@ | |||
5 | 25 | pkg_check_modules(DBUS dbus-1 REQUIRED) | 25 | pkg_check_modules(DBUS dbus-1 REQUIRED) |
6 | 26 | pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED) | 26 | pkg_check_modules(DBUS_CPP dbus-cpp REQUIRED) |
7 | 27 | pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED) | 27 | pkg_check_modules(PROPERTIES_CPP properties-cpp REQUIRED) |
8 | 28 | pkg_check_modules(GIO gio-2.0 REQUIRED) | ||
9 | 29 | pkg_check_modules(HYBRIS_MEDIA libmedia REQUIRED) | ||
10 | 28 | 30 | ||
11 | 29 | ##################################################################### | 31 | ##################################################################### |
12 | 30 | # Enable code coverage calculation with gcov/gcovr/lcov | 32 | # Enable code coverage calculation with gcov/gcovr/lcov |
13 | 31 | 33 | ||
14 | === modified file 'debian/control' | |||
15 | --- debian/control 2014-03-26 20:18:20 +0000 | |||
16 | +++ debian/control 2014-04-17 21:13:23 +0000 | |||
17 | @@ -5,6 +5,7 @@ | |||
18 | 5 | Build-Depends: cmake, | 5 | Build-Depends: cmake, |
19 | 6 | dbus-test-runner, | 6 | dbus-test-runner, |
20 | 7 | debhelper (>= 9), | 7 | debhelper (>= 9), |
21 | 8 | dh-apparmor, | ||
22 | 8 | doxygen, | 9 | doxygen, |
23 | 9 | gcc-4.7, | 10 | gcc-4.7, |
24 | 10 | g++-4.7, | 11 | g++-4.7, |
25 | @@ -39,6 +40,7 @@ | |||
26 | 39 | Depends: libmedia-hub-common0 (= ${binary:Version}), | 40 | Depends: libmedia-hub-common0 (= ${binary:Version}), |
27 | 40 | libmedia-hub-client0 (= ${binary:Version}), | 41 | libmedia-hub-client0 (= ${binary:Version}), |
28 | 41 | ${misc:Depends}, | 42 | ${misc:Depends}, |
29 | 43 | libproperties-cpp-dev, | ||
30 | 42 | Suggests: libmedia-hub-doc | 44 | Suggests: libmedia-hub-doc |
31 | 43 | Description: Simple and lightweight media playback service - development files | 45 | Description: Simple and lightweight media playback service - development files |
32 | 44 | Media Hub is a simple and lightweight service for media playback using | 46 | Media Hub is a simple and lightweight service for media playback using |
33 | @@ -51,6 +53,7 @@ | |||
34 | 51 | Pre-Depends: dpkg (>= 1.15.6~) | 53 | Pre-Depends: dpkg (>= 1.15.6~) |
35 | 52 | Depends: ${misc:Depends}, | 54 | Depends: ${misc:Depends}, |
36 | 53 | ${shlibs:Depends}, | 55 | ${shlibs:Depends}, |
37 | 56 | Suggests: apparmor (>= 2.8.95~2430-0ubuntu4~) | ||
38 | 54 | Description: Simple and lightweight media playback service | 57 | Description: Simple and lightweight media playback service |
39 | 55 | Media Hub is a simple and lightweight service for media playback using | 58 | Media Hub is a simple and lightweight service for media playback using |
40 | 56 | DBus. | 59 | DBus. |
41 | 57 | 60 | ||
42 | === modified file 'debian/media-hub.conf' | |||
43 | --- debian/media-hub.conf 2014-03-07 14:38:28 +0000 | |||
44 | +++ debian/media-hub.conf 2014-04-17 21:13:23 +0000 | |||
45 | @@ -1,6 +1,6 @@ | |||
46 | 1 | description "Starts the media-hub service" | 1 | description "Starts the media-hub service" |
47 | 2 | 2 | ||
49 | 3 | start on dbus | 3 | start on started dbus |
50 | 4 | stop on runlevel [06] | 4 | stop on runlevel [06] |
51 | 5 | 5 | ||
52 | 6 | exec media-hub-server | 6 | exec media-hub-server |
53 | 7 | 7 | ||
54 | === modified file 'debian/media-hub.install' | |||
55 | --- debian/media-hub.install 2014-03-06 22:51:51 +0000 | |||
56 | +++ debian/media-hub.install 2014-04-17 21:13:23 +0000 | |||
57 | @@ -1,2 +1,3 @@ | |||
58 | 1 | debian/media-hub.conf /usr/share/upstart/sessions/ | 1 | debian/media-hub.conf /usr/share/upstart/sessions/ |
59 | 2 | debian/usr.bin.media-hub-server etc/apparmor.d | ||
60 | 2 | usr/bin | 3 | usr/bin |
61 | 3 | 4 | ||
62 | === modified file 'debian/rules' | |||
63 | --- debian/rules 2014-03-07 22:49:23 +0000 | |||
64 | +++ debian/rules 2014-04-17 21:13:23 +0000 | |||
65 | @@ -14,3 +14,7 @@ | |||
66 | 14 | 14 | ||
67 | 15 | override_dh_auto_test: | 15 | override_dh_auto_test: |
68 | 16 | env -u LD_PRELOAD dh_auto_test | 16 | env -u LD_PRELOAD dh_auto_test |
69 | 17 | |||
70 | 18 | override_dh_installdeb: | ||
71 | 19 | dh_apparmor --profile-name=usr.bin.media-hub-server -pmedia-hub | ||
72 | 20 | dh_installdeb | ||
73 | 17 | 21 | ||
74 | === added file 'debian/usr.bin.media-hub-server' | |||
75 | --- debian/usr.bin.media-hub-server 1970-01-01 00:00:00 +0000 | |||
76 | +++ debian/usr.bin.media-hub-server 2014-04-17 21:13:23 +0000 | |||
77 | @@ -0,0 +1,98 @@ | |||
78 | 1 | #include <tunables/global> | ||
79 | 2 | |||
80 | 3 | /usr/bin/media-hub-server (attach_disconnected) { | ||
81 | 4 | #include <abstractions/base> | ||
82 | 5 | #include <abstractions/audio> | ||
83 | 6 | #include <abstractions/nameservice> | ||
84 | 7 | #include <abstractions/dbus-session> | ||
85 | 8 | #include <abstractions/dbus-strict> | ||
86 | 9 | #include <abstractions/user-tmp> | ||
87 | 10 | #include "/usr/share/apparmor/hardware/audio.d" | ||
88 | 11 | #include "/usr/share/apparmor/hardware/graphics.d" | ||
89 | 12 | #include "/usr/share/apparmor/hardware/video.d" | ||
90 | 13 | |||
91 | 14 | deny /dev/cpuctl/apps/tasks w, | ||
92 | 15 | deny /dev/cpuctl/apps/bg_non_interactive/tasks w, | ||
93 | 16 | |||
94 | 17 | @{PROC}/interrupts r, | ||
95 | 18 | owner @{PROC}/cmdline r, | ||
96 | 19 | owner @{PROC}/[0-9]*/auxv r, | ||
97 | 20 | owner @{PROC}/[0-9]*/fd/ r, | ||
98 | 21 | owner @{PROC}/[0-9]*/status r, | ||
99 | 22 | owner @{PROC}/[0-9]*/task/ r, | ||
100 | 23 | owner @{PROC}/[0-9]*/task/[0-9]*/ r, | ||
101 | 24 | owner @{PROC}/[0-9]*/cmdline r, | ||
102 | 25 | |||
103 | 26 | /sys/kernel/debug/tracing/trace_marker w, | ||
104 | 27 | /dev/ashmem rw, | ||
105 | 28 | |||
106 | 29 | # Explicitly deny this-- it is not needed | ||
107 | 30 | /dev/fb0 rw, | ||
108 | 31 | |||
109 | 32 | # libhybris | ||
110 | 33 | /{,var/}run/shm/hybris_shm_data rw, | ||
111 | 34 | /usr/lib/@{multiarch}/libhybris/*.so mr, | ||
112 | 35 | /{,android/}system/build.prop r, | ||
113 | 36 | # These libraries can be in any of: | ||
114 | 37 | # /vendor/lib | ||
115 | 38 | # /system/lib | ||
116 | 39 | # /system/vendor/lib | ||
117 | 40 | # /android/vendor/lib | ||
118 | 41 | # /android/system/lib | ||
119 | 42 | # /android/system/vendor/lib | ||
120 | 43 | /{,android/}vendor/lib/** r, | ||
121 | 44 | /{,android/}vendor/lib/**.so m, | ||
122 | 45 | /{,android/}system/lib/** r, | ||
123 | 46 | /{,android/}system/lib/**.so m, | ||
124 | 47 | /{,android/}system/vendor/lib/** r, | ||
125 | 48 | /{,android/}system/vendor/lib/**.so m, | ||
126 | 49 | |||
127 | 50 | # attach_disconnected path | ||
128 | 51 | /dev/socket/property_service rw, | ||
129 | 52 | |||
130 | 53 | # Android logging triggered by platform. Can safely deny | ||
131 | 54 | deny /dev/log_main w, | ||
132 | 55 | deny /dev/log_radio w, | ||
133 | 56 | deny /dev/log_events w, | ||
134 | 57 | deny /dev/log_system w, | ||
135 | 58 | |||
136 | 59 | # Allow all access to powerd for now, but we can fine-tune this if needed | ||
137 | 60 | dbus (receive, send) | ||
138 | 61 | bus=system | ||
139 | 62 | path=/com/canonical/powerd | ||
140 | 63 | interface=com.canonical.powerd, | ||
141 | 64 | |||
142 | 65 | # GStreamer binary registry - hybris pulls this in for everything now, not | ||
143 | 66 | # just audio | ||
144 | 67 | owner @{HOME}/.gstreamer*/registry.*.bin* rw, | ||
145 | 68 | owner @{HOME}/.gstreamer*/ rw, | ||
146 | 69 | owner @{HOME}/.cache/gstreamer*/registry.*.bin* rw, | ||
147 | 70 | |||
148 | 71 | /{,android/}system/etc/media_codecs.xml r, | ||
149 | 72 | /etc/wildmidi/wildmidi.cfg r, | ||
150 | 73 | |||
151 | 74 | audit deny owner /** m, | ||
152 | 75 | |||
153 | 76 | # Allow read on all directories | ||
154 | 77 | /**/ r, | ||
155 | 78 | |||
156 | 79 | # Allow read on click install directories, removable media and files in | ||
157 | 80 | # /usr/local/share. | ||
158 | 81 | /usr/share/** r, | ||
159 | 82 | /usr/local/share/** r, | ||
160 | 83 | /{media,mnt,opt,srv}/** r, | ||
161 | 84 | |||
162 | 85 | # Allow reading any files in non-hidden directories | ||
163 | 86 | owner @{HOME}/[^.]* rk, | ||
164 | 87 | owner @{HOME}/[^.]*/ rk, | ||
165 | 88 | owner @{HOME}/[^.]*/** rk, | ||
166 | 89 | |||
167 | 90 | # Allow reading files in XDG directories (ie, where apps are allowed to | ||
168 | 91 | # write) | ||
169 | 92 | owner @{HOME}/.cache/** rk, | ||
170 | 93 | owner @{HOME}/.local/share/** rk, | ||
171 | 94 | owner /{,var/}run/user/[0-9]*/** rk, | ||
172 | 95 | |||
173 | 96 | # Site-specific additions and overrides. See local/README for details. | ||
174 | 97 | #include <local/usr.bin.media-hub-server> | ||
175 | 98 | } | ||
176 | 0 | 99 | ||
177 | === modified file 'include/core/media/player.h' | |||
178 | --- include/core/media/player.h 2014-02-18 19:27:01 +0000 | |||
179 | +++ include/core/media/player.h 2014-04-17 21:13:23 +0000 | |||
180 | @@ -39,6 +39,12 @@ | |||
181 | 39 | public: | 39 | public: |
182 | 40 | typedef double PlaybackRate; | 40 | typedef double PlaybackRate; |
183 | 41 | typedef double Volume; | 41 | typedef double Volume; |
184 | 42 | typedef void* GLConsumerWrapperHybris; | ||
185 | 43 | |||
186 | 44 | /** Used to set a callback function to be called when a frame is ready to be rendered **/ | ||
187 | 45 | typedef void (*FrameAvailableCbHybris)(GLConsumerWrapperHybris wrapper, void *context); | ||
188 | 46 | typedef void (*FrameAvailableCb)(void *context); | ||
189 | 47 | typedef void (*PlaybackCompleteCb)(void *context); | ||
190 | 42 | 48 | ||
191 | 43 | struct Configuration; | 49 | struct Configuration; |
192 | 44 | 50 | ||
193 | @@ -74,6 +80,8 @@ | |||
194 | 74 | virtual std::shared_ptr<TrackList> track_list() = 0; | 80 | virtual std::shared_ptr<TrackList> track_list() = 0; |
195 | 75 | 81 | ||
196 | 76 | virtual bool open_uri(const Track::UriType& uri) = 0; | 82 | virtual bool open_uri(const Track::UriType& uri) = 0; |
197 | 83 | virtual void create_video_sink(uint32_t texture_id) = 0; | ||
198 | 84 | virtual GLConsumerWrapperHybris gl_consumer() const = 0; | ||
199 | 77 | virtual void next() = 0; | 85 | virtual void next() = 0; |
200 | 78 | virtual void previous() = 0; | 86 | virtual void previous() = 0; |
201 | 79 | virtual void play() = 0; | 87 | virtual void play() = 0; |
202 | @@ -81,11 +89,17 @@ | |||
203 | 81 | virtual void stop() = 0; | 89 | virtual void stop() = 0; |
204 | 82 | virtual void seek_to(const std::chrono::microseconds& offset) = 0; | 90 | virtual void seek_to(const std::chrono::microseconds& offset) = 0; |
205 | 83 | 91 | ||
206 | 92 | // TODO: Convert this to be a signal | ||
207 | 93 | virtual void set_frame_available_callback(FrameAvailableCb cb, void *context) = 0; | ||
208 | 94 | virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context) = 0; | ||
209 | 95 | |||
210 | 84 | virtual const core::Property<bool>& can_play() const = 0; | 96 | virtual const core::Property<bool>& can_play() const = 0; |
211 | 85 | virtual const core::Property<bool>& can_pause() const = 0; | 97 | virtual const core::Property<bool>& can_pause() const = 0; |
212 | 86 | virtual const core::Property<bool>& can_seek() const = 0; | 98 | virtual const core::Property<bool>& can_seek() const = 0; |
213 | 87 | virtual const core::Property<bool>& can_go_previous() const = 0; | 99 | virtual const core::Property<bool>& can_go_previous() const = 0; |
214 | 88 | virtual const core::Property<bool>& can_go_next() const = 0; | 100 | virtual const core::Property<bool>& can_go_next() const = 0; |
215 | 101 | virtual const core::Property<bool>& is_video_source() const = 0; | ||
216 | 102 | virtual const core::Property<bool>& is_audio_source() const = 0; | ||
217 | 89 | virtual const core::Property<PlaybackStatus>& playback_status() const = 0; | 103 | virtual const core::Property<PlaybackStatus>& playback_status() const = 0; |
218 | 90 | virtual const core::Property<LoopStatus>& loop_status() const = 0; | 104 | virtual const core::Property<LoopStatus>& loop_status() const = 0; |
219 | 91 | virtual const core::Property<PlaybackRate>& playback_rate() const = 0; | 105 | virtual const core::Property<PlaybackRate>& playback_rate() const = 0; |
220 | @@ -97,15 +111,13 @@ | |||
221 | 97 | virtual const core::Property<uint64_t>& position() const = 0; | 111 | virtual const core::Property<uint64_t>& position() const = 0; |
222 | 98 | virtual const core::Property<uint64_t>& duration() const = 0; | 112 | virtual const core::Property<uint64_t>& duration() const = 0; |
223 | 99 | 113 | ||
224 | 100 | |||
225 | 101 | virtual core::Property<LoopStatus>& loop_status() = 0; | 114 | virtual core::Property<LoopStatus>& loop_status() = 0; |
226 | 102 | virtual core::Property<PlaybackRate>& playback_rate() = 0; | 115 | virtual core::Property<PlaybackRate>& playback_rate() = 0; |
227 | 103 | virtual core::Property<bool>& is_shuffle() = 0; | 116 | virtual core::Property<bool>& is_shuffle() = 0; |
228 | 104 | virtual core::Property<Volume>& volume() = 0; | 117 | virtual core::Property<Volume>& volume() = 0; |
229 | 105 | 118 | ||
230 | 106 | |||
231 | 107 | virtual const core::Signal<uint64_t>& seeked_to() const = 0; | 119 | virtual const core::Signal<uint64_t>& seeked_to() const = 0; |
233 | 108 | 120 | virtual const core::Signal<void>& end_of_stream() const = 0; | |
234 | 109 | protected: | 121 | protected: |
235 | 110 | Player(); | 122 | Player(); |
236 | 111 | 123 | ||
237 | 112 | 124 | ||
238 | === modified file 'src/core/media/CMakeLists.txt' | |||
239 | --- src/core/media/CMakeLists.txt 2014-02-26 14:58:36 +0000 | |||
240 | +++ src/core/media/CMakeLists.txt 2014-04-17 21:13:23 +0000 | |||
241 | @@ -1,6 +1,6 @@ | |||
242 | 1 | pkg_check_modules(PC_GSTREAMER_1_0 REQUIRED gstreamer-1.0) | 1 | pkg_check_modules(PC_GSTREAMER_1_0 REQUIRED gstreamer-1.0) |
243 | 2 | 2 | ||
245 | 3 | include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS}) | 3 | include_directories(${PC_GSTREAMER_1_0_INCLUDE_DIRS} ${HYBRIS_MEDIA_CFLAGS}) |
246 | 4 | 4 | ||
247 | 5 | add_library( | 5 | add_library( |
248 | 6 | media-hub-common SHARED | 6 | media-hub-common SHARED |
249 | @@ -52,6 +52,7 @@ | |||
250 | 52 | ${DBUS_LIBRARIES} | 52 | ${DBUS_LIBRARIES} |
251 | 53 | ${DBUS_CPP_LDFLAGS} | 53 | ${DBUS_CPP_LDFLAGS} |
252 | 54 | ${GLog_LIBRARY} | 54 | ${GLog_LIBRARY} |
253 | 55 | ${HYBRIS_MEDIA_LIBRARIES} | ||
254 | 55 | ) | 56 | ) |
255 | 56 | 57 | ||
256 | 57 | install( | 58 | install( |
257 | @@ -82,9 +83,11 @@ | |||
258 | 82 | ${DBUS_CPP_LDFLAGS} | 83 | ${DBUS_CPP_LDFLAGS} |
259 | 83 | ${GLog_LIBRARY} | 84 | ${GLog_LIBRARY} |
260 | 84 | ${PC_GSTREAMER_1_0_LIBRARIES} | 85 | ${PC_GSTREAMER_1_0_LIBRARIES} |
261 | 86 | ${GIO_LIBRARIES} | ||
262 | 87 | ${HYBRIS_MEDIA_LIBRARIES} | ||
263 | 85 | ) | 88 | ) |
264 | 86 | 89 | ||
266 | 87 | include_directories(${PROJECT_SOURCE_DIR}/src/) | 90 | include_directories(${PROJECT_SOURCE_DIR}/src/ ${HYBRIS_MEDIA_CFLAGS}) |
267 | 88 | 91 | ||
268 | 89 | add_executable( | 92 | add_executable( |
269 | 90 | media-hub-server | 93 | media-hub-server |
270 | @@ -102,6 +105,7 @@ | |||
271 | 102 | ${DBUS_CPP_LDFLAGS} | 105 | ${DBUS_CPP_LDFLAGS} |
272 | 103 | ${GLog_LIBRARY} | 106 | ${GLog_LIBRARY} |
273 | 104 | ${PC_GSTREAMER_1_0_LIBRARIES} | 107 | ${PC_GSTREAMER_1_0_LIBRARIES} |
274 | 108 | ${HYBRIS_MEDIA_LIBRARIES} | ||
275 | 105 | ) | 109 | ) |
276 | 106 | 110 | ||
277 | 107 | install( | 111 | install( |
278 | 108 | 112 | ||
279 | === added file 'src/core/media/apparmor.h' | |||
280 | --- src/core/media/apparmor.h 1970-01-01 00:00:00 +0000 | |||
281 | +++ src/core/media/apparmor.h 2014-04-17 21:13:23 +0000 | |||
282 | @@ -0,0 +1,51 @@ | |||
283 | 1 | /* | ||
284 | 2 | * Copyright (C) 2013-2014 Canonical Ltd | ||
285 | 3 | * | ||
286 | 4 | * This program is free software: you can redistribute it and/or modify | ||
287 | 5 | * it under the terms of the GNU Lesser General Public License version 3 as | ||
288 | 6 | * published by the Free Software Foundation. | ||
289 | 7 | * | ||
290 | 8 | * This program is distributed in the hope that it will be useful, | ||
291 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
292 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
293 | 11 | * GNU Lesser General Public License for more details. | ||
294 | 12 | * | ||
295 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
296 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
297 | 15 | * | ||
298 | 16 | * Author: Ricardo Mendoza <ricardo.mendoza@canonical.com> | ||
299 | 17 | */ | ||
300 | 18 | |||
301 | 19 | #ifndef APPARMOR_H_DBUS_ | ||
302 | 20 | #define APPARMOR_H_DBUS_ | ||
303 | 21 | |||
304 | 22 | #include <string> | ||
305 | 23 | #include <chrono> | ||
306 | 24 | |||
307 | 25 | namespace core | ||
308 | 26 | { | ||
309 | 27 | |||
310 | 28 | struct Apparmor | ||
311 | 29 | { | ||
312 | 30 | static std::string& name() | ||
313 | 31 | { | ||
314 | 32 | static std::string s = "org.freedesktop.DBus"; | ||
315 | 33 | return s; | ||
316 | 34 | } | ||
317 | 35 | |||
318 | 36 | struct getConnectionAppArmorSecurityContext | ||
319 | 37 | { | ||
320 | 38 | static std::string name() | ||
321 | 39 | { | ||
322 | 40 | static std::string s = "GetConnectionAppArmorSecurityContext"; | ||
323 | 41 | return s; | ||
324 | 42 | } | ||
325 | 43 | |||
326 | 44 | static const std::chrono::milliseconds default_timeout() { return std::chrono::seconds{1}; } | ||
327 | 45 | |||
328 | 46 | typedef Apparmor Interface; | ||
329 | 47 | }; | ||
330 | 48 | }; | ||
331 | 49 | } | ||
332 | 50 | |||
333 | 51 | #endif | ||
334 | 0 | 52 | ||
335 | === modified file 'src/core/media/engine.h' | |||
336 | --- src/core/media/engine.h 2014-02-18 19:27:01 +0000 | |||
337 | +++ src/core/media/engine.h 2014-04-17 21:13:23 +0000 | |||
338 | @@ -97,12 +97,16 @@ | |||
339 | 97 | virtual const core::Property<State>& state() const = 0; | 97 | virtual const core::Property<State>& state() const = 0; |
340 | 98 | 98 | ||
341 | 99 | virtual bool open_resource_for_uri(const Track::UriType& uri) = 0; | 99 | virtual bool open_resource_for_uri(const Track::UriType& uri) = 0; |
342 | 100 | virtual void create_video_sink(uint32_t texture_id) = 0; | ||
343 | 100 | 101 | ||
344 | 101 | virtual bool play() = 0; | 102 | virtual bool play() = 0; |
345 | 102 | virtual bool stop() = 0; | 103 | virtual bool stop() = 0; |
346 | 103 | virtual bool pause() = 0; | 104 | virtual bool pause() = 0; |
347 | 104 | virtual bool seek_to(const std::chrono::microseconds& ts) = 0; | 105 | virtual bool seek_to(const std::chrono::microseconds& ts) = 0; |
348 | 105 | 106 | ||
349 | 107 | virtual const core::Property<bool>& is_video_source() const = 0; | ||
350 | 108 | virtual const core::Property<bool>& is_audio_source() const = 0; | ||
351 | 109 | |||
352 | 106 | virtual const core::Property<uint64_t>& position() const = 0; | 110 | virtual const core::Property<uint64_t>& position() const = 0; |
353 | 107 | virtual const core::Property<uint64_t>& duration() const = 0; | 111 | virtual const core::Property<uint64_t>& duration() const = 0; |
354 | 108 | 112 | ||
355 | @@ -110,6 +114,10 @@ | |||
356 | 110 | virtual core::Property<Volume>& volume() = 0; | 114 | virtual core::Property<Volume>& volume() = 0; |
357 | 111 | 115 | ||
358 | 112 | virtual const core::Property<std::tuple<Track::UriType, Track::MetaData>>& track_meta_data() const = 0; | 116 | virtual const core::Property<std::tuple<Track::UriType, Track::MetaData>>& track_meta_data() const = 0; |
359 | 117 | |||
360 | 118 | virtual const core::Signal<void>& about_to_finish_signal() const = 0; | ||
361 | 119 | virtual const core::Signal<uint64_t>& seeked_to_signal() const = 0; | ||
362 | 120 | virtual const core::Signal<void>& end_of_stream_signal() const = 0; | ||
363 | 113 | }; | 121 | }; |
364 | 114 | } | 122 | } |
365 | 115 | } | 123 | } |
366 | 116 | 124 | ||
367 | === modified file 'src/core/media/gstreamer/engine.cpp' | |||
368 | --- src/core/media/gstreamer/engine.cpp 2014-02-20 19:05:17 +0000 | |||
369 | +++ src/core/media/gstreamer/engine.cpp 2014-04-17 21:13:23 +0000 | |||
370 | @@ -16,6 +16,9 @@ | |||
371 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> |
372 | 17 | */ | 17 | */ |
373 | 18 | 18 | ||
374 | 19 | #include <stdio.h> | ||
375 | 20 | #include <stdlib.h> | ||
376 | 21 | |||
377 | 19 | #include "bus.h" | 22 | #include "bus.h" |
378 | 20 | #include "engine.h" | 23 | #include "engine.h" |
379 | 21 | #include "meta_data_extractor.h" | 24 | #include "meta_data_extractor.h" |
380 | @@ -43,14 +46,10 @@ | |||
381 | 43 | 46 | ||
382 | 44 | struct gstreamer::Engine::Private | 47 | struct gstreamer::Engine::Private |
383 | 45 | { | 48 | { |
384 | 46 | void about_to_finish() | ||
385 | 47 | { | ||
386 | 48 | state = Engine::State::ready; | ||
387 | 49 | } | ||
388 | 50 | |||
389 | 51 | void on_playbin_state_changed( | 49 | void on_playbin_state_changed( |
391 | 52 | const gstreamer::Bus::Message::Detail::StateChanged&) | 50 | const gstreamer::Bus::Message::Detail::StateChanged& state_change) |
392 | 53 | { | 51 | { |
393 | 52 | (void) state_change; | ||
394 | 54 | } | 53 | } |
395 | 55 | 54 | ||
396 | 56 | void on_tag_available(const gstreamer::Bus::Message::Detail::Tag& tag) | 55 | void on_tag_available(const gstreamer::Bus::Message::Detail::Tag& tag) |
397 | @@ -163,13 +162,31 @@ | |||
398 | 163 | playbin.set_volume(new_volume.value); | 162 | playbin.set_volume(new_volume.value); |
399 | 164 | } | 163 | } |
400 | 165 | 164 | ||
401 | 165 | void on_about_to_finish() | ||
402 | 166 | { | ||
403 | 167 | state = Engine::State::ready; | ||
404 | 168 | about_to_finish(); | ||
405 | 169 | } | ||
406 | 170 | |||
407 | 171 | void on_seeked_to(uint64_t value) | ||
408 | 172 | { | ||
409 | 173 | seeked_to(value); | ||
410 | 174 | } | ||
411 | 175 | |||
412 | 176 | void on_end_of_stream() | ||
413 | 177 | { | ||
414 | 178 | end_of_stream(); | ||
415 | 179 | } | ||
416 | 180 | |||
417 | 166 | Private() | 181 | Private() |
418 | 167 | : meta_data_extractor(new gstreamer::MetaDataExtractor()), | 182 | : meta_data_extractor(new gstreamer::MetaDataExtractor()), |
419 | 168 | volume(media::Engine::Volume(1.)), | 183 | volume(media::Engine::Volume(1.)), |
420 | 184 | is_video_source(false), | ||
421 | 185 | is_audio_source(false), | ||
422 | 169 | about_to_finish_connection( | 186 | about_to_finish_connection( |
423 | 170 | playbin.signals.about_to_finish.connect( | 187 | playbin.signals.about_to_finish.connect( |
424 | 171 | std::bind( | 188 | std::bind( |
426 | 172 | &Private::about_to_finish, | 189 | &Private::on_about_to_finish, |
427 | 173 | this))), | 190 | this))), |
428 | 174 | on_state_changed_connection( | 191 | on_state_changed_connection( |
429 | 175 | playbin.signals.on_state_changed.connect( | 192 | playbin.signals.on_state_changed.connect( |
430 | @@ -188,7 +205,18 @@ | |||
431 | 188 | std::bind( | 205 | std::bind( |
432 | 189 | &Private::on_volume_changed, | 206 | &Private::on_volume_changed, |
433 | 190 | this, | 207 | this, |
435 | 191 | std::placeholders::_1))) | 208 | std::placeholders::_1))), |
436 | 209 | on_seeked_to_connection( | ||
437 | 210 | playbin.signals.on_seeked_to.connect( | ||
438 | 211 | std::bind( | ||
439 | 212 | &Private::on_seeked_to, | ||
440 | 213 | this, | ||
441 | 214 | std::placeholders::_1))), | ||
442 | 215 | on_end_of_stream_connection( | ||
443 | 216 | playbin.signals.on_end_of_stream.connect( | ||
444 | 217 | std::bind( | ||
445 | 218 | &Private::on_end_of_stream, | ||
446 | 219 | this))) | ||
447 | 192 | { | 220 | { |
448 | 193 | } | 221 | } |
449 | 194 | 222 | ||
450 | @@ -198,11 +226,19 @@ | |||
451 | 198 | core::Property<uint64_t> position; | 226 | core::Property<uint64_t> position; |
452 | 199 | core::Property<uint64_t> duration; | 227 | core::Property<uint64_t> duration; |
453 | 200 | core::Property<media::Engine::Volume> volume; | 228 | core::Property<media::Engine::Volume> volume; |
454 | 229 | core::Property<bool> is_video_source; | ||
455 | 230 | core::Property<bool> is_audio_source; | ||
456 | 201 | gstreamer::Playbin playbin; | 231 | gstreamer::Playbin playbin; |
457 | 202 | core::ScopedConnection about_to_finish_connection; | 232 | core::ScopedConnection about_to_finish_connection; |
458 | 203 | core::ScopedConnection on_state_changed_connection; | 233 | core::ScopedConnection on_state_changed_connection; |
459 | 204 | core::ScopedConnection on_tag_available_connection; | 234 | core::ScopedConnection on_tag_available_connection; |
460 | 205 | core::ScopedConnection on_volume_changed_connection; | 235 | core::ScopedConnection on_volume_changed_connection; |
461 | 236 | core::ScopedConnection on_seeked_to_connection; | ||
462 | 237 | core::ScopedConnection on_end_of_stream_connection; | ||
463 | 238 | |||
464 | 239 | core::Signal<void> about_to_finish; | ||
465 | 240 | core::Signal<uint64_t> seeked_to; | ||
466 | 241 | core::Signal<void> end_of_stream; | ||
467 | 206 | }; | 242 | }; |
468 | 207 | 243 | ||
469 | 208 | gstreamer::Engine::Engine() : d(new Private{}) | 244 | gstreamer::Engine::Engine() : d(new Private{}) |
470 | @@ -231,6 +267,11 @@ | |||
471 | 231 | return true; | 267 | return true; |
472 | 232 | } | 268 | } |
473 | 233 | 269 | ||
474 | 270 | void gstreamer::Engine::create_video_sink(uint32_t texture_id) | ||
475 | 271 | { | ||
476 | 272 | d->playbin.create_video_sink(texture_id); | ||
477 | 273 | } | ||
478 | 274 | |||
479 | 234 | bool gstreamer::Engine::play() | 275 | bool gstreamer::Engine::play() |
480 | 235 | { | 276 | { |
481 | 236 | auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING); | 277 | auto result = d->playbin.set_state_and_wait(GST_STATE_PLAYING); |
482 | @@ -268,6 +309,28 @@ | |||
483 | 268 | return d->playbin.seek(ts); | 309 | return d->playbin.seek(ts); |
484 | 269 | } | 310 | } |
485 | 270 | 311 | ||
486 | 312 | const core::Property<bool>& gstreamer::Engine::is_video_source() const | ||
487 | 313 | { | ||
488 | 314 | gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type(); | ||
489 | 315 | if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_VIDEO) | ||
490 | 316 | d->is_video_source.set(true); | ||
491 | 317 | else | ||
492 | 318 | d->is_video_source.set(false); | ||
493 | 319 | |||
494 | 320 | return d->is_video_source; | ||
495 | 321 | } | ||
496 | 322 | |||
497 | 323 | const core::Property<bool>& gstreamer::Engine::is_audio_source() const | ||
498 | 324 | { | ||
499 | 325 | gstreamer::Playbin::MediaFileType type = d->playbin.media_file_type(); | ||
500 | 326 | if (type == gstreamer::Playbin::MediaFileType::MEDIA_FILE_TYPE_AUDIO) | ||
501 | 327 | d->is_audio_source.set(true); | ||
502 | 328 | else | ||
503 | 329 | d->is_audio_source.set(false); | ||
504 | 330 | |||
505 | 331 | return d->is_audio_source; | ||
506 | 332 | } | ||
507 | 333 | |||
508 | 271 | const core::Property<uint64_t>& gstreamer::Engine::position() const | 334 | const core::Property<uint64_t>& gstreamer::Engine::position() const |
509 | 272 | { | 335 | { |
510 | 273 | d->position.set(d->playbin.position()); | 336 | d->position.set(d->playbin.position()); |
511 | @@ -295,3 +358,18 @@ | |||
512 | 295 | { | 358 | { |
513 | 296 | return d->track_meta_data; | 359 | return d->track_meta_data; |
514 | 297 | } | 360 | } |
515 | 361 | |||
516 | 362 | const core::Signal<void>& gstreamer::Engine::about_to_finish_signal() const | ||
517 | 363 | { | ||
518 | 364 | return d->about_to_finish; | ||
519 | 365 | } | ||
520 | 366 | |||
521 | 367 | const core::Signal<uint64_t>& gstreamer::Engine::seeked_to_signal() const | ||
522 | 368 | { | ||
523 | 369 | return d->seeked_to; | ||
524 | 370 | } | ||
525 | 371 | |||
526 | 372 | const core::Signal<void>& gstreamer::Engine::end_of_stream_signal() const | ||
527 | 373 | { | ||
528 | 374 | return d->end_of_stream; | ||
529 | 375 | } | ||
530 | 298 | 376 | ||
531 | === modified file 'src/core/media/gstreamer/engine.h' | |||
532 | --- src/core/media/gstreamer/engine.h 2014-02-18 19:27:01 +0000 | |||
533 | +++ src/core/media/gstreamer/engine.h 2014-04-17 21:13:23 +0000 | |||
534 | @@ -33,12 +33,16 @@ | |||
535 | 33 | const core::Property<State>& state() const; | 33 | const core::Property<State>& state() const; |
536 | 34 | 34 | ||
537 | 35 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri); | 35 | bool open_resource_for_uri(const core::ubuntu::media::Track::UriType& uri); |
538 | 36 | void create_video_sink(uint32_t texture_id); | ||
539 | 36 | 37 | ||
540 | 37 | bool play(); | 38 | bool play(); |
541 | 38 | bool stop(); | 39 | bool stop(); |
542 | 39 | bool pause(); | 40 | bool pause(); |
543 | 40 | bool seek_to(const std::chrono::microseconds& ts); | 41 | bool seek_to(const std::chrono::microseconds& ts); |
544 | 41 | 42 | ||
545 | 43 | const core::Property<bool>& is_video_source() const; | ||
546 | 44 | const core::Property<bool>& is_audio_source() const; | ||
547 | 45 | |||
548 | 42 | const core::Property<uint64_t>& position() const; | 46 | const core::Property<uint64_t>& position() const; |
549 | 43 | const core::Property<uint64_t>& duration() const; | 47 | const core::Property<uint64_t>& duration() const; |
550 | 44 | 48 | ||
551 | @@ -47,6 +51,10 @@ | |||
552 | 47 | 51 | ||
553 | 48 | const core::Property<std::tuple<core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData>>& track_meta_data() const; | 52 | const core::Property<std::tuple<core::ubuntu::media::Track::UriType, core::ubuntu::media::Track::MetaData>>& track_meta_data() const; |
554 | 49 | 53 | ||
555 | 54 | const core::Signal<void>& about_to_finish_signal() const; | ||
556 | 55 | const core::Signal<uint64_t>& seeked_to_signal() const; | ||
557 | 56 | const core::Signal<void>& end_of_stream_signal() const; | ||
558 | 57 | |||
559 | 50 | private: | 58 | private: |
560 | 51 | struct Private; | 59 | struct Private; |
561 | 52 | std::unique_ptr<Private> d; | 60 | std::unique_ptr<Private> d; |
562 | 53 | 61 | ||
563 | === modified file 'src/core/media/gstreamer/playbin.h' | |||
564 | --- src/core/media/gstreamer/playbin.h 2014-02-20 19:05:17 +0000 | |||
565 | +++ src/core/media/gstreamer/playbin.h 2014-04-17 21:13:23 +0000 | |||
566 | @@ -21,6 +21,10 @@ | |||
567 | 21 | 21 | ||
568 | 22 | #include "bus.h" | 22 | #include "bus.h" |
569 | 23 | 23 | ||
570 | 24 | #include <hybris/media/media_codec_layer.h> | ||
571 | 25 | #include <hybris/media/surface_texture_client_hybris.h> | ||
572 | 26 | |||
573 | 27 | #include <gio/gio.h> | ||
574 | 24 | #include <gst/gst.h> | 28 | #include <gst/gst.h> |
575 | 25 | 29 | ||
576 | 26 | #include <chrono> | 30 | #include <chrono> |
577 | @@ -37,6 +41,13 @@ | |||
578 | 37 | GST_PLAY_FLAG_TEXT = (1 << 2) | 41 | GST_PLAY_FLAG_TEXT = (1 << 2) |
579 | 38 | }; | 42 | }; |
580 | 39 | 43 | ||
581 | 44 | enum MediaFileType | ||
582 | 45 | { | ||
583 | 46 | MEDIA_FILE_TYPE_NONE, | ||
584 | 47 | MEDIA_FILE_TYPE_AUDIO, | ||
585 | 48 | MEDIA_FILE_TYPE_VIDEO | ||
586 | 49 | }; | ||
587 | 50 | |||
588 | 40 | static const std::string& pipeline_name() | 51 | static const std::string& pipeline_name() |
589 | 41 | { | 52 | { |
590 | 42 | static const std::string s{"playbin"}; | 53 | static const std::string s{"playbin"}; |
591 | @@ -45,20 +56,22 @@ | |||
592 | 45 | 56 | ||
593 | 46 | static void about_to_finish(GstElement*, | 57 | static void about_to_finish(GstElement*, |
594 | 47 | gpointer user_data) | 58 | gpointer user_data) |
597 | 48 | { auto thiz = static_cast<Playbin*>(user_data); | 59 | { |
598 | 49 | 60 | auto thiz = static_cast<Playbin*>(user_data); | |
599 | 50 | thiz->signals.about_to_finish(); | 61 | thiz->signals.about_to_finish(); |
600 | 51 | } | 62 | } |
601 | 52 | 63 | ||
602 | 53 | Playbin() | 64 | Playbin() |
603 | 54 | : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())), | 65 | : pipeline(gst_element_factory_make("playbin", pipeline_name().c_str())), |
604 | 55 | bus{gst_element_get_bus(pipeline)}, | 66 | bus{gst_element_get_bus(pipeline)}, |
605 | 67 | file_type(MEDIA_FILE_TYPE_NONE), | ||
606 | 56 | on_new_message_connection( | 68 | on_new_message_connection( |
607 | 57 | bus.on_new_message.connect( | 69 | bus.on_new_message.connect( |
608 | 58 | std::bind( | 70 | std::bind( |
609 | 59 | &Playbin::on_new_message, | 71 | &Playbin::on_new_message, |
610 | 60 | this, | 72 | this, |
612 | 61 | std::placeholders::_1))) | 73 | std::placeholders::_1))), |
613 | 74 | is_seeking(false) | ||
614 | 62 | { | 75 | { |
615 | 63 | if (!pipeline) | 76 | if (!pipeline) |
616 | 64 | throw std::runtime_error("Could not create pipeline for playbin."); | 77 | throw std::runtime_error("Could not create pipeline for playbin."); |
617 | @@ -74,6 +87,8 @@ | |||
618 | 74 | this | 87 | this |
619 | 75 | ); | 88 | ); |
620 | 76 | 89 | ||
621 | 90 | // When a client of media-hub dies, call on_client_died | ||
622 | 91 | decoding_service_set_client_death_cb(&Playbin::on_client_died_cb, static_cast<void*>(this)); | ||
623 | 77 | } | 92 | } |
624 | 78 | 93 | ||
625 | 79 | ~Playbin() | 94 | ~Playbin() |
626 | @@ -82,6 +97,43 @@ | |||
627 | 82 | gst_object_unref(pipeline); | 97 | gst_object_unref(pipeline); |
628 | 83 | } | 98 | } |
629 | 84 | 99 | ||
630 | 100 | static void on_client_died_cb(void *context) | ||
631 | 101 | { | ||
632 | 102 | if (context) | ||
633 | 103 | { | ||
634 | 104 | Playbin *pb = static_cast<Playbin*>(context); | ||
635 | 105 | pb->on_client_died(); | ||
636 | 106 | } | ||
637 | 107 | } | ||
638 | 108 | |||
639 | 109 | void on_client_died() | ||
640 | 110 | { | ||
641 | 111 | std::cout << "Client died, resetting pipeline" << std::endl; | ||
642 | 112 | // When the client dies, tear down the current pipeline and get it | ||
643 | 113 | // in a state that is ready for the next client that connects to the | ||
644 | 114 | // service | ||
645 | 115 | reset_pipeline(); | ||
646 | 116 | } | ||
647 | 117 | |||
648 | 118 | void reset_pipeline() | ||
649 | 119 | { | ||
650 | 120 | std::cout << __PRETTY_FUNCTION__ << std::endl; | ||
651 | 121 | auto ret = gst_element_set_state(pipeline, GST_STATE_NULL); | ||
652 | 122 | switch(ret) | ||
653 | 123 | { | ||
654 | 124 | case GST_STATE_CHANGE_FAILURE: | ||
655 | 125 | std::cout << "Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl; | ||
656 | 126 | break; | ||
657 | 127 | case GST_STATE_CHANGE_NO_PREROLL: | ||
658 | 128 | case GST_STATE_CHANGE_SUCCESS: | ||
659 | 129 | case GST_STATE_CHANGE_ASYNC: | ||
660 | 130 | break; | ||
661 | 131 | default: | ||
662 | 132 | std::cout << "Failed to reset the pipeline state. Client reconnect may not function properly." << std::endl; | ||
663 | 133 | } | ||
664 | 134 | file_type = MEDIA_FILE_TYPE_NONE; | ||
665 | 135 | } | ||
666 | 136 | |||
667 | 85 | void on_new_message(const Bus::Message& message) | 137 | void on_new_message(const Bus::Message& message) |
668 | 86 | { | 138 | { |
669 | 87 | switch(message.type) | 139 | switch(message.type) |
670 | @@ -101,6 +153,16 @@ | |||
671 | 101 | case GST_MESSAGE_STATE_CHANGED: | 153 | case GST_MESSAGE_STATE_CHANGED: |
672 | 102 | signals.on_state_changed(message.detail.state_changed); | 154 | signals.on_state_changed(message.detail.state_changed); |
673 | 103 | break; | 155 | break; |
674 | 156 | case GST_MESSAGE_ASYNC_DONE: | ||
675 | 157 | if (is_seeking) | ||
676 | 158 | { | ||
677 | 159 | // FIXME: Pass the actual playback time position to the signal call | ||
678 | 160 | signals.on_seeked_to(0); | ||
679 | 161 | is_seeking = false; | ||
680 | 162 | } | ||
681 | 163 | break; | ||
682 | 164 | case GST_MESSAGE_EOS: | ||
683 | 165 | signals.on_end_of_stream(); | ||
684 | 104 | default: | 166 | default: |
685 | 105 | break; | 167 | break; |
686 | 106 | } | 168 | } |
687 | @@ -126,6 +188,8 @@ | |||
688 | 126 | ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"), | 188 | ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME"), |
689 | 127 | "audio-sink"); | 189 | "audio-sink"); |
690 | 128 | 190 | ||
691 | 191 | std::cout << "audio_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_AUDIO_SINK_NAME") << std::endl; | ||
692 | 192 | |||
693 | 129 | g_object_set ( | 193 | g_object_set ( |
694 | 130 | pipeline, | 194 | pipeline, |
695 | 131 | "audio-sink", | 195 | "audio-sink", |
696 | @@ -136,26 +200,41 @@ | |||
697 | 136 | if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr) | 200 | if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr) |
698 | 137 | { | 201 | { |
699 | 138 | auto video_sink = gst_element_factory_make ( | 202 | auto video_sink = gst_element_factory_make ( |
702 | 139 | ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"), | 203 | ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME"), |
703 | 140 | "video-sink"); | 204 | "video-sink"); |
704 | 141 | 205 | ||
705 | 142 | std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl; | 206 | std::cout << "video_sink: " << ::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") << std::endl; |
706 | 143 | 207 | ||
707 | 144 | g_object_set ( | 208 | g_object_set ( |
712 | 145 | pipeline, | 209 | pipeline, |
713 | 146 | "video-sink", | 210 | "video-sink", |
714 | 147 | video_sink, | 211 | video_sink, |
715 | 148 | NULL); | 212 | NULL); |
716 | 213 | } | ||
717 | 214 | } | ||
718 | 215 | |||
719 | 216 | void create_video_sink(uint32_t texture_id) | ||
720 | 217 | { | ||
721 | 218 | std::cout << "Creating video sink for texture_id: " << texture_id << std::endl; | ||
722 | 219 | |||
723 | 220 | if (::getenv("CORE_UBUNTU_MEDIA_SERVICE_VIDEO_SINK_NAME") != nullptr) | ||
724 | 221 | { | ||
725 | 222 | GstElement *video_sink = NULL; | ||
726 | 223 | g_object_get (pipeline, "video_sink", &video_sink, NULL); | ||
727 | 224 | |||
728 | 225 | // Get the service-side BufferQueue (IGraphicBufferProducer) and associate it with | ||
729 | 226 | // the SurfaceTextureClientHybris instance | ||
730 | 227 | IGBPWrapperHybris igbp = decoding_service_get_igraphicbufferproducer(); | ||
731 | 228 | SurfaceTextureClientHybris stc = surface_texture_client_create_by_igbp(igbp); | ||
732 | 229 | // Because mirsink is being loaded, we are definitely doing * hardware rendering. | ||
733 | 230 | surface_texture_client_set_hardware_rendering (stc, TRUE); | ||
734 | 231 | g_object_set (G_OBJECT (video_sink), "surface", static_cast<gpointer>(stc), static_cast<char*>(NULL)); | ||
735 | 149 | } | 232 | } |
736 | 150 | } | 233 | } |
737 | 151 | 234 | ||
738 | 152 | void set_volume(double new_volume) | 235 | void set_volume(double new_volume) |
739 | 153 | { | 236 | { |
745 | 154 | g_object_set( | 237 | g_object_set(pipeline, "volume", new_volume, NULL); |
741 | 155 | pipeline, | ||
742 | 156 | "volume", | ||
743 | 157 | new_volume, | ||
744 | 158 | NULL); | ||
746 | 159 | } | 238 | } |
747 | 160 | 239 | ||
748 | 161 | uint64_t position() const | 240 | uint64_t position() const |
749 | @@ -178,11 +257,11 @@ | |||
750 | 178 | 257 | ||
751 | 179 | void set_uri(const std::string& uri) | 258 | void set_uri(const std::string& uri) |
752 | 180 | { | 259 | { |
758 | 181 | g_object_set( | 260 | g_object_set(pipeline, "uri", uri.c_str(), NULL); |
759 | 182 | pipeline, | 261 | if (is_video_file(uri)) |
760 | 183 | "uri", | 262 | file_type = MEDIA_FILE_TYPE_VIDEO; |
761 | 184 | uri.c_str(), | 263 | else if (is_audio_file(uri)) |
762 | 185 | NULL); | 264 | file_type = MEDIA_FILE_TYPE_AUDIO; |
763 | 186 | } | 265 | } |
764 | 187 | 266 | ||
765 | 188 | std::string uri() const | 267 | std::string uri() const |
766 | @@ -229,16 +308,96 @@ | |||
767 | 229 | 308 | ||
768 | 230 | bool seek(const std::chrono::microseconds& ms) | 309 | bool seek(const std::chrono::microseconds& ms) |
769 | 231 | { | 310 | { |
770 | 311 | is_seeking = true; | ||
771 | 232 | return gst_element_seek_simple( | 312 | return gst_element_seek_simple( |
772 | 233 | pipeline, | 313 | pipeline, |
773 | 234 | GST_FORMAT_TIME, | 314 | GST_FORMAT_TIME, |
775 | 235 | (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), | 315 | (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | |
776 | 316 | GST_SEEK_FLAG_SNAP_BEFORE), | ||
777 | 236 | ms.count() * 1000); | 317 | ms.count() * 1000); |
778 | 237 | } | 318 | } |
779 | 238 | 319 | ||
780 | 320 | std::string get_file_content_type(const std::string& uri) const | ||
781 | 321 | { | ||
782 | 322 | if (uri.empty()) | ||
783 | 323 | return std::string(); | ||
784 | 324 | |||
785 | 325 | std::string filename(uri); | ||
786 | 326 | std::cout << "filename: " << filename << std::endl; | ||
787 | 327 | size_t pos = uri.find("file://"); | ||
788 | 328 | if (pos != std::string::npos) | ||
789 | 329 | filename = uri.substr(pos + 7, std::string::npos); | ||
790 | 330 | else | ||
791 | 331 | // Anything other than a file, for now claim that the type | ||
792 | 332 | // is both audio and video. | ||
793 | 333 | // FIXME: implement true net stream sampling and get the type from GstCaps | ||
794 | 334 | return std::string("audio/video/"); | ||
795 | 335 | |||
796 | 336 | |||
797 | 337 | GError *error = nullptr; | ||
798 | 338 | std::unique_ptr<GFile, void(*)(void *)> file( | ||
799 | 339 | g_file_new_for_path(filename.c_str()), g_object_unref); | ||
800 | 340 | std::unique_ptr<GFileInfo, void(*)(void *)> info( | ||
801 | 341 | g_file_query_info( | ||
802 | 342 | file.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE "," | ||
803 | 343 | G_FILE_ATTRIBUTE_ETAG_VALUE, G_FILE_QUERY_INFO_NONE, | ||
804 | 344 | /* cancellable */ NULL, &error), | ||
805 | 345 | g_object_unref); | ||
806 | 346 | if (!info) | ||
807 | 347 | { | ||
808 | 348 | std::string error_str(error->message); | ||
809 | 349 | g_error_free(error); | ||
810 | 350 | |||
811 | 351 | std::cout << "Failed to query the URI for the presence of video content: " | ||
812 | 352 | << error_str << std::endl; | ||
813 | 353 | return std::string(); | ||
814 | 354 | } | ||
815 | 355 | |||
816 | 356 | std::string content_type(g_file_info_get_attribute_string( | ||
817 | 357 | info.get(), G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE)); | ||
818 | 358 | |||
819 | 359 | return content_type; | ||
820 | 360 | } | ||
821 | 361 | |||
822 | 362 | bool is_audio_file(const std::string& uri) const | ||
823 | 363 | { | ||
824 | 364 | if (uri.empty()) | ||
825 | 365 | return false; | ||
826 | 366 | |||
827 | 367 | if (get_file_content_type(uri).find("audio/") == 0) | ||
828 | 368 | { | ||
829 | 369 | std::cout << "Found audio content" << std::endl; | ||
830 | 370 | return true; | ||
831 | 371 | } | ||
832 | 372 | |||
833 | 373 | return false; | ||
834 | 374 | } | ||
835 | 375 | |||
836 | 376 | bool is_video_file(const std::string& uri) const | ||
837 | 377 | { | ||
838 | 378 | if (uri.empty()) | ||
839 | 379 | return false; | ||
840 | 380 | |||
841 | 381 | if (get_file_content_type(uri).find("video/") == 0) | ||
842 | 382 | { | ||
843 | 383 | std::cout << "Found video content" << std::endl; | ||
844 | 384 | return true; | ||
845 | 385 | } | ||
846 | 386 | |||
847 | 387 | return false; | ||
848 | 388 | } | ||
849 | 389 | |||
850 | 390 | MediaFileType media_file_type() const | ||
851 | 391 | { | ||
852 | 392 | return file_type; | ||
853 | 393 | } | ||
854 | 394 | |||
855 | 239 | GstElement* pipeline; | 395 | GstElement* pipeline; |
856 | 240 | gstreamer::Bus bus; | 396 | gstreamer::Bus bus; |
857 | 397 | MediaFileType file_type; | ||
858 | 398 | SurfaceTextureClientHybris stc_hybris; | ||
859 | 241 | core::Connection on_new_message_connection; | 399 | core::Connection on_new_message_connection; |
860 | 400 | bool is_seeking; | ||
861 | 242 | struct | 401 | struct |
862 | 243 | { | 402 | { |
863 | 244 | core::Signal<void> about_to_finish; | 403 | core::Signal<void> about_to_finish; |
864 | @@ -247,6 +406,8 @@ | |||
865 | 247 | core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info; | 406 | core::Signal<Bus::Message::Detail::ErrorWarningInfo> on_info; |
866 | 248 | core::Signal<Bus::Message::Detail::Tag> on_tag_available; | 407 | core::Signal<Bus::Message::Detail::Tag> on_tag_available; |
867 | 249 | core::Signal<Bus::Message::Detail::StateChanged> on_state_changed; | 408 | core::Signal<Bus::Message::Detail::StateChanged> on_state_changed; |
868 | 409 | core::Signal<uint64_t> on_seeked_to; | ||
869 | 410 | core::Signal<void> on_end_of_stream; | ||
870 | 250 | } signals; | 411 | } signals; |
871 | 251 | }; | 412 | }; |
872 | 252 | } | 413 | } |
873 | 253 | 414 | ||
874 | === modified file 'src/core/media/mpris/player.h' | |||
875 | --- src/core/media/mpris/player.h 2014-02-18 19:27:01 +0000 | |||
876 | +++ src/core/media/mpris/player.h 2014-04-17 21:13:23 +0000 | |||
877 | @@ -54,11 +54,13 @@ | |||
878 | 54 | METHOD(Play, Player, std::chrono::seconds(1)) | 54 | METHOD(Play, Player, std::chrono::seconds(1)) |
879 | 55 | METHOD(Seek, Player, std::chrono::seconds(1)) | 55 | METHOD(Seek, Player, std::chrono::seconds(1)) |
880 | 56 | METHOD(SetPosition, Player, std::chrono::seconds(1)) | 56 | METHOD(SetPosition, Player, std::chrono::seconds(1)) |
881 | 57 | METHOD(CreateVideoSink, Player, std::chrono::seconds(1)) | ||
882 | 57 | METHOD(OpenUri, Player, std::chrono::seconds(1)) | 58 | METHOD(OpenUri, Player, std::chrono::seconds(1)) |
883 | 58 | 59 | ||
884 | 59 | struct Signals | 60 | struct Signals |
885 | 60 | { | 61 | { |
886 | 61 | SIGNAL(Seeked, Player, uint64_t) | 62 | SIGNAL(Seeked, Player, uint64_t) |
887 | 63 | SIGNAL(EndOfStream, Player, void) | ||
888 | 62 | }; | 64 | }; |
889 | 63 | 65 | ||
890 | 64 | struct Properties | 66 | struct Properties |
891 | @@ -74,6 +76,8 @@ | |||
892 | 74 | READABLE_PROPERTY(Duration, Player, uint64_t) | 76 | READABLE_PROPERTY(Duration, Player, uint64_t) |
893 | 75 | READABLE_PROPERTY(MinimumRate, Player, double) | 77 | READABLE_PROPERTY(MinimumRate, Player, double) |
894 | 76 | READABLE_PROPERTY(MaximumRate, Player, double) | 78 | READABLE_PROPERTY(MaximumRate, Player, double) |
895 | 79 | READABLE_PROPERTY(IsVideoSource, Player, bool) | ||
896 | 80 | READABLE_PROPERTY(IsAudioSource, Player, bool) | ||
897 | 77 | READABLE_PROPERTY(CanGoNext, Player, bool) | 81 | READABLE_PROPERTY(CanGoNext, Player, bool) |
898 | 78 | READABLE_PROPERTY(CanGoPrevious, Player, bool) | 82 | READABLE_PROPERTY(CanGoPrevious, Player, bool) |
899 | 79 | READABLE_PROPERTY(CanPlay, Player, bool) | 83 | READABLE_PROPERTY(CanPlay, Player, bool) |
900 | 80 | 84 | ||
901 | === modified file 'src/core/media/player_implementation.cpp' | |||
902 | --- src/core/media/player_implementation.cpp 2014-02-18 20:25:21 +0000 | |||
903 | +++ src/core/media/player_implementation.cpp 2014-04-17 21:13:23 +0000 | |||
904 | @@ -17,9 +17,13 @@ | |||
905 | 17 | 17 | ||
906 | 18 | #include "player_implementation.h" | 18 | #include "player_implementation.h" |
907 | 19 | 19 | ||
908 | 20 | #include <unistd.h> | ||
909 | 21 | |||
910 | 20 | #include "engine.h" | 22 | #include "engine.h" |
911 | 21 | #include "track_list_implementation.h" | 23 | #include "track_list_implementation.h" |
912 | 22 | 24 | ||
913 | 25 | #define UNUSED __attribute__((unused)) | ||
914 | 26 | |||
915 | 23 | namespace media = core::ubuntu::media; | 27 | namespace media = core::ubuntu::media; |
916 | 24 | 28 | ||
917 | 25 | struct media::PlayerImplementation::Private | 29 | struct media::PlayerImplementation::Private |
918 | @@ -39,7 +43,7 @@ | |||
919 | 39 | { | 43 | { |
920 | 40 | engine->state().changed().connect( | 44 | engine->state().changed().connect( |
921 | 41 | [parent](const Engine::State& state) | 45 | [parent](const Engine::State& state) |
923 | 42 | { | 46 | { |
924 | 43 | switch(state) | 47 | switch(state) |
925 | 44 | { | 48 | { |
926 | 45 | case Engine::State::ready: parent->playback_status().set(media::Player::ready); break; | 49 | case Engine::State::ready: parent->playback_status().set(media::Player::ready); break; |
927 | @@ -49,7 +53,8 @@ | |||
928 | 49 | default: | 53 | default: |
929 | 50 | break; | 54 | break; |
930 | 51 | }; | 55 | }; |
932 | 52 | }); | 56 | }); |
933 | 57 | |||
934 | 53 | } | 58 | } |
935 | 54 | 59 | ||
936 | 55 | PlayerImplementation* parent; | 60 | PlayerImplementation* parent; |
937 | @@ -76,6 +81,8 @@ | |||
938 | 76 | can_seek().set(true); | 81 | can_seek().set(true); |
939 | 77 | can_go_previous().set(true); | 82 | can_go_previous().set(true); |
940 | 78 | can_go_next().set(true); | 83 | can_go_next().set(true); |
941 | 84 | is_video_source().set(false); | ||
942 | 85 | is_audio_source().set(false); | ||
943 | 79 | is_shuffle().set(true); | 86 | is_shuffle().set(true); |
944 | 80 | playback_rate().set(1.f); | 87 | playback_rate().set(1.f); |
945 | 81 | playback_status().set(Player::PlaybackStatus::null); | 88 | playback_status().set(Player::PlaybackStatus::null); |
946 | @@ -98,6 +105,38 @@ | |||
947 | 98 | return d->engine->duration().get(); | 105 | return d->engine->duration().get(); |
948 | 99 | }; | 106 | }; |
949 | 100 | duration().install(duration_getter); | 107 | duration().install(duration_getter); |
950 | 108 | |||
951 | 109 | std::function<bool()> video_type_getter = [this]() | ||
952 | 110 | { | ||
953 | 111 | return d->engine->is_video_source().get(); | ||
954 | 112 | }; | ||
955 | 113 | is_video_source().install(video_type_getter); | ||
956 | 114 | |||
957 | 115 | std::function<bool()> audio_type_getter = [this]() | ||
958 | 116 | { | ||
959 | 117 | return d->engine->is_audio_source().get(); | ||
960 | 118 | }; | ||
961 | 119 | is_audio_source().install(audio_type_getter); | ||
962 | 120 | |||
963 | 121 | engine->about_to_finish_signal().connect([this]() | ||
964 | 122 | { | ||
965 | 123 | if (d->track_list->has_next()) | ||
966 | 124 | { | ||
967 | 125 | Track::UriType uri = d->track_list->query_uri_for_track(d->track_list->next()); | ||
968 | 126 | if (!uri.empty()) | ||
969 | 127 | d->parent->open_uri(uri); | ||
970 | 128 | } | ||
971 | 129 | }); | ||
972 | 130 | |||
973 | 131 | engine->seeked_to_signal().connect([this](uint64_t value) | ||
974 | 132 | { | ||
975 | 133 | seeked_to()(value); | ||
976 | 134 | }); | ||
977 | 135 | |||
978 | 136 | engine->end_of_stream_signal().connect([this]() | ||
979 | 137 | { | ||
980 | 138 | end_of_stream()(); | ||
981 | 139 | }); | ||
982 | 101 | } | 140 | } |
983 | 102 | 141 | ||
984 | 103 | media::PlayerImplementation::~PlayerImplementation() | 142 | media::PlayerImplementation::~PlayerImplementation() |
985 | @@ -114,6 +153,17 @@ | |||
986 | 114 | return d->engine->open_resource_for_uri(uri); | 153 | return d->engine->open_resource_for_uri(uri); |
987 | 115 | } | 154 | } |
988 | 116 | 155 | ||
989 | 156 | void media::PlayerImplementation::create_video_sink(uint32_t texture_id) | ||
990 | 157 | { | ||
991 | 158 | d->engine->create_video_sink(texture_id); | ||
992 | 159 | } | ||
993 | 160 | |||
994 | 161 | media::Player::GLConsumerWrapperHybris media::PlayerImplementation::gl_consumer() const | ||
995 | 162 | { | ||
996 | 163 | // This method is client-side only and is simply a no-op for the service side | ||
997 | 164 | return NULL; | ||
998 | 165 | } | ||
999 | 166 | |||
1000 | 117 | void media::PlayerImplementation::next() | 167 | void media::PlayerImplementation::next() |
1001 | 118 | { | 168 | { |
1002 | 119 | } | 169 | } |
1003 | @@ -124,11 +174,6 @@ | |||
1004 | 124 | 174 | ||
1005 | 125 | void media::PlayerImplementation::play() | 175 | void media::PlayerImplementation::play() |
1006 | 126 | { | 176 | { |
1007 | 127 | /*if (playback_status() == media::Player::null) | ||
1008 | 128 | { | ||
1009 | 129 | if (d->track_list->has_next()) | ||
1010 | 130 | if (open_uri(d->track_list->next()->)) | ||
1011 | 131 | }*/ | ||
1012 | 132 | d->engine->play(); | 177 | d->engine->play(); |
1013 | 133 | } | 178 | } |
1014 | 134 | 179 | ||
1015 | @@ -142,6 +187,18 @@ | |||
1016 | 142 | d->engine->stop(); | 187 | d->engine->stop(); |
1017 | 143 | } | 188 | } |
1018 | 144 | 189 | ||
1019 | 190 | void media::PlayerImplementation::set_frame_available_callback( | ||
1020 | 191 | UNUSED FrameAvailableCb cb, UNUSED void *context) | ||
1021 | 192 | { | ||
1022 | 193 | // This method is client-side only and is simply a no-op for the service side | ||
1023 | 194 | } | ||
1024 | 195 | |||
1025 | 196 | void media::PlayerImplementation::set_playback_complete_callback( | ||
1026 | 197 | UNUSED PlaybackCompleteCb cb, UNUSED void *context) | ||
1027 | 198 | { | ||
1028 | 199 | // This method is client-side only and is simply a no-op for the service side | ||
1029 | 200 | } | ||
1030 | 201 | |||
1031 | 145 | void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms) | 202 | void media::PlayerImplementation::seek_to(const std::chrono::microseconds& ms) |
1032 | 146 | { | 203 | { |
1033 | 147 | d->engine->seek_to(ms); | 204 | d->engine->seek_to(ms); |
1034 | 148 | 205 | ||
1035 | === modified file 'src/core/media/player_implementation.h' | |||
1036 | --- src/core/media/player_implementation.h 2014-02-18 20:25:21 +0000 | |||
1037 | +++ src/core/media/player_implementation.h 2014-04-17 21:13:23 +0000 | |||
1038 | @@ -43,11 +43,15 @@ | |||
1039 | 43 | virtual std::shared_ptr<TrackList> track_list(); | 43 | virtual std::shared_ptr<TrackList> track_list(); |
1040 | 44 | 44 | ||
1041 | 45 | virtual bool open_uri(const Track::UriType& uri); | 45 | virtual bool open_uri(const Track::UriType& uri); |
1042 | 46 | virtual void create_video_sink(uint32_t texture_id); | ||
1043 | 47 | virtual GLConsumerWrapperHybris gl_consumer() const; | ||
1044 | 46 | virtual void next(); | 48 | virtual void next(); |
1045 | 47 | virtual void previous(); | 49 | virtual void previous(); |
1046 | 48 | virtual void play(); | 50 | virtual void play(); |
1047 | 49 | virtual void pause(); | 51 | virtual void pause(); |
1048 | 50 | virtual void stop(); | 52 | virtual void stop(); |
1049 | 53 | virtual void set_frame_available_callback(FrameAvailableCb cb, void *context); | ||
1050 | 54 | virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context); | ||
1051 | 51 | virtual void seek_to(const std::chrono::microseconds& offset); | 55 | virtual void seek_to(const std::chrono::microseconds& offset); |
1052 | 52 | 56 | ||
1053 | 53 | private: | 57 | private: |
1054 | 54 | 58 | ||
1055 | === modified file 'src/core/media/player_skeleton.cpp' | |||
1056 | --- src/core/media/player_skeleton.cpp 2014-02-20 19:05:17 +0000 | |||
1057 | +++ src/core/media/player_skeleton.cpp 2014-04-17 21:13:23 +0000 | |||
1058 | @@ -16,6 +16,7 @@ | |||
1059 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1060 | 17 | */ | 17 | */ |
1061 | 18 | 18 | ||
1062 | 19 | #include "apparmor.h" | ||
1063 | 19 | #include "codec.h" | 20 | #include "codec.h" |
1064 | 20 | #include "player_skeleton.h" | 21 | #include "player_skeleton.h" |
1065 | 21 | #include "player_traits.h" | 22 | #include "player_traits.h" |
1066 | @@ -27,6 +28,7 @@ | |||
1067 | 27 | #include <core/dbus/object.h> | 28 | #include <core/dbus/object.h> |
1068 | 28 | #include <core/dbus/property.h> | 29 | #include <core/dbus/property.h> |
1069 | 29 | #include <core/dbus/stub.h> | 30 | #include <core/dbus/stub.h> |
1070 | 31 | #include <core/dbus/asio/executor.h> | ||
1071 | 30 | 32 | ||
1072 | 31 | namespace dbus = core::dbus; | 33 | namespace dbus = core::dbus; |
1073 | 32 | namespace media = core::ubuntu::media; | 34 | namespace media = core::ubuntu::media; |
1074 | @@ -36,6 +38,7 @@ | |||
1075 | 36 | Private(media::PlayerSkeleton* player, const dbus::types::ObjectPath& session) | 38 | Private(media::PlayerSkeleton* player, const dbus::types::ObjectPath& session) |
1076 | 37 | : impl(player), | 39 | : impl(player), |
1077 | 38 | object(impl->access_service()->add_object_for_path(session)), | 40 | object(impl->access_service()->add_object_for_path(session)), |
1078 | 41 | apparmor_session(nullptr), | ||
1079 | 39 | properties | 42 | properties |
1080 | 40 | { | 43 | { |
1081 | 41 | object->get_property<mpris::Player::Properties::CanPlay>(), | 44 | object->get_property<mpris::Player::Properties::CanPlay>(), |
1082 | @@ -44,6 +47,8 @@ | |||
1083 | 44 | object->get_property<mpris::Player::Properties::CanControl>(), | 47 | object->get_property<mpris::Player::Properties::CanControl>(), |
1084 | 45 | object->get_property<mpris::Player::Properties::CanGoNext>(), | 48 | object->get_property<mpris::Player::Properties::CanGoNext>(), |
1085 | 46 | object->get_property<mpris::Player::Properties::CanGoPrevious>(), | 49 | object->get_property<mpris::Player::Properties::CanGoPrevious>(), |
1086 | 50 | object->get_property<mpris::Player::Properties::IsVideoSource>(), | ||
1087 | 51 | object->get_property<mpris::Player::Properties::IsAudioSource>(), | ||
1088 | 47 | object->get_property<mpris::Player::Properties::PlaybackStatus>(), | 52 | object->get_property<mpris::Player::Properties::PlaybackStatus>(), |
1089 | 48 | object->get_property<mpris::Player::Properties::LoopStatus>(), | 53 | object->get_property<mpris::Player::Properties::LoopStatus>(), |
1090 | 49 | object->get_property<mpris::Player::Properties::PlaybackRate>(), | 54 | object->get_property<mpris::Player::Properties::PlaybackRate>(), |
1091 | @@ -54,6 +59,11 @@ | |||
1092 | 54 | object->get_property<mpris::Player::Properties::Duration>(), | 59 | object->get_property<mpris::Player::Properties::Duration>(), |
1093 | 55 | object->get_property<mpris::Player::Properties::MinimumRate>(), | 60 | object->get_property<mpris::Player::Properties::MinimumRate>(), |
1094 | 56 | object->get_property<mpris::Player::Properties::MaximumRate>() | 61 | object->get_property<mpris::Player::Properties::MaximumRate>() |
1095 | 62 | }, | ||
1096 | 63 | signals | ||
1097 | 64 | { | ||
1098 | 65 | object->get_signal<mpris::Player::Signals::Seeked>(), | ||
1099 | 66 | object->get_signal<mpris::Player::Signals::EndOfStream>() | ||
1100 | 57 | } | 67 | } |
1101 | 58 | { | 68 | { |
1102 | 59 | } | 69 | } |
1103 | @@ -111,18 +121,123 @@ | |||
1104 | 111 | { | 121 | { |
1105 | 112 | } | 122 | } |
1106 | 113 | 123 | ||
1107 | 124 | void handle_create_video_sink(const core::dbus::Message::Ptr& in) | ||
1108 | 125 | { | ||
1109 | 126 | uint32_t texture_id; | ||
1110 | 127 | in->reader() >> texture_id; | ||
1111 | 128 | impl->create_video_sink(texture_id); | ||
1112 | 129 | |||
1113 | 130 | auto reply = dbus::Message::make_method_return(in); | ||
1114 | 131 | impl->access_bus()->send(reply); | ||
1115 | 132 | } | ||
1116 | 133 | |||
1117 | 134 | std::string get_client_apparmor_context(const core::dbus::Message::Ptr& msg) | ||
1118 | 135 | { | ||
1119 | 136 | auto bus = std::shared_ptr<dbus::Bus>(new dbus::Bus(core::dbus::WellKnownBus::session)); | ||
1120 | 137 | bus->install_executor(dbus::asio::make_executor(bus)); | ||
1121 | 138 | |||
1122 | 139 | auto stub_service = dbus::Service::use_service(bus, dbus::traits::Service<core::Apparmor>::interface_name()); | ||
1123 | 140 | apparmor_session = stub_service->object_for_path(dbus::types::ObjectPath("/org/freedesktop/DBus")); | ||
1124 | 141 | // Get the AppArmor security context for the client | ||
1125 | 142 | auto result = apparmor_session->invoke_method_synchronously<core::Apparmor::getConnectionAppArmorSecurityContext, std::string>(msg->sender()); | ||
1126 | 143 | if (result.is_error()) | ||
1127 | 144 | { | ||
1128 | 145 | std::cout << "Error getting apparmor profile: " << result.error().print() << std::endl; | ||
1129 | 146 | return std::string(); | ||
1130 | 147 | } | ||
1131 | 148 | |||
1132 | 149 | return result.value(); | ||
1133 | 150 | } | ||
1134 | 151 | |||
1135 | 152 | bool does_client_have_access(const std::string& context, const std::string& uri) | ||
1136 | 153 | { | ||
1137 | 154 | if (context.empty() || uri.empty()) | ||
1138 | 155 | { | ||
1139 | 156 | std::cout << "Client denied access since context or uri are empty" << std::endl; | ||
1140 | 157 | return false; | ||
1141 | 158 | } | ||
1142 | 159 | |||
1143 | 160 | if (context == "unconfined") | ||
1144 | 161 | { | ||
1145 | 162 | std::cout << "Client allowed access since it's unconfined" << std::endl; | ||
1146 | 163 | return true; | ||
1147 | 164 | } | ||
1148 | 165 | |||
1149 | 166 | size_t pos = context.find_first_of('_'); | ||
1150 | 167 | if (pos == std::string::npos) | ||
1151 | 168 | { | ||
1152 | 169 | std::cout << "Client denied access since it's an invalid apparmor security context" << std::endl; | ||
1153 | 170 | return false; | ||
1154 | 171 | } | ||
1155 | 172 | |||
1156 | 173 | const std::string pkgname = context.substr(0, pos); | ||
1157 | 174 | std::cout << "client pkgname: " << pkgname << std::endl; | ||
1158 | 175 | std::cout << "uri: " << uri << std::endl; | ||
1159 | 176 | |||
1160 | 177 | // All confined apps can access their own files | ||
1161 | 178 | if (uri.find(std::string(".local/share/" + pkgname + "/")) != std::string::npos | ||
1162 | 179 | || uri.find(std::string(".cache/" + pkgname + "/")) != std::string::npos) | ||
1163 | 180 | { | ||
1164 | 181 | std::cout << "Client can access content in ~/.local/share/" << pkgname << " or ~/.cache/" << pkgname << std::endl; | ||
1165 | 182 | return true; | ||
1166 | 183 | } | ||
1167 | 184 | else if (uri.find(std::string("opt/click.ubuntu.com/")) != std::string::npos | ||
1168 | 185 | && uri.find(pkgname) != std::string::npos) | ||
1169 | 186 | { | ||
1170 | 187 | std::cout << "Client can access content in own opt directory" << std::endl; | ||
1171 | 188 | return true; | ||
1172 | 189 | } | ||
1173 | 190 | else if ((uri.find(std::string("/system/media/audio/ui/")) != std::string::npos | ||
1174 | 191 | || uri.find(std::string("/android/system/media/audio/ui/")) != std::string::npos) | ||
1175 | 192 | && pkgname == "com.ubuntu.camera") | ||
1176 | 193 | { | ||
1177 | 194 | std::cout << "Camera app can access ui sounds" << std::endl; | ||
1178 | 195 | return true; | ||
1179 | 196 | } | ||
1180 | 197 | // TODO: Check if the trust store previously allowed direct access to uri | ||
1181 | 198 | |||
1182 | 199 | // Check in ~/Music and ~/Videos | ||
1183 | 200 | // TODO: when the trust store lands, check it to see if this app can access the dirs and | ||
1184 | 201 | // then remove the explicit whitelist of the music-app | ||
1185 | 202 | else if (pkgname == "com.ubuntu.music" && | ||
1186 | 203 | (uri.find(std::string("Music/")) != std::string::npos | ||
1187 | 204 | || uri.find(std::string("Videos/")) != std::string::npos)) | ||
1188 | 205 | { | ||
1189 | 206 | std::cout << "Client can access content in ~/Music or ~/Videos" << std::endl; | ||
1190 | 207 | return true; | ||
1191 | 208 | } | ||
1192 | 209 | else if (uri.find(std::string("http://")) != std::string::npos | ||
1193 | 210 | || uri.find(std::string("rtsp://")) != std::string::npos) | ||
1194 | 211 | { | ||
1195 | 212 | std::cout << "Client can access streaming content" << std::endl; | ||
1196 | 213 | return true; | ||
1197 | 214 | } | ||
1198 | 215 | else | ||
1199 | 216 | { | ||
1200 | 217 | std::cout << "Client denied access to open_uri()" << std::endl; | ||
1201 | 218 | return false; | ||
1202 | 219 | } | ||
1203 | 220 | } | ||
1204 | 221 | |||
1205 | 114 | void handle_open_uri(const core::dbus::Message::Ptr& in) | 222 | void handle_open_uri(const core::dbus::Message::Ptr& in) |
1206 | 115 | { | 223 | { |
1207 | 116 | Track::UriType uri; | 224 | Track::UriType uri; |
1208 | 117 | in->reader() >> uri; | 225 | in->reader() >> uri; |
1209 | 118 | 226 | ||
1210 | 227 | std::string context = get_client_apparmor_context(in); | ||
1211 | 228 | bool have_access = does_client_have_access(context, uri); | ||
1212 | 229 | |||
1213 | 119 | auto reply = dbus::Message::make_method_return(in); | 230 | auto reply = dbus::Message::make_method_return(in); |
1215 | 120 | reply->writer() << impl->open_uri(uri); | 231 | if (have_access) |
1216 | 232 | reply->writer() << impl->open_uri(uri); | ||
1217 | 233 | else | ||
1218 | 234 | reply->writer() << false; | ||
1219 | 121 | impl->access_bus()->send(reply); | 235 | impl->access_bus()->send(reply); |
1220 | 122 | } | 236 | } |
1221 | 123 | 237 | ||
1222 | 124 | media::PlayerSkeleton* impl; | 238 | media::PlayerSkeleton* impl; |
1223 | 125 | dbus::Object::Ptr object; | 239 | dbus::Object::Ptr object; |
1224 | 240 | dbus::Object::Ptr apparmor_session; | ||
1225 | 126 | struct | 241 | struct |
1226 | 127 | { | 242 | { |
1227 | 128 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play; | 243 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanPlay>> can_play; |
1228 | @@ -131,6 +246,8 @@ | |||
1229 | 131 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control; | 246 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control; |
1230 | 132 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next; | 247 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next; |
1231 | 133 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous; | 248 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous; |
1232 | 249 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source; | ||
1233 | 250 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source; | ||
1234 | 134 | 251 | ||
1235 | 135 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status; | 252 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status; |
1236 | 136 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status; | 253 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status; |
1237 | @@ -144,10 +261,40 @@ | |||
1238 | 144 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate; | 261 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate; |
1239 | 145 | } properties; | 262 | } properties; |
1240 | 146 | 263 | ||
1242 | 147 | /*struct | 264 | struct Signals |
1243 | 148 | { | 265 | { |
1246 | 149 | std::shared_ptr<dbus::Signal<mpris::Player::Signals::Seeked, uint64_t>> seeked; | 266 | typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal; |
1247 | 150 | } signals;*/ | 267 | typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal; |
1248 | 268 | |||
1249 | 269 | Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked, | ||
1250 | 270 | const std::shared_ptr<DBusEndOfStreamSignal>& eos) | ||
1251 | 271 | : dbus | ||
1252 | 272 | { | ||
1253 | 273 | seeked, | ||
1254 | 274 | eos | ||
1255 | 275 | }, | ||
1256 | 276 | seeked_to(), | ||
1257 | 277 | end_of_stream() | ||
1258 | 278 | { | ||
1259 | 279 | seeked_to.connect([this](std::uint64_t value) | ||
1260 | 280 | { | ||
1261 | 281 | dbus.seeked_to->emit(value); | ||
1262 | 282 | }); | ||
1263 | 283 | |||
1264 | 284 | end_of_stream.connect([this]() | ||
1265 | 285 | { | ||
1266 | 286 | dbus.end_of_stream->emit(); | ||
1267 | 287 | }); | ||
1268 | 288 | } | ||
1269 | 289 | |||
1270 | 290 | struct DBus | ||
1271 | 291 | { | ||
1272 | 292 | std::shared_ptr<DBusSeekedToSignal> seeked_to; | ||
1273 | 293 | std::shared_ptr<DBusEndOfStreamSignal> end_of_stream; | ||
1274 | 294 | } dbus; | ||
1275 | 295 | core::Signal<uint64_t> seeked_to; | ||
1276 | 296 | core::Signal<void> end_of_stream; | ||
1277 | 297 | } signals; | ||
1278 | 151 | 298 | ||
1279 | 152 | }; | 299 | }; |
1280 | 153 | 300 | ||
1281 | @@ -184,6 +331,10 @@ | |||
1282 | 184 | std::bind(&Private::handle_set_position, | 331 | std::bind(&Private::handle_set_position, |
1283 | 185 | std::ref(d), | 332 | std::ref(d), |
1284 | 186 | std::placeholders::_1)); | 333 | std::placeholders::_1)); |
1285 | 334 | d->object->install_method_handler<mpris::Player::CreateVideoSink>( | ||
1286 | 335 | std::bind(&Private::handle_create_video_sink, | ||
1287 | 336 | std::ref(d), | ||
1288 | 337 | std::placeholders::_1)); | ||
1289 | 187 | d->object->install_method_handler<mpris::Player::OpenUri>( | 338 | d->object->install_method_handler<mpris::Player::OpenUri>( |
1290 | 188 | std::bind(&Private::handle_open_uri, | 339 | std::bind(&Private::handle_open_uri, |
1291 | 189 | std::ref(d), | 340 | std::ref(d), |
1292 | @@ -219,6 +370,16 @@ | |||
1293 | 219 | return *d->properties.can_go_next; | 370 | return *d->properties.can_go_next; |
1294 | 220 | } | 371 | } |
1295 | 221 | 372 | ||
1296 | 373 | const core::Property<bool>& media::PlayerSkeleton::is_video_source() const | ||
1297 | 374 | { | ||
1298 | 375 | return *d->properties.is_video_source; | ||
1299 | 376 | } | ||
1300 | 377 | |||
1301 | 378 | const core::Property<bool>& media::PlayerSkeleton::is_audio_source() const | ||
1302 | 379 | { | ||
1303 | 380 | return *d->properties.is_audio_source; | ||
1304 | 381 | } | ||
1305 | 382 | |||
1306 | 222 | const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const | 383 | const core::Property<media::Player::PlaybackStatus>& media::PlayerSkeleton::playback_status() const |
1307 | 223 | { | 384 | { |
1308 | 224 | return *d->properties.playback_status; | 385 | return *d->properties.playback_status; |
1309 | @@ -329,6 +490,17 @@ | |||
1310 | 329 | return *d->properties.can_go_next; | 490 | return *d->properties.can_go_next; |
1311 | 330 | } | 491 | } |
1312 | 331 | 492 | ||
1313 | 493 | core::Property<bool>& media::PlayerSkeleton::is_video_source() | ||
1314 | 494 | { | ||
1315 | 495 | return *d->properties.is_video_source; | ||
1316 | 496 | } | ||
1317 | 497 | |||
1318 | 498 | core::Property<bool>& media::PlayerSkeleton::is_audio_source() | ||
1319 | 499 | { | ||
1320 | 500 | return *d->properties.is_audio_source; | ||
1321 | 501 | } | ||
1322 | 502 | |||
1323 | 503 | |||
1324 | 332 | core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() | 504 | core::Property<media::Track::MetaData>& media::PlayerSkeleton::meta_data_for_current_track() |
1325 | 333 | { | 505 | { |
1326 | 334 | return *d->properties.meta_data_for_current_track; | 506 | return *d->properties.meta_data_for_current_track; |
1327 | @@ -346,6 +518,20 @@ | |||
1328 | 346 | 518 | ||
1329 | 347 | const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const | 519 | const core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() const |
1330 | 348 | { | 520 | { |
1333 | 349 | static const core::Signal<uint64_t> signal; | 521 | return d->signals.seeked_to; |
1334 | 350 | return signal; | 522 | } |
1335 | 523 | |||
1336 | 524 | core::Signal<uint64_t>& media::PlayerSkeleton::seeked_to() | ||
1337 | 525 | { | ||
1338 | 526 | return d->signals.seeked_to; | ||
1339 | 527 | } | ||
1340 | 528 | |||
1341 | 529 | const core::Signal<void>& media::PlayerSkeleton::end_of_stream() const | ||
1342 | 530 | { | ||
1343 | 531 | return d->signals.end_of_stream; | ||
1344 | 532 | } | ||
1345 | 533 | |||
1346 | 534 | core::Signal<void>& media::PlayerSkeleton::end_of_stream() | ||
1347 | 535 | { | ||
1348 | 536 | return d->signals.end_of_stream; | ||
1349 | 351 | } | 537 | } |
1350 | 352 | 538 | ||
1351 | === modified file 'src/core/media/player_skeleton.h' | |||
1352 | --- src/core/media/player_skeleton.h 2014-02-18 19:27:01 +0000 | |||
1353 | +++ src/core/media/player_skeleton.h 2014-04-17 21:13:23 +0000 | |||
1354 | @@ -1,4 +1,6 @@ | |||
1355 | 1 | /** | 1 | /** |
1356 | 2 | * Copyright (C) 2013-2014 Canonical Ltd | ||
1357 | 3 | * | ||
1358 | 2 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1359 | 3 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1360 | 4 | * as published by the Free Software Foundation. | 6 | * as published by the Free Software Foundation. |
1361 | @@ -46,6 +48,8 @@ | |||
1362 | 46 | virtual const core::Property<bool>& can_seek() const; | 48 | virtual const core::Property<bool>& can_seek() const; |
1363 | 47 | virtual const core::Property<bool>& can_go_previous() const; | 49 | virtual const core::Property<bool>& can_go_previous() const; |
1364 | 48 | virtual const core::Property<bool>& can_go_next() const; | 50 | virtual const core::Property<bool>& can_go_next() const; |
1365 | 51 | virtual const core::Property<bool>& is_video_source() const; | ||
1366 | 52 | virtual const core::Property<bool>& is_audio_source() const; | ||
1367 | 49 | virtual const core::Property<PlaybackStatus>& playback_status() const; | 53 | virtual const core::Property<PlaybackStatus>& playback_status() const; |
1368 | 50 | virtual const core::Property<LoopStatus>& loop_status() const; | 54 | virtual const core::Property<LoopStatus>& loop_status() const; |
1369 | 51 | virtual const core::Property<PlaybackRate>& playback_rate() const; | 55 | virtual const core::Property<PlaybackRate>& playback_rate() const; |
1370 | @@ -63,6 +67,7 @@ | |||
1371 | 63 | virtual core::Property<Volume>& volume(); | 67 | virtual core::Property<Volume>& volume(); |
1372 | 64 | 68 | ||
1373 | 65 | virtual const core::Signal<uint64_t>& seeked_to() const; | 69 | virtual const core::Signal<uint64_t>& seeked_to() const; |
1374 | 70 | virtual const core::Signal<void>& end_of_stream() const; | ||
1375 | 66 | 71 | ||
1376 | 67 | protected: | 72 | protected: |
1377 | 68 | PlayerSkeleton(const core::dbus::types::ObjectPath& session_path); | 73 | PlayerSkeleton(const core::dbus::types::ObjectPath& session_path); |
1378 | @@ -73,12 +78,17 @@ | |||
1379 | 73 | virtual core::Property<bool>& can_seek(); | 78 | virtual core::Property<bool>& can_seek(); |
1380 | 74 | virtual core::Property<bool>& can_go_previous(); | 79 | virtual core::Property<bool>& can_go_previous(); |
1381 | 75 | virtual core::Property<bool>& can_go_next(); | 80 | virtual core::Property<bool>& can_go_next(); |
1382 | 81 | virtual core::Property<bool>& is_video_source(); | ||
1383 | 82 | virtual core::Property<bool>& is_audio_source(); | ||
1384 | 76 | virtual core::Property<Track::MetaData>& meta_data_for_current_track(); | 83 | virtual core::Property<Track::MetaData>& meta_data_for_current_track(); |
1385 | 77 | virtual core::Property<PlaybackRate>& minimum_playback_rate(); | 84 | virtual core::Property<PlaybackRate>& minimum_playback_rate(); |
1386 | 78 | virtual core::Property<PlaybackRate>& maximum_playback_rate(); | 85 | virtual core::Property<PlaybackRate>& maximum_playback_rate(); |
1387 | 79 | virtual core::Property<uint64_t>& position(); | 86 | virtual core::Property<uint64_t>& position(); |
1388 | 80 | virtual core::Property<uint64_t>& duration(); | 87 | virtual core::Property<uint64_t>& duration(); |
1389 | 81 | 88 | ||
1390 | 89 | virtual core::Signal<uint64_t>& seeked_to(); | ||
1391 | 90 | virtual core::Signal<void>& end_of_stream(); | ||
1392 | 91 | |||
1393 | 82 | private: | 92 | private: |
1394 | 83 | struct Private; | 93 | struct Private; |
1395 | 84 | std::unique_ptr<Private> d; | 94 | std::unique_ptr<Private> d; |
1396 | 85 | 95 | ||
1397 | === modified file 'src/core/media/player_stub.cpp' | |||
1398 | --- src/core/media/player_stub.cpp 2014-02-20 19:05:17 +0000 | |||
1399 | +++ src/core/media/player_stub.cpp 2014-04-17 21:13:23 +0000 | |||
1400 | @@ -1,5 +1,5 @@ | |||
1401 | 1 | /* | 1 | /* |
1403 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2013-2014 Canonical Ltd. |
1404 | 3 | * | 3 | * |
1405 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1406 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1407 | @@ -31,8 +31,14 @@ | |||
1408 | 31 | #include <core/dbus/property.h> | 31 | #include <core/dbus/property.h> |
1409 | 32 | #include <core/dbus/types/object_path.h> | 32 | #include <core/dbus/types/object_path.h> |
1410 | 33 | 33 | ||
1411 | 34 | // Hybris | ||
1412 | 35 | #include <hybris/media/media_codec_layer.h> | ||
1413 | 36 | #include <hybris/media/surface_texture_client_hybris.h> | ||
1414 | 37 | |||
1415 | 34 | #include <limits> | 38 | #include <limits> |
1416 | 35 | 39 | ||
1417 | 40 | #define UNUSED __attribute__((unused)) | ||
1418 | 41 | |||
1419 | 36 | namespace dbus = core::dbus; | 42 | namespace dbus = core::dbus; |
1420 | 37 | namespace media = core::ubuntu::media; | 43 | namespace media = core::ubuntu::media; |
1421 | 38 | 44 | ||
1422 | @@ -42,6 +48,12 @@ | |||
1423 | 42 | const std::shared_ptr<dbus::Service>& remote, | 48 | const std::shared_ptr<dbus::Service>& remote, |
1424 | 43 | const dbus::types::ObjectPath& path | 49 | const dbus::types::ObjectPath& path |
1425 | 44 | ) : parent(parent), | 50 | ) : parent(parent), |
1426 | 51 | texture_id(0), | ||
1427 | 52 | igbc_wrapper(nullptr), | ||
1428 | 53 | glc_wrapper(nullptr), | ||
1429 | 54 | decoding_session(decoding_service_create_session()), | ||
1430 | 55 | frame_available_cb(nullptr), | ||
1431 | 56 | frame_available_context(nullptr), | ||
1432 | 45 | path(path), | 57 | path(path), |
1433 | 46 | object(remote->object_for_path(path)), | 58 | object(remote->object_for_path(path)), |
1434 | 47 | properties | 59 | properties |
1435 | @@ -52,6 +64,8 @@ | |||
1436 | 52 | object->get_property<mpris::Player::Properties::CanControl>(), | 64 | object->get_property<mpris::Player::Properties::CanControl>(), |
1437 | 53 | object->get_property<mpris::Player::Properties::CanGoNext>(), | 65 | object->get_property<mpris::Player::Properties::CanGoNext>(), |
1438 | 54 | object->get_property<mpris::Player::Properties::CanGoPrevious>(), | 66 | object->get_property<mpris::Player::Properties::CanGoPrevious>(), |
1439 | 67 | object->get_property<mpris::Player::Properties::IsVideoSource>(), | ||
1440 | 68 | object->get_property<mpris::Player::Properties::IsAudioSource>(), | ||
1441 | 55 | object->get_property<mpris::Player::Properties::PlaybackStatus>(), | 69 | object->get_property<mpris::Player::Properties::PlaybackStatus>(), |
1442 | 56 | object->get_property<mpris::Player::Properties::LoopStatus>(), | 70 | object->get_property<mpris::Player::Properties::LoopStatus>(), |
1443 | 57 | object->get_property<mpris::Player::Properties::PlaybackRate>(), | 71 | object->get_property<mpris::Player::Properties::PlaybackRate>(), |
1444 | @@ -62,13 +76,67 @@ | |||
1445 | 62 | object->get_property<mpris::Player::Properties::Duration>(), | 76 | object->get_property<mpris::Player::Properties::Duration>(), |
1446 | 63 | object->get_property<mpris::Player::Properties::MinimumRate>(), | 77 | object->get_property<mpris::Player::Properties::MinimumRate>(), |
1447 | 64 | object->get_property<mpris::Player::Properties::MaximumRate>() | 78 | object->get_property<mpris::Player::Properties::MaximumRate>() |
1448 | 79 | }, | ||
1449 | 80 | signals | ||
1450 | 81 | { | ||
1451 | 82 | object->get_signal<mpris::Player::Signals::Seeked>(), | ||
1452 | 83 | object->get_signal<mpris::Player::Signals::EndOfStream>() | ||
1453 | 65 | } | 84 | } |
1454 | 66 | { | 85 | { |
1455 | 67 | } | 86 | } |
1456 | 68 | 87 | ||
1457 | 88 | ~Private() | ||
1458 | 89 | { | ||
1459 | 90 | } | ||
1460 | 91 | |||
1461 | 92 | static void on_frame_available_cb(UNUSED GLConsumerWrapperHybris wrapper, void *context) | ||
1462 | 93 | { | ||
1463 | 94 | if (context != nullptr) { | ||
1464 | 95 | Private *p = static_cast<Private*>(context); | ||
1465 | 96 | p->on_frame_available(); | ||
1466 | 97 | } | ||
1467 | 98 | else | ||
1468 | 99 | std::cout << "context is nullptr, can't call on_frame_available()" << std::endl; | ||
1469 | 100 | } | ||
1470 | 101 | |||
1471 | 102 | void on_frame_available() | ||
1472 | 103 | { | ||
1473 | 104 | if (frame_available_cb != nullptr) { | ||
1474 | 105 | frame_available_cb(frame_available_context); | ||
1475 | 106 | } | ||
1476 | 107 | else | ||
1477 | 108 | std::cout << "frame_available_cb is nullptr, can't call frame_available_cb()" << std::endl; | ||
1478 | 109 | } | ||
1479 | 110 | |||
1480 | 111 | void set_frame_available_cb(FrameAvailableCb cb, void *context) | ||
1481 | 112 | { | ||
1482 | 113 | frame_available_cb = cb; | ||
1483 | 114 | frame_available_context = context; | ||
1484 | 115 | |||
1485 | 116 | gl_consumer_set_frame_available_cb(glc_wrapper, &Private::on_frame_available_cb, static_cast<void*>(this)); | ||
1486 | 117 | } | ||
1487 | 118 | |||
1488 | 119 | /** We need a GLConsumerHybris instance for doing texture streaming over the | ||
1489 | 120 | * process boundary **/ | ||
1490 | 121 | void get_gl_consumer() | ||
1491 | 122 | { | ||
1492 | 123 | igbc_wrapper = decoding_service_get_igraphicbufferconsumer(); | ||
1493 | 124 | glc_wrapper = gl_consumer_create_by_id_with_igbc(texture_id, igbc_wrapper); | ||
1494 | 125 | |||
1495 | 126 | } | ||
1496 | 127 | |||
1497 | 69 | std::shared_ptr<Service> parent; | 128 | std::shared_ptr<Service> parent; |
1498 | 70 | std::shared_ptr<TrackList> track_list; | 129 | std::shared_ptr<TrackList> track_list; |
1499 | 71 | 130 | ||
1500 | 131 | uint32_t texture_id; | ||
1501 | 132 | IGBCWrapperHybris igbc_wrapper; | ||
1502 | 133 | GLConsumerWrapperHybris glc_wrapper; | ||
1503 | 134 | |||
1504 | 135 | DSSessionWrapperHybris decoding_session; | ||
1505 | 136 | |||
1506 | 137 | FrameAvailableCb frame_available_cb; | ||
1507 | 138 | void *frame_available_context; | ||
1508 | 139 | |||
1509 | 72 | dbus::Bus::Ptr bus; | 140 | dbus::Bus::Ptr bus; |
1510 | 73 | dbus::types::ObjectPath path; | 141 | dbus::types::ObjectPath path; |
1511 | 74 | dbus::Object::Ptr object; | 142 | dbus::Object::Ptr object; |
1512 | @@ -81,6 +149,8 @@ | |||
1513 | 81 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control; | 149 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanControl>> can_control; |
1514 | 82 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next; | 150 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoNext>> can_go_next; |
1515 | 83 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous; | 151 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::CanGoPrevious>> can_go_previous; |
1516 | 152 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsVideoSource>> is_video_source; | ||
1517 | 153 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::IsAudioSource>> is_audio_source; | ||
1518 | 84 | 154 | ||
1519 | 85 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status; | 155 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::PlaybackStatus>> playback_status; |
1520 | 86 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status; | 156 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::LoopStatus>> loop_status; |
1521 | @@ -93,6 +163,56 @@ | |||
1522 | 93 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate; | 163 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MinimumRate>> minimum_playback_rate; |
1523 | 94 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate; | 164 | std::shared_ptr<core::dbus::Property<mpris::Player::Properties::MaximumRate>> maximum_playback_rate; |
1524 | 95 | } properties; | 165 | } properties; |
1525 | 166 | |||
1526 | 167 | struct Signals | ||
1527 | 168 | { | ||
1528 | 169 | typedef core::dbus::Signal<mpris::Player::Signals::Seeked, mpris::Player::Signals::Seeked::ArgumentType> DBusSeekedToSignal; | ||
1529 | 170 | typedef core::dbus::Signal<mpris::Player::Signals::EndOfStream, mpris::Player::Signals::EndOfStream::ArgumentType> DBusEndOfStreamSignal; | ||
1530 | 171 | |||
1531 | 172 | Signals(const std::shared_ptr<DBusSeekedToSignal>& seeked, | ||
1532 | 173 | const std::shared_ptr<DBusEndOfStreamSignal>& eos) | ||
1533 | 174 | : dbus | ||
1534 | 175 | { | ||
1535 | 176 | seeked, | ||
1536 | 177 | eos | ||
1537 | 178 | }, | ||
1538 | 179 | playback_complete_cb(nullptr), | ||
1539 | 180 | playback_complete_context(nullptr), | ||
1540 | 181 | seeked_to(), | ||
1541 | 182 | end_of_stream() | ||
1542 | 183 | { | ||
1543 | 184 | dbus.seeked_to->connect([this](std::uint64_t value) | ||
1544 | 185 | { | ||
1545 | 186 | std::cout << "seeked_to signal arrived via the bus." << std::endl; | ||
1546 | 187 | seeked_to(value); | ||
1547 | 188 | }); | ||
1548 | 189 | |||
1549 | 190 | dbus.end_of_stream->connect([this]() | ||
1550 | 191 | { | ||
1551 | 192 | std::cout << "EndOfStream signal arrived via the bus." << std::endl; | ||
1552 | 193 | if (playback_complete_cb) | ||
1553 | 194 | playback_complete_cb(playback_complete_context); | ||
1554 | 195 | end_of_stream(); | ||
1555 | 196 | }); | ||
1556 | 197 | } | ||
1557 | 198 | |||
1558 | 199 | struct DBus | ||
1559 | 200 | { | ||
1560 | 201 | std::shared_ptr<DBusSeekedToSignal> seeked_to; | ||
1561 | 202 | std::shared_ptr<DBusEndOfStreamSignal> end_of_stream; | ||
1562 | 203 | } dbus; | ||
1563 | 204 | |||
1564 | 205 | void set_playback_complete_cb(PlaybackCompleteCb cb, void *context) | ||
1565 | 206 | { | ||
1566 | 207 | playback_complete_cb = cb; | ||
1567 | 208 | playback_complete_context = context; | ||
1568 | 209 | } | ||
1569 | 210 | |||
1570 | 211 | PlaybackCompleteCb playback_complete_cb; | ||
1571 | 212 | void *playback_complete_context; | ||
1572 | 213 | core::Signal<uint64_t> seeked_to; | ||
1573 | 214 | core::Signal<void> end_of_stream; | ||
1574 | 215 | } signals; | ||
1575 | 96 | }; | 216 | }; |
1576 | 97 | 217 | ||
1577 | 98 | media::PlayerStub::PlayerStub( | 218 | media::PlayerStub::PlayerStub( |
1578 | @@ -101,6 +221,11 @@ | |||
1579 | 101 | : dbus::Stub<Player>(the_session_bus()), | 221 | : dbus::Stub<Player>(the_session_bus()), |
1580 | 102 | d(new Private{parent, access_service(), object_path}) | 222 | d(new Private{parent, access_service(), object_path}) |
1581 | 103 | { | 223 | { |
1582 | 224 | auto bus = the_session_bus(); | ||
1583 | 225 | worker = std::move(std::thread([bus]() | ||
1584 | 226 | { | ||
1585 | 227 | bus->run(); | ||
1586 | 228 | })); | ||
1587 | 104 | } | 229 | } |
1588 | 105 | 230 | ||
1589 | 106 | media::PlayerStub::~PlayerStub() | 231 | media::PlayerStub::~PlayerStub() |
1590 | @@ -125,6 +250,21 @@ | |||
1591 | 125 | return op.value(); | 250 | return op.value(); |
1592 | 126 | } | 251 | } |
1593 | 127 | 252 | ||
1594 | 253 | void media::PlayerStub::create_video_sink(uint32_t texture_id) | ||
1595 | 254 | { | ||
1596 | 255 | auto op = d->object->invoke_method_synchronously<mpris::Player::CreateVideoSink, void>(texture_id); | ||
1597 | 256 | d->texture_id = texture_id; | ||
1598 | 257 | d->get_gl_consumer(); | ||
1599 | 258 | |||
1600 | 259 | if (op.is_error()) | ||
1601 | 260 | throw std::runtime_error("Problem creating new video sink instance on remote object"); | ||
1602 | 261 | } | ||
1603 | 262 | |||
1604 | 263 | GLConsumerWrapperHybris media::PlayerStub::gl_consumer() const | ||
1605 | 264 | { | ||
1606 | 265 | return d->glc_wrapper; | ||
1607 | 266 | } | ||
1608 | 267 | |||
1609 | 128 | void media::PlayerStub::next() | 268 | void media::PlayerStub::next() |
1610 | 129 | { | 269 | { |
1611 | 130 | auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>(); | 270 | auto op = d->object->invoke_method_synchronously<mpris::Player::Next, void>(); |
1612 | @@ -173,6 +313,16 @@ | |||
1613 | 173 | throw std::runtime_error("Problem stopping playback on remote object"); | 313 | throw std::runtime_error("Problem stopping playback on remote object"); |
1614 | 174 | } | 314 | } |
1615 | 175 | 315 | ||
1616 | 316 | void media::PlayerStub::set_frame_available_callback(FrameAvailableCb cb, void *context) | ||
1617 | 317 | { | ||
1618 | 318 | d->set_frame_available_cb(cb, context); | ||
1619 | 319 | } | ||
1620 | 320 | |||
1621 | 321 | void media::PlayerStub::set_playback_complete_callback(PlaybackCompleteCb cb, void *context) | ||
1622 | 322 | { | ||
1623 | 323 | d->signals.set_playback_complete_cb(cb, context); | ||
1624 | 324 | } | ||
1625 | 325 | |||
1626 | 176 | const core::Property<bool>& media::PlayerStub::can_play() const | 326 | const core::Property<bool>& media::PlayerStub::can_play() const |
1627 | 177 | { | 327 | { |
1628 | 178 | return *d->properties.can_play; | 328 | return *d->properties.can_play; |
1629 | @@ -198,6 +348,16 @@ | |||
1630 | 198 | return *d->properties.can_go_next; | 348 | return *d->properties.can_go_next; |
1631 | 199 | } | 349 | } |
1632 | 200 | 350 | ||
1633 | 351 | const core::Property<bool>& media::PlayerStub::is_video_source() const | ||
1634 | 352 | { | ||
1635 | 353 | return *d->properties.is_video_source; | ||
1636 | 354 | } | ||
1637 | 355 | |||
1638 | 356 | const core::Property<bool>& media::PlayerStub::is_audio_source() const | ||
1639 | 357 | { | ||
1640 | 358 | return *d->properties.is_audio_source; | ||
1641 | 359 | } | ||
1642 | 360 | |||
1643 | 201 | const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const | 361 | const core::Property<media::Player::PlaybackStatus>& media::PlayerStub::playback_status() const |
1644 | 202 | { | 362 | { |
1645 | 203 | return *d->properties.playback_status; | 363 | return *d->properties.playback_status; |
1646 | @@ -270,6 +430,10 @@ | |||
1647 | 270 | 430 | ||
1648 | 271 | const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const | 431 | const core::Signal<uint64_t>& media::PlayerStub::seeked_to() const |
1649 | 272 | { | 432 | { |
1652 | 273 | static core::Signal<uint64_t> signal; | 433 | return d->signals.seeked_to; |
1653 | 274 | return signal; | 434 | } |
1654 | 435 | |||
1655 | 436 | const core::Signal<void>& media::PlayerStub::end_of_stream() const | ||
1656 | 437 | { | ||
1657 | 438 | return d->signals.end_of_stream; | ||
1658 | 275 | } | 439 | } |
1659 | 276 | 440 | ||
1660 | === modified file 'src/core/media/player_stub.h' | |||
1661 | --- src/core/media/player_stub.h 2014-02-18 19:27:01 +0000 | |||
1662 | +++ src/core/media/player_stub.h 2014-04-17 21:13:23 +0000 | |||
1663 | @@ -45,6 +45,8 @@ | |||
1664 | 45 | virtual std::shared_ptr<TrackList> track_list(); | 45 | virtual std::shared_ptr<TrackList> track_list(); |
1665 | 46 | 46 | ||
1666 | 47 | virtual bool open_uri(const Track::UriType& uri); | 47 | virtual bool open_uri(const Track::UriType& uri); |
1667 | 48 | virtual void create_video_sink(uint32_t texture_id); | ||
1668 | 49 | virtual GLConsumerWrapperHybris gl_consumer() const; | ||
1669 | 48 | virtual void next(); | 50 | virtual void next(); |
1670 | 49 | virtual void previous(); | 51 | virtual void previous(); |
1671 | 50 | virtual void play(); | 52 | virtual void play(); |
1672 | @@ -52,11 +54,16 @@ | |||
1673 | 52 | virtual void seek_to(const std::chrono::microseconds& offset); | 54 | virtual void seek_to(const std::chrono::microseconds& offset); |
1674 | 53 | virtual void stop(); | 55 | virtual void stop(); |
1675 | 54 | 56 | ||
1676 | 57 | virtual void set_frame_available_callback(FrameAvailableCb cb, void *context); | ||
1677 | 58 | virtual void set_playback_complete_callback(PlaybackCompleteCb cb, void *context); | ||
1678 | 59 | |||
1679 | 55 | virtual const core::Property<bool>& can_play() const; | 60 | virtual const core::Property<bool>& can_play() const; |
1680 | 56 | virtual const core::Property<bool>& can_pause() const; | 61 | virtual const core::Property<bool>& can_pause() const; |
1681 | 57 | virtual const core::Property<bool>& can_seek() const; | 62 | virtual const core::Property<bool>& can_seek() const; |
1682 | 58 | virtual const core::Property<bool>& can_go_previous() const; | 63 | virtual const core::Property<bool>& can_go_previous() const; |
1683 | 59 | virtual const core::Property<bool>& can_go_next() const; | 64 | virtual const core::Property<bool>& can_go_next() const; |
1684 | 65 | virtual const core::Property<bool>& is_video_source() const; | ||
1685 | 66 | virtual const core::Property<bool>& is_audio_source() const; | ||
1686 | 60 | virtual const core::Property<PlaybackStatus>& playback_status() const; | 67 | virtual const core::Property<PlaybackStatus>& playback_status() const; |
1687 | 61 | virtual const core::Property<LoopStatus>& loop_status() const; | 68 | virtual const core::Property<LoopStatus>& loop_status() const; |
1688 | 62 | virtual const core::Property<PlaybackRate>& playback_rate() const; | 69 | virtual const core::Property<PlaybackRate>& playback_rate() const; |
1689 | @@ -74,10 +81,12 @@ | |||
1690 | 74 | virtual core::Property<Volume>& volume(); | 81 | virtual core::Property<Volume>& volume(); |
1691 | 75 | 82 | ||
1692 | 76 | virtual const core::Signal<uint64_t>& seeked_to() const; | 83 | virtual const core::Signal<uint64_t>& seeked_to() const; |
1693 | 84 | virtual const core::Signal<void>& end_of_stream() const; | ||
1694 | 77 | 85 | ||
1695 | 78 | private: | 86 | private: |
1696 | 79 | struct Private; | 87 | struct Private; |
1697 | 80 | std::unique_ptr<Private> d; | 88 | std::unique_ptr<Private> d; |
1698 | 89 | std::thread worker; | ||
1699 | 81 | }; | 90 | }; |
1700 | 82 | } | 91 | } |
1701 | 83 | } | 92 | } |
1702 | 84 | 93 | ||
1703 | === modified file 'src/core/media/server/server.cpp' | |||
1704 | --- src/core/media/server/server.cpp 2014-02-12 15:53:57 +0000 | |||
1705 | +++ src/core/media/server/server.cpp 2014-04-17 21:13:23 +0000 | |||
1706 | @@ -1,13 +1,41 @@ | |||
1707 | 1 | /* | ||
1708 | 2 | * Copyright (C) 2014 Canonical Ltd | ||
1709 | 3 | * | ||
1710 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
1711 | 5 | * you may not use this file except in compliance with the License. | ||
1712 | 6 | * You may obtain a copy of the License at | ||
1713 | 7 | * | ||
1714 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
1715 | 9 | * | ||
1716 | 10 | * Unless required by applicable law or agreed to in writing, software | ||
1717 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
1718 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
1719 | 13 | * See the License for the specific language governing permissions and | ||
1720 | 14 | * limitations under the License. | ||
1721 | 15 | * | ||
1722 | 16 | * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | ||
1723 | 17 | */ | ||
1724 | 18 | |||
1725 | 1 | #include <core/media/service.h> | 19 | #include <core/media/service.h> |
1726 | 2 | #include <core/media/player.h> | 20 | #include <core/media/player.h> |
1727 | 3 | #include <core/media/track_list.h> | 21 | #include <core/media/track_list.h> |
1728 | 4 | 22 | ||
1729 | 23 | #include <hybris/media/media_codec_layer.h> | ||
1730 | 24 | |||
1731 | 5 | #include "core/media/service_implementation.h" | 25 | #include "core/media/service_implementation.h" |
1732 | 6 | 26 | ||
1733 | 27 | #include <iostream> | ||
1734 | 28 | |||
1735 | 7 | namespace media = core::ubuntu::media; | 29 | namespace media = core::ubuntu::media; |
1736 | 8 | 30 | ||
1737 | 31 | using namespace std; | ||
1738 | 32 | |||
1739 | 9 | int main() | 33 | int main() |
1740 | 10 | { | 34 | { |
1741 | 35 | // Init hybris-level DecodingService | ||
1742 | 36 | decoding_service_init(); | ||
1743 | 37 | cout << "Starting DecodingService..." << endl; | ||
1744 | 38 | |||
1745 | 11 | auto service = std::make_shared<media::ServiceImplementation>(); | 39 | auto service = std::make_shared<media::ServiceImplementation>(); |
1746 | 12 | service->run(); | 40 | service->run(); |
1747 | 13 | 41 | ||
1748 | 14 | 42 | ||
1749 | === modified file 'src/core/media/service.cpp' | |||
1750 | --- src/core/media/service.cpp 2014-01-17 20:58:31 +0000 | |||
1751 | +++ src/core/media/service.cpp 2014-04-17 21:13:23 +0000 | |||
1752 | @@ -24,7 +24,7 @@ | |||
1753 | 24 | 24 | ||
1754 | 25 | const std::shared_ptr<media::Service> media::Service::Client::instance() | 25 | const std::shared_ptr<media::Service> media::Service::Client::instance() |
1755 | 26 | { | 26 | { |
1757 | 27 | std::cout << "Creating a new Service instance" << std::endl; | 27 | std::cout << "Creating a new static Service instance" << std::endl; |
1758 | 28 | static std::shared_ptr<media::Service> instance{new media::ServiceStub()}; | 28 | static std::shared_ptr<media::Service> instance{new media::ServiceStub()}; |
1759 | 29 | return instance; | 29 | return instance; |
1760 | 30 | } | 30 | } |
1761 | 31 | 31 | ||
1762 | === modified file 'src/core/media/track_list_implementation.cpp' | |||
1763 | --- src/core/media/track_list_implementation.cpp 2014-02-12 15:53:57 +0000 | |||
1764 | +++ src/core/media/track_list_implementation.cpp 2014-04-17 21:13:23 +0000 | |||
1765 | @@ -16,6 +16,9 @@ | |||
1766 | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> | 16 | * Authored by: Thomas Voß <thomas.voss@canonical.com> |
1767 | 17 | */ | 17 | */ |
1768 | 18 | 18 | ||
1769 | 19 | #include <stdio.h> | ||
1770 | 20 | #include <stdlib.h> | ||
1771 | 21 | |||
1772 | 19 | #include "track_list_implementation.h" | 22 | #include "track_list_implementation.h" |
1773 | 20 | 23 | ||
1774 | 21 | #include "engine.h" | 24 | #include "engine.h" |
1775 | @@ -45,6 +48,16 @@ | |||
1776 | 45 | { | 48 | { |
1777 | 46 | } | 49 | } |
1778 | 47 | 50 | ||
1779 | 51 | media::Track::UriType media::TrackListImplementation::query_uri_for_track(const media::Track::Id& id) | ||
1780 | 52 | { | ||
1781 | 53 | auto it = d->meta_data_cache.find(id); | ||
1782 | 54 | |||
1783 | 55 | if (it == d->meta_data_cache.end()) | ||
1784 | 56 | return Track::UriType{}; | ||
1785 | 57 | |||
1786 | 58 | return std::get<0>(it->second); | ||
1787 | 59 | } | ||
1788 | 60 | |||
1789 | 48 | media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id) | 61 | media::Track::MetaData media::TrackListImplementation::query_meta_data_for_track(const media::Track::Id& id) |
1790 | 49 | { | 62 | { |
1791 | 50 | auto it = d->meta_data_cache.find(id); | 63 | auto it = d->meta_data_cache.find(id); |
1792 | 51 | 64 | ||
1793 | === modified file 'src/core/media/track_list_implementation.h' | |||
1794 | --- src/core/media/track_list_implementation.h 2014-02-12 15:53:57 +0000 | |||
1795 | +++ src/core/media/track_list_implementation.h 2014-04-17 21:13:23 +0000 | |||
1796 | @@ -36,6 +36,7 @@ | |||
1797 | 36 | const std::shared_ptr<Engine::MetaDataExtractor>& extractor); | 36 | const std::shared_ptr<Engine::MetaDataExtractor>& extractor); |
1798 | 37 | ~TrackListImplementation(); | 37 | ~TrackListImplementation(); |
1799 | 38 | 38 | ||
1800 | 39 | Track::UriType query_uri_for_track(const Track::Id& id); | ||
1801 | 39 | Track::MetaData query_meta_data_for_track(const Track::Id& id); | 40 | Track::MetaData query_meta_data_for_track(const Track::Id& id); |
1802 | 40 | 41 | ||
1803 | 41 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); | 42 | void add_track_with_uri_at(const Track::UriType& uri, const Track::Id& position, bool make_current); |
1804 | 42 | 43 | ||
1805 | === modified file 'src/core/media/track_list_skeleton.cpp' | |||
1806 | --- src/core/media/track_list_skeleton.cpp 2014-02-12 15:53:57 +0000 | |||
1807 | +++ src/core/media/track_list_skeleton.cpp 2014-04-17 21:13:23 +0000 | |||
1808 | @@ -48,7 +48,8 @@ | |||
1809 | 48 | object(object), | 48 | object(object), |
1810 | 49 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), | 49 | can_edit_tracks(object->get_property<mpris::TrackList::Properties::CanEditTracks>()), |
1811 | 50 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()), | 50 | tracks(object->get_property<mpris::TrackList::Properties::Tracks>()), |
1813 | 51 | current_track(tracks->get().begin()) | 51 | current_track(tracks->get().begin()), |
1814 | 52 | empty_iterator(tracks->get().begin()) | ||
1815 | 52 | { | 53 | { |
1816 | 53 | } | 54 | } |
1817 | 54 | 55 | ||
1818 | @@ -103,6 +104,7 @@ | |||
1819 | 103 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; | 104 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::CanEditTracks>> can_edit_tracks; |
1820 | 104 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; | 105 | std::shared_ptr<core::dbus::Property<mpris::TrackList::Properties::Tracks>> tracks; |
1821 | 105 | TrackList::ConstIterator current_track; | 106 | TrackList::ConstIterator current_track; |
1822 | 107 | TrackList::ConstIterator empty_iterator; | ||
1823 | 106 | 108 | ||
1824 | 107 | core::Signal<void> on_track_list_replaced; | 109 | core::Signal<void> on_track_list_replaced; |
1825 | 108 | core::Signal<Track::Id> on_track_added; | 110 | core::Signal<Track::Id> on_track_added; |
1826 | @@ -142,12 +144,22 @@ | |||
1827 | 142 | 144 | ||
1828 | 143 | bool media::TrackListSkeleton::has_next() const | 145 | bool media::TrackListSkeleton::has_next() const |
1829 | 144 | { | 146 | { |
1831 | 145 | return std::next(d->current_track) != d->tracks->get().end(); | 147 | return d->current_track != d->tracks->get().end(); |
1832 | 146 | } | 148 | } |
1833 | 147 | 149 | ||
1834 | 148 | const media::Track::Id& media::TrackListSkeleton::next() | 150 | const media::Track::Id& media::TrackListSkeleton::next() |
1835 | 149 | { | 151 | { |
1837 | 150 | return *(d->current_track = std::next(d->current_track)); | 152 | if (d->tracks->get().empty()) |
1838 | 153 | return *(d->current_track); | ||
1839 | 154 | |||
1840 | 155 | if (d->tracks->get().size() && (d->current_track == d->empty_iterator)) | ||
1841 | 156 | { | ||
1842 | 157 | d->current_track = d->tracks->get().begin(); | ||
1843 | 158 | return *(d->current_track = std::next(d->current_track)); | ||
1844 | 159 | } | ||
1845 | 160 | |||
1846 | 161 | d->current_track = std::next(d->current_track); | ||
1847 | 162 | return *(d->current_track); | ||
1848 | 151 | } | 163 | } |
1849 | 152 | 164 | ||
1850 | 153 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const | 165 | const core::Property<bool>& media::TrackListSkeleton::can_edit_tracks() const |
1851 | 154 | 166 | ||
1852 | === modified file 'src/core/media/track_list_skeleton.h' | |||
1853 | --- src/core/media/track_list_skeleton.h 2014-02-12 15:53:57 +0000 | |||
1854 | +++ src/core/media/track_list_skeleton.h 2014-04-17 21:13:23 +0000 | |||
1855 | @@ -48,9 +48,10 @@ | |||
1856 | 48 | const core::Signal<Track::Id>& on_track_removed() const; | 48 | const core::Signal<Track::Id>& on_track_removed() const; |
1857 | 49 | const core::Signal<Track::Id>& on_track_changed() const; | 49 | const core::Signal<Track::Id>& on_track_changed() const; |
1858 | 50 | 50 | ||
1859 | 51 | core::Property<Container>& tracks(); | ||
1860 | 52 | |||
1861 | 51 | protected: | 53 | protected: |
1862 | 52 | core::Property<bool>& can_edit_tracks(); | 54 | core::Property<bool>& can_edit_tracks(); |
1863 | 53 | core::Property<Container>& tracks(); | ||
1864 | 54 | 55 | ||
1865 | 55 | core::Signal<void>& on_track_list_replaced(); | 56 | core::Signal<void>& on_track_list_replaced(); |
1866 | 56 | core::Signal<Track::Id>& on_track_added(); | 57 | core::Signal<Track::Id>& on_track_added(); |
1867 | 57 | 58 | ||
1868 | === modified file 'tests/acceptance-tests/service.cpp' | |||
1869 | --- tests/acceptance-tests/service.cpp 2014-03-06 19:23:19 +0000 | |||
1870 | +++ tests/acceptance-tests/service.cpp 2014-04-17 21:13:23 +0000 | |||
1871 | @@ -1,5 +1,5 @@ | |||
1872 | 1 | /* | 1 | /* |
1874 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2013-2014 Canonical Ltd. |
1875 | 3 | * | 3 | * |
1876 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1877 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1878 | 6 | 6 | ||
1879 | === modified file 'tests/unit-tests/CMakeLists.txt' | |||
1880 | --- tests/unit-tests/CMakeLists.txt 2014-01-17 20:58:31 +0000 | |||
1881 | +++ tests/unit-tests/CMakeLists.txt 2014-04-17 21:13:23 +0000 | |||
1882 | @@ -1,10 +1,21 @@ | |||
1883 | 1 | include_directories( | 1 | include_directories( |
1884 | 2 | . | 2 | . |
1885 | 3 | ${CMAKE_SOURCE_DIR}/src | 3 | ${CMAKE_SOURCE_DIR}/src |
1886 | 4 | ${PC_GSTREAMER_1_0_INCLUDE_DIRS} | ||
1887 | 4 | ) | 5 | ) |
1888 | 5 | 6 | ||
1889 | 6 | add_executable( | 7 | add_executable( |
1890 | 7 | test-gstreamer-engine | 8 | test-gstreamer-engine |
1891 | 9 | |||
1892 | 10 | libmedia-mock.cpp | ||
1893 | 11 | ${CMAKE_SOURCE_DIR}/src/core/media/engine.cpp | ||
1894 | 12 | ${CMAKE_SOURCE_DIR}/src/core/media/gstreamer/engine.cpp | ||
1895 | 13 | ${CMAKE_SOURCE_DIR}/src/core/media/player_skeleton.cpp | ||
1896 | 14 | ${CMAKE_SOURCE_DIR}/src/core/media/player_implementation.cpp | ||
1897 | 15 | ${CMAKE_SOURCE_DIR}/src/core/media/service_skeleton.cpp | ||
1898 | 16 | ${CMAKE_SOURCE_DIR}/src/core/media/service_implementation.cpp | ||
1899 | 17 | ${CMAKE_SOURCE_DIR}/src/core/media/track_list_skeleton.cpp | ||
1900 | 18 | ${CMAKE_SOURCE_DIR}/src/core/media/track_list_implementation.cpp | ||
1901 | 8 | test-gstreamer-engine.cpp | 19 | test-gstreamer-engine.cpp |
1902 | 9 | ) | 20 | ) |
1903 | 10 | 21 | ||
1904 | @@ -13,12 +24,15 @@ | |||
1905 | 13 | 24 | ||
1906 | 14 | media-hub-common | 25 | media-hub-common |
1907 | 15 | media-hub-client | 26 | media-hub-client |
1908 | 16 | media-hub-service | ||
1909 | 17 | media-hub-test-framework | 27 | media-hub-test-framework |
1910 | 18 | 28 | ||
1911 | 19 | ${CMAKE_THREAD_LIBS_INIT} | 29 | ${CMAKE_THREAD_LIBS_INIT} |
1912 | 20 | ${Boost_LIBRARIES} | 30 | ${Boost_LIBRARIES} |
1913 | 21 | ${DBUS_LIBRARIES} | 31 | ${DBUS_LIBRARIES} |
1914 | 32 | ${DBUS_CPP_LDFLAGS} | ||
1915 | 33 | ${GLog_LIBRARY} | ||
1916 | 34 | ${PC_GSTREAMER_1_0_LIBRARIES} | ||
1917 | 35 | ${GIO_LIBRARIES} | ||
1918 | 22 | 36 | ||
1919 | 23 | gmock | 37 | gmock |
1920 | 24 | gmock_main | 38 | gmock_main |
1921 | 25 | 39 | ||
1922 | === added file 'tests/unit-tests/libmedia-mock.cpp' | |||
1923 | --- tests/unit-tests/libmedia-mock.cpp 1970-01-01 00:00:00 +0000 | |||
1924 | +++ tests/unit-tests/libmedia-mock.cpp 2014-04-17 21:13:23 +0000 | |||
1925 | @@ -0,0 +1,26 @@ | |||
1926 | 1 | /* | ||
1927 | 2 | * Copyright © 2013-2014 Canonical Ltd. | ||
1928 | 3 | * | ||
1929 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1930 | 5 | * under the terms of the GNU Lesser General Public License version 3, | ||
1931 | 6 | * as published by the Free Software Foundation. | ||
1932 | 7 | * | ||
1933 | 8 | * This program is distributed in the hope that it will be useful, | ||
1934 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1935 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1936 | 11 | * GNU Lesser General Public License for more details. | ||
1937 | 12 | * | ||
1938 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
1939 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1940 | 15 | * | ||
1941 | 16 | * Authored by: Jim Hodapp <jim.hodapp@canonical.com> | ||
1942 | 17 | */ | ||
1943 | 18 | |||
1944 | 19 | #include <hybris/media/media_codec_layer.h> | ||
1945 | 20 | #include <hybris/media/surface_texture_client_hybris.h> | ||
1946 | 21 | |||
1947 | 22 | #define UNUSED __attribute__((unused)) | ||
1948 | 23 | |||
1949 | 24 | void decoding_service_set_client_death_cb(UNUSED DecodingClientDeathCbHybris callback, UNUSED void *context) | ||
1950 | 25 | { | ||
1951 | 26 | } | ||
1952 | 0 | 27 | ||
1953 | === modified file 'tests/unit-tests/test-gstreamer-engine.cpp' | |||
1954 | --- tests/unit-tests/test-gstreamer-engine.cpp 2014-02-26 14:58:36 +0000 | |||
1955 | +++ tests/unit-tests/test-gstreamer-engine.cpp 2014-04-17 21:13:23 +0000 | |||
1956 | @@ -1,5 +1,5 @@ | |||
1957 | 1 | /* | 1 | /* |
1959 | 2 | * Copyright © 2013 Canonical Ltd. | 2 | * Copyright © 2013-2014 Canonical Ltd. |
1960 | 3 | * | 3 | * |
1961 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
1962 | 5 | * under the terms of the GNU Lesser General Public License version 3, | 5 | * under the terms of the GNU Lesser General Public License version 3, |
1963 | @@ -198,7 +198,7 @@ | |||
1964 | 198 | std::chrono::seconds{40})); | 198 | std::chrono::seconds{40})); |
1965 | 199 | } | 199 | } |
1966 | 200 | 200 | ||
1968 | 201 | TEST(GStreamerEngine, DISABLED_stop_pause_play_seek_video_works) | 201 | TEST(GStreamerEngine, stop_pause_play_seek_video_works) |
1969 | 202 | { | 202 | { |
1970 | 203 | const std::string test_file{"/tmp/h264.avi"}; | 203 | const std::string test_file{"/tmp/h264.avi"}; |
1971 | 204 | const std::string test_file_uri{"file:///tmp/h264.avi"}; | 204 | const std::string test_file_uri{"file:///tmp/h264.avi"}; |
1972 | @@ -248,8 +248,8 @@ | |||
1973 | 248 | 248 | ||
1974 | 249 | TEST(GStreamerEngine, get_position_duration_work) | 249 | TEST(GStreamerEngine, get_position_duration_work) |
1975 | 250 | { | 250 | { |
1978 | 251 | const std::string test_file{"/tmp/test.ogg"}; | 251 | const std::string test_file{"/tmp/h264.avi"}; |
1979 | 252 | const std::string test_file_uri{"file:///tmp/test.ogg"}; | 252 | const std::string test_file_uri{"file:///tmp/h264.avi"}; |
1980 | 253 | std::remove(test_file.c_str()); | 253 | std::remove(test_file.c_str()); |
1981 | 254 | ASSERT_TRUE(test::copy_test_ogg_file_to(test_file)); | 254 | ASSERT_TRUE(test::copy_test_ogg_file_to(test_file)); |
1982 | 255 | 255 | ||
1983 | @@ -269,10 +269,18 @@ | |||
1984 | 269 | EXPECT_TRUE(wst.wait_for_state_for( | 269 | EXPECT_TRUE(wst.wait_for_state_for( |
1985 | 270 | core::ubuntu::media::Engine::State::playing, | 270 | core::ubuntu::media::Engine::State::playing, |
1986 | 271 | std::chrono::milliseconds{4000})); | 271 | std::chrono::milliseconds{4000})); |
1991 | 272 | sleep(1); | 272 | |
1992 | 273 | 273 | EXPECT_TRUE(engine.seek_to(std::chrono::seconds{10})); | |
1993 | 274 | // FIXME: Ideally we want to seek_to and measure the position there, but seek_to seems | 274 | EXPECT_TRUE(engine.play()); |
1994 | 275 | // broken from within this unit test | 275 | EXPECT_TRUE(wst.wait_for_state_for( |
1995 | 276 | core::ubuntu::media::Engine::State::playing, | ||
1996 | 277 | std::chrono::milliseconds{4000})); | ||
1997 | 278 | |||
1998 | 279 | std::cout << "position: " << engine.position() << std::endl; | ||
1999 | 280 | std::cout << "duration: " << engine.duration() << std::endl; | ||
2000 | 281 | |||
2001 | 282 | // FIXME: This should be 10e9, but seek_to seems to be broken from within this unit test | ||
2002 | 283 | // and I haven't been able to figure out why | ||
2003 | 276 | EXPECT_TRUE(engine.position() > 1e9); | 284 | EXPECT_TRUE(engine.position() > 1e9); |
2004 | 277 | 285 | ||
2005 | 278 | EXPECT_TRUE(engine.duration() > 1e9); | 286 | EXPECT_TRUE(engine.duration() > 1e9); |
FAILED: Continuous integration, rev:36 /code.launchpad .net/~jhodapp/ media-hub/ video-support/ +merge/ 212905/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ media-hub- ci/30/ jenkins. qa.ubuntu. com/job/ media-hub- trusty- amd64-ci/ 31/console jenkins. qa.ubuntu. com/job/ media-hub- trusty- armhf-ci/ 30/console jenkins. qa.ubuntu. com/job/ media-hub- trusty- i386-ci/ 30/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/media- hub-ci/ 30/rebuild
http://