Merge lp:~audience-members/audience/gtk-3.12 into lp:~audience-members/audience/trunk

Proposed by Corentin Noël
Status: Merged
Approved by: Cody Garver
Approved revision: 355
Merged at revision: 351
Proposed branch: lp:~audience-members/audience/gtk-3.12
Merge into: lp:~audience-members/audience/trunk
Diff against target: 4734 lines (+1792/-2173)
27 files modified
CMakeLists.txt (+3/-59)
cmake/FindGirCompiler.cmake (+56/-0)
cmake/GObjectIntrospectionMacros.cmake (+34/-0)
cmake/Makefile (+0/-286)
cmake/Translations.cmake (+37/-12)
cmake/ValaPrecompile.cmake (+75/-12)
data/CMakeLists.txt (+12/-0)
data/org.pantheon.audience.gschema.xml (+10/-5)
src/Audience.vala (+467/-473)
src/CMakeLists.txt (+57/-0)
src/Consts.vala (+3/-2)
src/DiskManager.vala (+98/-0)
src/Settings.vala (+35/-18)
src/Utils.vala (+56/-202)
src/Widgets/BottomBar.vala (+160/-0)
src/Widgets/Button.vala (+0/-53)
src/Widgets/ControlsBar.vala (+0/-137)
src/Widgets/LLabel.vala (+0/-27)
src/Widgets/MediaSlider.vala (+0/-238)
src/Widgets/Playlist.vala (+92/-57)
src/Widgets/PlaylistPopover.vala (+116/-0)
src/Widgets/PreviewPopover.vala (+90/-0)
src/Widgets/SettingsPopover.vala (+166/-0)
src/Widgets/TagView.vala (+0/-253)
src/Widgets/TimeWidget.vala (+127/-0)
src/Widgets/TopPanel.vala (+0/-87)
src/Widgets/VideoPlayer.vala (+98/-252)
To merge this branch: bzr merge lp:~audience-members/audience/gtk-3.12
Reviewer Review Type Date Requested Status
Cody Garver Needs Fixing
Robert Roth (community) Abstain
Review via email: mp+223919@code.launchpad.net

Commit message

Ported all UI widgets to pure Gtk 3.12

Description of the change

Ported all UI widgets to pure Gtk.

To post a comment you must log in.
348. By Corentin Noël

Synchronized with trunk.

Revision history for this message
Robert Roth (evfool) wrote :

I have tested this branch a few times, felt stable and working. Just for nitpicking: The diff seems a bit hard to read, given that some changes not necessarily related to GTK-3.12 migration have been added (e.g. CMake file splitting per subdir for data and src, generated Makefile removal), those might be better in separate merges, but necessary. If no one else has objections against those being in this one, I'll give this an approve.

review: Abstain
Revision history for this message
David Gomes (davidgomes) wrote :

Agreed with Robert here. Corentin, can you explain us if any of these changes included in this branch (mentioned by Robert) have anything to do with GTK+ 3.12?

Revision history for this message
Corentin Noël (tintou) wrote :

They are not Gtk3.12 related but they are a full part of the project
reorganization (if you look at the changes, a lot of code has been removed).
Le 21 juin 2014 14:45, "David Gomes" <email address hidden> a écrit :

> Agreed with Robert here. Corentin, can you explain us if any of these
> changes included in this branch (mentioned by Robert) have anything to do
> with GTK+ 3.12?
> --
>
> https://code.launchpad.net/~audience-members/audience/gtk-3.12/+merge/223919
> You proposed lp:~audience-members/audience/gtk-3.12 for merging.
>

Revision history for this message
Cody Garver (codygarver) wrote :

- Each video in the playlist is duplicated 01.mkv 01.mkv 02.mkv 02.mkv

- This video doesn't show the controls for me unless I fullscreen then unfullscreen:
  https://slack-files.com/T028SLY6K-F02CDA4MD-c12d7c

- More than 1 video in the playlist requires a scrollbar even if there's available space above

- This video has black bars on the left and right when played windowed:
  https://slack-files.com/T028SLY6K-F02CE461E-df989c

review: Needs Fixing
Revision history for this message
Cody Garver (codygarver) wrote :

Also doesn't properly detect/display the Audio and Subtitle of the video with black bars I linked

review: Needs Fixing
349. By Corentin Noël

Multiple Fixes to the interface.

350. By Corentin Noël

Fix Aspect not replacing the bottombar.

Revision history for this message
Corentin Noël (tintou) wrote :

Cody: I've pushed a fix for the problems you pointed out.

351. By Cody Garver

Add a couple spaces in CMakeLists.txt

352. By Cody Garver

Merge in trunk

Revision history for this message
Cody Garver (codygarver) wrote :

I'm still getting black bars on left/right of this video in windowed mode https://slack-files.com/T028SLY6K-F02CE461E-df989c

review: Needs Fixing
Revision history for this message
Cody Garver (codygarver) wrote :

- Welcome screen does no longer offers to resume last played video

- Welcome screen always offers to play a DVD

review: Needs Fixing
353. By Cody Garver

Restore comment about C warnings

Revision history for this message
Cody Garver (codygarver) wrote :

private void on_destroy () has a block of commented out code

review: Needs Fixing
Revision history for this message
Corentin Noël (tintou) wrote :

I only have black bars on left/right black bars because the video size>screen size. You maybe have an higher resolution as me.

354. By Corentin Noël

Check if the media is a DVD or BlueRay.

355. By Corentin Noël

Fixed saving videos when closing the application.

Revision history for this message
Cody Garver (codygarver) wrote :

Every video has black bars on the side, my display resolution is 1080p

Revision history for this message
Robert Roth (evfool) wrote :

@Cody Garver: Do you get the black bars only in windowed mode? For FullHD movies (e.g. one MKV anime you've shared on slack) for me the black bars only appear in windowed mode, fullscreen is true fullscreen without black bars.

Revision history for this message
Danielle Foré (danrabbit) wrote :

I can confirm that the black bars on the side show up in windowed, but not fullscreen

Revision history for this message
Cody Garver (codygarver) wrote :

Well black bars are happening for me with trunk now too. The problem is outside of this branch?

Revision history for this message
Robert Roth (evfool) wrote :

It looks that the headerbar is the thing to blame on this branch, commenting the set_titlebar line out fixes the issue.
In case of an 1280x720 video the window size is set to 1280x720 (+decorations) in case there is no headerbar, and with headerbar the size is also set to 1280x720, but that includes the CSD size, so the size allocated to the clutterembed is only 1174x572. The headerbar height for me is 42px, so strangely, that's not the only difference.

Revision history for this message
Corentin Noël (tintou) wrote :

For CSD windows, the size also contains shadows so it's maybe linked. In all cases i don't think it's a merge-blocker…

Revision history for this message
Cody Garver (codygarver) wrote :

It is indeed export GTK_CSD=1 that causes the bug, not your fault tintou

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-05-02 13:04:44 +0000
3+++ CMakeLists.txt 2014-07-06 11:18:29 +0000
4@@ -4,7 +4,7 @@
5 enable_testing ()
6 list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
7
8-project (audience)
9+project (audience C)
10
11 set (DATADIR ${CMAKE_INSTALL_PREFIX}/share)
12 set (PKGDATADIR ${DATADIR}/${CMAKE_PROJECT_NAME})
13@@ -18,17 +18,6 @@
14 # Comment this out to enable C compiler warnings
15 add_definitions (-w)
16
17-# Data
18-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/16/audience.svg DESTINATION ${DATADIR}/icons/hicolor/16x16/apps/)
19-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/24/audience.svg DESTINATION ${DATADIR}/icons/hicolor/24x24/apps/)
20-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/32/audience.svg DESTINATION ${DATADIR}/icons/hicolor/32x32/apps/)
21-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/48/audience.svg DESTINATION ${DATADIR}/icons/hicolor/48x48/apps/)
22-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/64/audience.svg DESTINATION ${DATADIR}/icons/hicolor/64x64/apps/)
23-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/icons/128/audience.svg DESTINATION ${DATADIR}/icons/hicolor/128x128/apps/)
24-install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/audience.desktop DESTINATION ${DATADIR}/applications/)
25-
26-# Configure file
27-configure_file (${CMAKE_SOURCE_DIR}/src/Config.vala.cmake ${CMAKE_BINARY_DIR}/src/Config.vala)
28
29 set (CPACK_PACKAGE_VERSION ${VERSION})
30 set (CPACK_SOURCE_GENERATOR "TGZ")
31@@ -38,54 +27,9 @@
32 include (CPack)
33 add_custom_target (dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
34
35-find_package (PkgConfig)
36-pkg_check_modules (DEPS REQUIRED granite clutter-gtk-1.0 gstreamer-1.0 gstreamer-pbutils-1.0 gstreamer-tag-1.0)
37-
38-add_definitions (${DEPS_CFLAGS})
39-link_libraries (${DEPS_LIBRARIES})
40-link_directories (${DEPS_LIBRARY_DIRS})
41-find_package (Vala REQUIRED)
42-include (ValaVersion)
43-
44-ensure_vala_version ("0.16.1" MINIMUM)
45-
46-include (ValaPrecompile)
47-vala_precompile (VALA_C
48- ${CMAKE_BINARY_DIR}/src/Config.vala
49- src/Audience.vala
50- src/Consts.vala
51- src/desktop-launcher.vala
52- src/Settings.vala
53- src/Utils.vala
54- src/Widgets/Button.vala
55- src/Widgets/ControlsBar.vala
56- src/Widgets/LLabel.vala
57- src/Widgets/MediaSlider.vala
58- src/Widgets/Playlist.vala
59- src/Widgets/TagView.vala
60- src/Widgets/TopPanel.vala
61- src/Widgets/VideoPlayer.vala
62-PACKAGES
63- clutter-gtk-1.0
64- granite
65- gdk-x11-3.0
66- gstreamer-1.0
67- gstreamer-pbutils-1.0
68- gstreamer-tag-1.0
69-OPTIONS
70- --enable-experimental
71- --target-glib=2.32
72- --thread
73- -g
74-)
75-
76-
77-include (GSettings)
78-add_schema ("data/org.pantheon.audience.gschema.xml")
79-
80+add_subdirectory (src)
81+add_subdirectory (data)
82 add_subdirectory (po)
83-add_executable (${CMAKE_PROJECT_NAME} ${VALA_C})
84-install (TARGETS ${CMAKE_PROJECT_NAME} RUNTIME DESTINATION bin)
85
86 # uninstall target
87 configure_file (
88
89=== added file 'cmake/FindGirCompiler.cmake'
90--- cmake/FindGirCompiler.cmake 1970-01-01 00:00:00 +0000
91+++ cmake/FindGirCompiler.cmake 2014-07-06 11:18:29 +0000
92@@ -0,0 +1,56 @@
93+##
94+# Copyright 2009-2010 Jakob Westhoff. All rights reserved.
95+#
96+# Redistribution and use in source and binary forms, with or without
97+# modification, are permitted provided that the following conditions are met:
98+#
99+# 1. Redistributions of source code must retain the above copyright notice,
100+# this list of conditions and the following disclaimer.
101+#
102+# 2. Redistributions in binary form must reproduce the above copyright notice,
103+# this list of conditions and the following disclaimer in the documentation
104+# and/or other materials provided with the distribution.
105+#
106+# THIS SOFTWARE IS PROVIDED BY JAKOB WESTHOFF ``AS IS'' AND ANY EXPRESS OR
107+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
108+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
109+# EVENT SHALL JAKOB WESTHOFF OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
110+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
111+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
112+# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
113+# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
114+# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
115+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
116+#
117+# The views and conclusions contained in the software and documentation are those
118+# of the authors and should not be interpreted as representing official policies,
119+# either expressed or implied, of Jakob Westhoff
120+##
121+
122+##
123+# Find module for the Gir compiler (g-ir-compiler)
124+#
125+# This module determines wheter a Gir compiler is installed on the current
126+# system and where its executable is.
127+#
128+# Call the module using "find_package(GirCompiler) from within your CMakeLists.txt.
129+#
130+# The following variables will be set after an invocation:
131+#
132+# G_IR_COMPILER_FOUND Whether the g-ir-compiler compiler has been found or not
133+# G_IR_COMPILER_EXECUTABLE Full path to the g-ir-compiler executable if it has been found
134+##
135+
136+
137+# Search for the g-ir-compiler executable in the usual system paths.
138+find_program (G_IR_COMPILER_EXECUTABLE
139+ NAMES g-ir-compiler)
140+
141+# Handle the QUIETLY and REQUIRED arguments, which may be given to the find call.
142+# Furthermore set G_IR_COMPILER_FOUND to TRUE if the g-ir-compiler has been found (aka.
143+# G_IR_COMPILER_EXECUTABLE is set)
144+
145+include (FindPackageHandleStandardArgs)
146+find_package_handle_standard_args (GirCompiler DEFAULT_MSG G_IR_COMPILER_EXECUTABLE)
147+
148+mark_as_advanced (G_IR_COMPILER_EXECUTABLE)
149
150=== added file 'cmake/GObjectIntrospectionMacros.cmake'
151--- cmake/GObjectIntrospectionMacros.cmake 1970-01-01 00:00:00 +0000
152+++ cmake/GObjectIntrospectionMacros.cmake 2014-07-06 11:18:29 +0000
153@@ -0,0 +1,34 @@
154+macro(add_target_gir TARGET_NAME GIR_NAME HEADER CFLAGS GRANITE_VERSION)
155+ set(PACKAGES "")
156+ foreach(PKG ${ARGN})
157+ set(PACKAGES ${PACKAGES} --include=${PKG})
158+ endforeach()
159+ install(CODE "set(ENV{LD_LIBRARY_PATH} \"${CMAKE_CURRENT_BINARY_DIR}:\$ENV{LD_LIBRARY_PATH}\")
160+ execute_process(COMMAND g-ir-scanner ${CFLAGS} -n ${GIR_NAME}
161+ --quiet
162+ --library ${TARGET_NAME} ${PACKAGES}
163+ -o ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir
164+ -L${CMAKE_CURRENT_BINARY_DIR}
165+ --nsversion=${GRANITE_VERSION} ${HEADER})")
166+ install(CODE "execute_process(COMMAND g-ir-compiler ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir -o ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.typelib)")
167+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir DESTINATION share/gir-1.0/)
168+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.typelib DESTINATION lib/girepository-1.0/)
169+endmacro()
170+
171+macro(add_target_gir_with_executable TARGET_NAME EXE_NAME GIR_NAME HEADER EXE_HEADER CFLAGS GRANITE_VERSION)
172+ set(PACKAGES "")
173+ foreach(PKG ${ARGN})
174+ set(PACKAGES ${PACKAGES} --include=${PKG})
175+ endforeach()
176+ install(CODE "set(ENV{LD_LIBRARY_PATH} \"${CMAKE_CURRENT_BINARY_DIR}:\$ENV{LD_LIBRARY_PATH}\")
177+ execute_process(COMMAND g-ir-scanner ${CFLAGS} -n ${GIR_NAME}
178+ --quiet
179+ --library ${TARGET_NAME} --program ${EXE_NAME} ${PACKAGES}
180+ -o ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir
181+ -L${CMAKE_CURRENT_BINARY_DIR}
182+ -I${CMAKE_CURRENT_BINARY_DIR}
183+ --nsversion=${GRANITE_VERSION} ${HEADER} ${EXE_HEADER})")
184+ install(CODE "execute_process(COMMAND g-ir-compiler ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir -o ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.typelib)")
185+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.gir DESTINATION share/gir-1.0/)
186+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${GIR_NAME}-${GRANITE_VERSION}.typelib DESTINATION lib/girepository-1.0/)
187+endmacro()
188
189=== removed file 'cmake/Makefile'
190--- cmake/Makefile 2011-12-13 18:08:48 +0000
191+++ cmake/Makefile 1970-01-01 00:00:00 +0000
192@@ -1,286 +0,0 @@
193-# CMAKE generated file: DO NOT EDIT!
194-# Generated by "Unix Makefiles" Generator, CMake Version 2.8
195-
196-# Default target executed when no arguments are given to make.
197-default_target: all
198-.PHONY : default_target
199-
200-#=============================================================================
201-# Special targets provided by cmake.
202-
203-# Disable implicit rules so canoncical targets will work.
204-.SUFFIXES:
205-
206-# Remove some rules from gmake that .SUFFIXES does not remove.
207-SUFFIXES =
208-
209-.SUFFIXES: .hpux_make_needs_suffix_list
210-
211-# Suppress display of executed commands.
212-$(VERBOSE).SILENT:
213-
214-# A target that is always out of date.
215-cmake_force:
216-.PHONY : cmake_force
217-
218-#=============================================================================
219-# Set environment variables for the build.
220-
221-# The shell in which to execute make rules.
222-SHELL = /bin/sh
223-
224-# The CMake executable.
225-CMAKE_COMMAND = /usr/bin/cmake
226-
227-# The command to remove a file.
228-RM = /usr/bin/cmake -E remove -f
229-
230-# The top-level source directory on which CMake was run.
231-CMAKE_SOURCE_DIR = /home/mefrio/Scrivania/cmake
232-
233-# The top-level build directory on which CMake was run.
234-CMAKE_BINARY_DIR = /home/mefrio/Scrivania/cmake/cmake
235-
236-#=============================================================================
237-# Targets provided globally by CMake.
238-
239-# Special rule for the target edit_cache
240-edit_cache:
241- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running interactive CMake command-line interface..."
242- /usr/bin/cmake -i .
243-.PHONY : edit_cache
244-
245-# Special rule for the target edit_cache
246-edit_cache/fast: edit_cache
247-.PHONY : edit_cache/fast
248-
249-# Special rule for the target install
250-install: preinstall
251- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
252- /usr/bin/cmake -P cmake_install.cmake
253-.PHONY : install
254-
255-# Special rule for the target install
256-install/fast: preinstall/fast
257- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
258- /usr/bin/cmake -P cmake_install.cmake
259-.PHONY : install/fast
260-
261-# Special rule for the target install/local
262-install/local: preinstall
263- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
264- /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
265-.PHONY : install/local
266-
267-# Special rule for the target install/local
268-install/local/fast: install/local
269-.PHONY : install/local/fast
270-
271-# Special rule for the target install/strip
272-install/strip: preinstall
273- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
274- /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
275-.PHONY : install/strip
276-
277-# Special rule for the target install/strip
278-install/strip/fast: install/strip
279-.PHONY : install/strip/fast
280-
281-# Special rule for the target list_install_components
282-list_install_components:
283- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
284-.PHONY : list_install_components
285-
286-# Special rule for the target list_install_components
287-list_install_components/fast: list_install_components
288-.PHONY : list_install_components/fast
289-
290-# Special rule for the target rebuild_cache
291-rebuild_cache:
292- @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
293- /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
294-.PHONY : rebuild_cache
295-
296-# Special rule for the target rebuild_cache
297-rebuild_cache/fast: rebuild_cache
298-.PHONY : rebuild_cache/fast
299-
300-# The main all target
301-all: cmake_check_build_system
302- $(CMAKE_COMMAND) -E cmake_progress_start /home/mefrio/Scrivania/cmake/cmake/CMakeFiles /home/mefrio/Scrivania/cmake/cmake/CMakeFiles/progress.marks
303- $(MAKE) -f CMakeFiles/Makefile2 all
304- $(CMAKE_COMMAND) -E cmake_progress_start /home/mefrio/Scrivania/cmake/cmake/CMakeFiles 0
305-.PHONY : all
306-
307-# The main clean target
308-clean:
309- $(MAKE) -f CMakeFiles/Makefile2 clean
310-.PHONY : clean
311-
312-# The main clean target
313-clean/fast: clean
314-.PHONY : clean/fast
315-
316-# Prepare targets for installation.
317-preinstall: all
318- $(MAKE) -f CMakeFiles/Makefile2 preinstall
319-.PHONY : preinstall
320-
321-# Prepare targets for installation.
322-preinstall/fast:
323- $(MAKE) -f CMakeFiles/Makefile2 preinstall
324-.PHONY : preinstall/fast
325-
326-# clear depends
327-depend:
328- $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
329-.PHONY : depend
330-
331-#=============================================================================
332-# Target rules for targets named scratch
333-
334-# Build rule for target.
335-scratch: cmake_check_build_system
336- $(MAKE) -f CMakeFiles/Makefile2 scratch
337-.PHONY : scratch
338-
339-# fast build rule for target.
340-scratch/fast:
341- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/build
342-.PHONY : scratch/fast
343-
344-src/entry.o: src/entry.c.o
345-.PHONY : src/entry.o
346-
347-# target to build an object file
348-src/entry.c.o:
349- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/entry.c.o
350-.PHONY : src/entry.c.o
351-
352-src/entry.i: src/entry.c.i
353-.PHONY : src/entry.i
354-
355-# target to preprocess a source file
356-src/entry.c.i:
357- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/entry.c.i
358-.PHONY : src/entry.c.i
359-
360-src/entry.s: src/entry.c.s
361-.PHONY : src/entry.s
362-
363-# target to generate assembly for a file
364-src/entry.c.s:
365- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/entry.c.s
366-.PHONY : src/entry.c.s
367-
368-src/main_window.o: src/main_window.c.o
369-.PHONY : src/main_window.o
370-
371-# target to build an object file
372-src/main_window.c.o:
373- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/main_window.c.o
374-.PHONY : src/main_window.c.o
375-
376-src/main_window.i: src/main_window.c.i
377-.PHONY : src/main_window.i
378-
379-# target to preprocess a source file
380-src/main_window.c.i:
381- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/main_window.c.i
382-.PHONY : src/main_window.c.i
383-
384-src/main_window.s: src/main_window.c.s
385-.PHONY : src/main_window.s
386-
387-# target to generate assembly for a file
388-src/main_window.c.s:
389- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/main_window.c.s
390-.PHONY : src/main_window.c.s
391-
392-src/menu.o: src/menu.c.o
393-.PHONY : src/menu.o
394-
395-# target to build an object file
396-src/menu.c.o:
397- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/menu.c.o
398-.PHONY : src/menu.c.o
399-
400-src/menu.i: src/menu.c.i
401-.PHONY : src/menu.i
402-
403-# target to preprocess a source file
404-src/menu.c.i:
405- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/menu.c.i
406-.PHONY : src/menu.c.i
407-
408-src/menu.s: src/menu.c.s
409-.PHONY : src/menu.s
410-
411-# target to generate assembly for a file
412-src/menu.c.s:
413- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/menu.c.s
414-.PHONY : src/menu.c.s
415-
416-src/notebook.o: src/notebook.c.o
417-.PHONY : src/notebook.o
418-
419-# target to build an object file
420-src/notebook.c.o:
421- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/notebook.c.o
422-.PHONY : src/notebook.c.o
423-
424-src/notebook.i: src/notebook.c.i
425-.PHONY : src/notebook.i
426-
427-# target to preprocess a source file
428-src/notebook.c.i:
429- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/notebook.c.i
430-.PHONY : src/notebook.c.i
431-
432-src/notebook.s: src/notebook.c.s
433-.PHONY : src/notebook.s
434-
435-# target to generate assembly for a file
436-src/notebook.c.s:
437- $(MAKE) -f CMakeFiles/scratch.dir/build.make CMakeFiles/scratch.dir/src/notebook.c.s
438-.PHONY : src/notebook.c.s
439-
440-# Help Target
441-help:
442- @echo "The following are some of the valid targets for this Makefile:"
443- @echo "... all (the default if no target is provided)"
444- @echo "... clean"
445- @echo "... depend"
446- @echo "... edit_cache"
447- @echo "... install"
448- @echo "... install/local"
449- @echo "... install/strip"
450- @echo "... list_install_components"
451- @echo "... rebuild_cache"
452- @echo "... scratch"
453- @echo "... src/entry.o"
454- @echo "... src/entry.i"
455- @echo "... src/entry.s"
456- @echo "... src/main_window.o"
457- @echo "... src/main_window.i"
458- @echo "... src/main_window.s"
459- @echo "... src/menu.o"
460- @echo "... src/menu.i"
461- @echo "... src/menu.s"
462- @echo "... src/notebook.o"
463- @echo "... src/notebook.i"
464- @echo "... src/notebook.s"
465-.PHONY : help
466-
467-
468-
469-#=============================================================================
470-# Special targets to cleanup operation of make.
471-
472-# Special rule to run CMake to check the build system integrity.
473-# No rule that depends on this can have commands that come from listfiles
474-# because they might be regenerated.
475-cmake_check_build_system:
476- $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
477-.PHONY : cmake_check_build_system
478-
479
480=== modified file 'cmake/Translations.cmake'
481--- cmake/Translations.cmake 2012-06-07 15:38:06 +0000
482+++ cmake/Translations.cmake 2014-07-06 11:18:29 +0000
483@@ -20,22 +20,47 @@
484 add_custom_target (pot COMMENT “Building translation catalog.”)
485 find_program (XGETTEXT_EXECUTABLE xgettext)
486
487-
488 set(C_SOURCE "")
489+ set(VALA_SOURCE "")
490+ set(GLADE_SOURCE "")
491
492 foreach(FILES_INPUT ${ARGN})
493- file (GLOB SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.c)
494- foreach(C_FILE ${SOURCE_FILES})
495- set(C_SOURCE ${C_SOURCE} ${C_FILE})
496- endforeach()
497- file (GLOB SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT}/*.vala)
498- foreach(C_FILE ${SOURCE_FILES})
499- set(C_SOURCE ${C_SOURCE} ${C_FILE})
500+ set(BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${FILES_INPUT})
501+
502+ file (GLOB_RECURSE SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ ${BASE_DIRECTORY}/*.c)
503+ foreach(C_FILE ${SOURCE_FILES})
504+ set(C_SOURCE ${C_SOURCE} ${C_FILE})
505+ endforeach()
506+
507+ file (GLOB_RECURSE SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ ${BASE_DIRECTORY}/*.vala)
508+ foreach(VALA_C_FILE ${SOURCE_FILES})
509+ set(VALA_SOURCE ${VALA_SOURCE} ${VALA_C_FILE})
510+ endforeach()
511+
512+ file (GLOB_RECURSE SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ ${BASE_DIRECTORY}/*.ui)
513+ foreach(GLADE_C_FILE ${SOURCE_FILES})
514+ set(GLADE_SOURCE ${GLADE_SOURCE} ${GLADE_C_FILE})
515 endforeach()
516 endforeach()
517
518- add_custom_command (TARGET pot COMMAND
519- ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE} -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
520- ${VALA_SOURCE} ${C_SOURCE} --keyword="_" --keyword="N_" --from-code=UTF-8
521- )
522+ set(BASE_XGETTEXT_COMMAND
523+ ${XGETTEXT_EXECUTABLE} -d ${NLS_PACKAGE}
524+ -o ${CMAKE_CURRENT_SOURCE_DIR}/${NLS_PACKAGE}.pot
525+ --add-comments="/" --keyword="_" --keyword="N_" --keyword="C_:1c,2" --keyword="NC_:1c,2" --keyword="ngettext:1,2" --keyword="Q_:1g" --from-code=UTF-8)
526+
527+ set(CONTINUE_FLAG "")
528+
529+ IF(NOT "${C_SOURCE}" STREQUAL "")
530+ add_custom_command(TARGET pot WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${BASE_XGETTEXT_COMMAND} ${C_SOURCE})
531+ set(CONTINUE_FLAG "-j")
532+ ENDIF()
533+
534+ IF(NOT "${VALA_SOURCE}" STREQUAL "")
535+ add_custom_command(TARGET pot WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${BASE_XGETTEXT_COMMAND} ${CONTINUE_FLAG} -LC\# ${VALA_SOURCE})
536+ set(CONTINUE_FLAG "-j")
537+ ENDIF()
538+
539+ IF(NOT "${GLADE_SOURCE}" STREQUAL "")
540+ add_custom_command (TARGET pot WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMAND ${BASE_XGETTEXT_COMMAND} ${CONTINUE_FLAG} -LGlade ${GLADE_SOURCE})
541+ ENDIF()
542 endmacro()
543
544=== modified file 'cmake/ValaPrecompile.cmake'
545--- cmake/ValaPrecompile.cmake 2012-02-23 20:42:55 +0000
546+++ cmake/ValaPrecompile.cmake 2014-07-06 11:18:29 +0000
547@@ -1,5 +1,6 @@
548 ##
549 # Copyright 2009-2010 Jakob Westhoff. All rights reserved.
550+# Copyright 2012 elementary.
551 #
552 # Redistribution and use in source and binary forms, with or without
553 # modification, are permitted provided that the following conditions are met:
554@@ -74,10 +75,18 @@
555 # be a header file as well as an internal header file being generated called
556 # <provided_name>.h and <provided_name>_internal.h
557 #
558+# GENERATE_GIR
559+# Have the compiler generate a GObject-Introspection repository file with
560+# name: <provided_name>.gir. This can be later used to create a binary typelib
561+# using the GI compiler.
562+#
563+# GENERATE_SYMBOLS
564+# Output a <provided_name>.symbols file containing all the exported symbols.
565+#
566 # The following call is a simple example to the vala_precompile macro showing
567 # an example to every of the optional sections:
568 #
569-# vala_precompile(VALA_C
570+# vala_precompile(VALA_C mytargetname
571 # source1.vala
572 # source2.vala
573 # source3.vala
574@@ -95,14 +104,19 @@
575 # myvapi
576 # GENERATE_HEADER
577 # myheader
578+# GENERATE_GIR
579+# mygir
580+# GENERATE_SYMBOLS
581+# mysymbols
582 # )
583 #
584 # Most important is the variable VALA_C which will contain all the generated c
585 # file names after the call.
586 ##
587
588-macro(vala_precompile output)
589- parse_arguments(ARGS "PACKAGES;OPTIONS;DIRECTORY;GENERATE_HEADER;GENERATE_VAPI;CUSTOM_VAPIS" "" ${ARGN})
590+macro(vala_precompile output target_name)
591+ parse_arguments(ARGS "TARGET;PACKAGES;OPTIONS;DIRECTORY;GENERATE_GIR;GENERATE_SYMBOLS;GENERATE_HEADER;GENERATE_VAPI;CUSTOM_VAPIS" "" ${ARGN})
592+
593 if(ARGS_DIRECTORY)
594 set(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${ARGS_DIRECTORY})
595 else(ARGS_DIRECTORY)
596@@ -115,15 +129,17 @@
597 endforeach(pkg ${ARGS_PACKAGES})
598 set(in_files "")
599 set(out_files "")
600+ set(out_files_display "")
601 set(${output} "")
602+
603 foreach(src ${ARGS_DEFAULT_ARGS})
604- string(REPLACE ${CMAKE_CURRENT_SOURCE_DIR}/ "" src ${src})
605 string(REGEX MATCH "^/" IS_MATCHED ${src})
606 if(${IS_MATCHED} MATCHES "/")
607- list(APPEND in_files "${src}")
608+ set(src_file_path ${src})
609 else()
610- list(APPEND in_files "${CMAKE_CURRENT_SOURCE_DIR}/${src}")
611+ set(src_file_path ${CMAKE_CURRENT_SOURCE_DIR}/${src})
612 endif()
613+ list(APPEND in_files ${src_file_path})
614 string(REPLACE ".vala" ".c" src ${src})
615 string(REPLACE ".gs" ".c" src ${src})
616 if(${IS_MATCHED} MATCHES "/")
617@@ -135,6 +151,7 @@
618 list(APPEND out_files "${DIRECTORY}/${src}")
619 endif()
620 list(APPEND ${output} ${out_file})
621+ list(APPEND out_files_display "${src}")
622 endforeach(src ${ARGS_DEFAULT_ARGS})
623
624 set(custom_vapi_arguments "")
625@@ -151,7 +168,8 @@
626 set(vapi_arguments "")
627 if(ARGS_GENERATE_VAPI)
628 list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_VAPI}.vapi")
629- set(vapi_arguments "--internal-vapi=${ARGS_GENERATE_VAPI}.vapi")
630+ list(APPEND out_files_display "${ARGS_GENERATE_VAPI}.vapi")
631+ set(vapi_arguments "--library=${ARGS_GENERATE_VAPI}" "--vapi=${ARGS_GENERATE_VAPI}.vapi")
632
633 # Header and internal header is needed to generate internal vapi
634 if (NOT ARGS_GENERATE_HEADER)
635@@ -162,26 +180,71 @@
636 set(header_arguments "")
637 if(ARGS_GENERATE_HEADER)
638 list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
639- list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
640- list(APPEND header_arguments "--header=${DIRECTORY}/${ARGS_GENERATE_HEADER}.h")
641- list(APPEND header_arguments "--internal-header=${DIRECTORY}/${ARGS_GENERATE_HEADER}_internal.h")
642+ list(APPEND out_files_display "${ARGS_GENERATE_HEADER}.h")
643+ list(APPEND header_arguments "--header=${ARGS_GENERATE_HEADER}.h")
644 endif(ARGS_GENERATE_HEADER)
645
646- add_custom_command(OUTPUT ${out_files}
647+ set(gir_arguments "")
648+ set(gircomp_command "")
649+ if(ARGS_GENERATE_GIR)
650+ list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_GIR}.gir")
651+ list(APPEND out_files_display "${ARGS_GENERATE_GIR}.gir")
652+ set(gir_arguments "--gir=${ARGS_GENERATE_GIR}.gir")
653+
654+ include (FindGirCompiler)
655+ find_package(GirCompiler REQUIRED)
656+
657+ set(gircomp_command
658+ COMMAND
659+ ${G_IR_COMPILER_EXECUTABLE}
660+ ARGS
661+ "${DIRECTORY}/${ARGS_GENERATE_GIR}.gir"
662+ -o "${DIRECTORY}/${ARGS_GENERATE_GIR}.typelib")
663+ endif(ARGS_GENERATE_GIR)
664+
665+ set(symbols_arguments "")
666+ if(ARGS_GENERATE_SYMBOLS)
667+ list(APPEND out_files "${DIRECTORY}/${ARGS_GENERATE_SYMBOLS}.symbols")
668+ list(APPEND out_files_display "${ARGS_GENERATE_SYMBOLS}.symbols")
669+ set(symbols_arguments "--symbols=${ARGS_GENERATE_SYMBOLS}.symbols")
670+ endif(ARGS_GENERATE_SYMBOLS)
671+
672+ # Workaround for a bug that would make valac run twice. This file is written
673+ # after the vala compiler generates C source code.
674+ set(OUTPUT_STAMP ${CMAKE_CURRENT_BINARY_DIR}/${target_name}_valac.stamp)
675+
676+ add_custom_command(
677+ OUTPUT
678+ ${OUTPUT_STAMP}
679 COMMAND
680 ${VALA_EXECUTABLE}
681 ARGS
682 "-C"
683 ${header_arguments}
684- ${vapi_arguments}
685+ ${vapi_arguments}
686+ ${gir_arguments}
687+ ${symbols_arguments}
688 "-b" ${CMAKE_CURRENT_SOURCE_DIR}
689 "-d" ${DIRECTORY}
690 ${vala_pkg_opts}
691 ${ARGS_OPTIONS}
692+ "-g"
693+ "--save-temps"
694 ${in_files}
695 ${custom_vapi_arguments}
696+ COMMAND
697+ touch
698+ ARGS
699+ ${OUTPUT_STAMP}
700 DEPENDS
701 ${in_files}
702 ${ARGS_CUSTOM_VAPIS}
703+ COMMENT
704+ "Generating ${out_files_display}"
705+ ${gircomp_command}
706 )
707+
708+ # This command will be run twice for some reason (pass a non-empty string to COMMENT
709+ # in order to see it). Since valac is not executed from here, this won't be a problem.
710+ add_custom_command(OUTPUT ${out_files} DEPENDS ${OUTPUT_STAMP} COMMENT "")
711 endmacro(vala_precompile)
712
713=== added file 'data/CMakeLists.txt'
714--- data/CMakeLists.txt 1970-01-01 00:00:00 +0000
715+++ data/CMakeLists.txt 2014-07-06 11:18:29 +0000
716@@ -0,0 +1,12 @@
717+set (HICOLOR_DIR ${DATADIR}/icons/hicolor)
718+# Data
719+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/16/audience.svg DESTINATION ${HICOLOR_DIR}/16x16/apps/)
720+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/24/audience.svg DESTINATION ${HICOLOR_DIR}/24x24/apps/)
721+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/32/audience.svg DESTINATION ${HICOLOR_DIR}/32x32/apps/)
722+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/48/audience.svg DESTINATION ${HICOLOR_DIR}/48x48/apps/)
723+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/64/audience.svg DESTINATION ${HICOLOR_DIR}/64x64/apps/)
724+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/icons/128/audience.svg DESTINATION ${HICOLOR_DIR}/128x128/apps/)
725+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/audience.desktop DESTINATION ${DATADIR}/applications/)
726+
727+include(GSettings)
728+add_schema (org.pantheon.audience.gschema.xml)
729
730=== modified file 'data/org.pantheon.audience.gschema.xml'
731--- data/org.pantheon.audience.gschema.xml 2013-03-31 21:46:37 +0000
732+++ data/org.pantheon.audience.gschema.xml 2014-07-06 11:18:29 +0000
733@@ -15,10 +15,15 @@
734 <summary>Resume videos</summary>
735 <description>Resume video at the point they were stopped when audience was closed</description>
736 </key>
737- <key name="last-played-videos" type="s">
738- <default>""</default>
739- <summary>List of last played videos and the time they stopped</summary>
740- <description>A list of the last played and the time they were stopped</description>
741+ <key name="last-played-videos" type="as">
742+ <default>[]</default>
743+ <summary>List of last played videos</summary>
744+ <description>A list of the last played</description>
745+ </key>
746+ <key name="last-stopped" type="d">
747+ <default>0</default>
748+ <summary>Last stopped time of last played video</summary>
749+ <description>Last stopped time of last played video</description>
750 </key>
751 <key name="last-folder" type="s">
752 <default>"-1"</default>
753@@ -41,4 +46,4 @@
754 <description>Hide the window decorations. You can close the window with escape</description>
755 </key>
756 </schema>
757-</schemalist>
758+</schemalist>
759\ No newline at end of file
760
761=== modified file 'src/Audience.vala'
762--- src/Audience.vala 2014-05-25 13:34:00 +0000
763+++ src/Audience.vala 2014-07-06 11:18:29 +0000
764@@ -1,3 +1,23 @@
765+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
766+/*-
767+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
768+ *
769+ * This program is free software: you can redistribute it and/or modify
770+ * it under the terms of the GNU General Public License as published by
771+ * the Free Software Foundation, either version 3 of the License, or
772+ * (at your option) any later version.
773+
774+ * This program is distributed in the hope that it will be useful,
775+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
776+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
777+ * GNU General Public License for more details.
778+
779+ * You should have received a copy of the GNU General Public License
780+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
781+ *
782+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
783+ * Cody Garver <cody@elementaryos.org>
784+ */
785
786 /*
787 [CCode (cname="gst_navigation_query_parse_commands_length")]
788@@ -21,7 +41,7 @@
789 build_version = Constants.VERSION;
790 build_version_info = Constants.VERSION_INFO;
791
792- app_years = "2011-2013";
793+ app_years = "2011-2014";
794 app_icon = "audience";
795 app_launcher = "audience.desktop";
796 application_id = "net.launchpad.audience";
797@@ -40,27 +60,32 @@
798 }
799
800 public Gtk.Window mainwindow;
801- public Audience.Widgets.TagView tagview;
802 public GnomeMediaKeys mediakeys;
803 public Audience.Widgets.Playlist playlist;
804 public GtkClutter.Embed clutter;
805 public Granite.Widgets.Welcome welcome;
806- public Audience.Widgets.VideoPlayer video_player;
807-
808- public bool has_dvd;
809-
810- public List<string> last_played_videos; //taken from settings, but splitted
811+
812+ public bool fullscreened { get; set; }
813+
814+ private Audience.Widgets.VideoPlayer video_player;
815+ private Audience.Widgets.BottomBar bottom_bar;
816+ private Clutter.Stage stage;
817+ private Gtk.Revealer unfullscreen_bar;
818+ private GtkClutter.Actor bottom_actor;
819+ private GtkClutter.Actor unfullscreen_actor;
820+ private bool mouse_primary_down = false;
821+ private int bottom_bar_size = 0;
822
823 public GLib.VolumeMonitor monitor;
824-
825+
826 private const string[] SUBTITLE_EXTENSIONS = {
827- "sub",
828- "srt",
829- "smi",
830- "ssa",
831- "ass",
832- "asc"
833- };
834+ "sub",
835+ "srt",
836+ "smi",
837+ "ssa",
838+ "ass",
839+ "asc"
840+ };
841
842 public App () {
843 Granite.Services.Logger.DisplayLevel = Granite.Services.LogLevel.DEBUG;
844@@ -69,148 +94,77 @@
845 this.flags |= GLib.ApplicationFlags.HANDLES_OPEN;
846 }
847
848- void build ()
849- {
850+ void build () {
851 playlist = new Widgets.Playlist ();
852 settings = new Settings ();
853 mainwindow = new Gtk.Window ();
854- video_player = new Widgets.VideoPlayer ();
855- tagview = new Widgets.TagView (this);
856-
857- tagview.select_external_subtitle.connect (video_player.set_subtitle_uri);
858-
859- var mainbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
860+ video_player = Widgets.VideoPlayer.get_default ();
861+ video_player.notify["playing"].connect (() => {bottom_bar.toggle_play_pause ();});
862+
863 clutter = new GtkClutter.Embed ();
864
865- //prepare last played videos
866- last_played_videos = new List<string> ();
867- var split = settings.last_played_videos.split (",");;
868- for (var i=0;i<split.length;i++){
869- last_played_videos.append (split[i]);
870- }
871-
872- has_dvd = Audience.has_dvd ();
873-
874 if (settings.last_folder == "-1")
875 settings.last_folder = Environment.get_home_dir ();
876
877- welcome = new Granite.Widgets.Welcome (_("No Videos Open"), _("Select a source to begin playing."));
878- var open_file_welcome_index = welcome.append ("document-open", _("Open file"), _("Open a saved file."));
879-
880- var filename = last_played_videos.length () > 0 ? last_played_videos.nth_data (0) : "";
881- var last_file = File.new_for_uri (filename);
882-
883- var last_video_welcome_index = -1;
884- if (last_file.query_exists ()) {
885- last_video_welcome_index = welcome.append ("media-playback-start", _("Resume last video"), get_title (last_file.get_basename ()));
886- welcome.set_item_visible (last_video_welcome_index, last_played_videos.length () > 0);
887- }
888-
889- var dvd_welcome_index = welcome.append ("media-cdrom", _("Play from Disc"), _("Watch a DVD or open a file from disc"));
890- welcome.set_item_visible (dvd_welcome_index, has_dvd);
891-
892- var stage = clutter.get_stage ();
893+ stage = (Clutter.Stage)clutter.get_stage ();
894+ stage.background_color = {0, 0, 0, 0};
895+ stage.use_alpha = true;
896
897 video_player.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.WIDTH, 0));
898 video_player.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.HEIGHT, 0));
899
900 stage.add_child (video_player);
901- stage.add_child (tagview);
902- stage.background_color = {0, 0, 0};
903-
904- this.tagview.y = -10;
905- this.tagview.x = stage.width;
906- this.tagview.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.HEIGHT, -20));
907-
908+
909+ bottom_bar = new Widgets.BottomBar ();
910+ bottom_bar.set_valign (Gtk.Align.END);
911+ bottom_bar.play_toggled.connect (() => {video_player.playing = !video_player.playing;});
912+ bottom_bar.seeked.connect ((val) => {video_player.progress = val;});
913+ bottom_bar.unfullscreen.connect (() => {toggle_fullscreen ();});
914+
915+ //tagview.select_external_subtitle.connect (video_player.set_subtitle_uri);
916+
917+ unfullscreen_bar = bottom_bar.get_unfullscreen_button ();
918+
919+ bottom_actor = new GtkClutter.Actor.with_contents (bottom_bar);
920+ bottom_actor.opacity = GLOBAL_OPACITY;
921+ stage.add_child (bottom_actor);
922+
923+ unfullscreen_actor = new GtkClutter.Actor.with_contents (unfullscreen_bar);
924+ unfullscreen_actor.opacity = GLOBAL_OPACITY;
925+ stage.add_child (unfullscreen_actor);
926+
927+ setup_welcome_screen ();
928+
929+ var mainbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
930+ mainbox.pack_start (clutter);
931 mainbox.pack_start (welcome);
932- mainbox.pack_start (clutter);
933-
934- this.mainwindow.title = program_name;
935- this.mainwindow.window_position = Gtk.WindowPosition.CENTER;
936- this.mainwindow.set_application (this);
937- this.mainwindow.add (mainbox);
938- this.mainwindow.set_default_size (624, 352);
939- this.mainwindow.show_all ();
940+
941+ var header = new Gtk.HeaderBar ();
942+ header.set_show_close_button (true);
943+ header.get_style_context ().remove_class ("header-bar");
944+
945+ mainwindow.set_titlebar (header);
946+
947+ mainwindow.events |= Gdk.EventMask.POINTER_MOTION_MASK;
948+ mainwindow.events |= Gdk.EventMask.LEAVE_NOTIFY_MASK;
949+ mainwindow.events |= Gdk.EventMask.BUTTON_PRESS_MASK;
950+ mainwindow.title = program_name;
951+ mainwindow.window_position = Gtk.WindowPosition.CENTER;
952+ mainwindow.set_application (this);
953+ mainwindow.add (mainbox);
954+ mainwindow.set_default_size (624, 352);
955+ mainwindow.set_size_request (350, 300);
956+ mainwindow.show_all ();
957 if (!settings.show_window_decoration)
958- this.mainwindow.decorated = false;
959+ mainwindow.decorated = false;
960
961 clutter.hide ();
962
963- /*events*/
964- video_player.text_tags_changed.connect (tagview.setup_text_setup);
965- video_player.audio_tags_changed.connect (tagview.setup_audio_setup);
966-
967- //look for dvd
968- this.monitor = GLib.VolumeMonitor.get ();
969- monitor.drive_connected.connect ( (drive) => {
970- this.has_dvd = Audience.has_dvd ();
971- welcome.set_item_visible (dvd_welcome_index, this.has_dvd);
972- });
973- monitor.drive_disconnected.connect ( () => {
974- this.has_dvd = Audience.has_dvd ();
975- welcome.set_item_visible (dvd_welcome_index, this.has_dvd);
976- });
977- //playlist wants us to open a file
978- playlist.play.connect ( (file) => {
979- this.play_file (file.get_uri ());
980- });
981-
982- //handle welcome
983- welcome.activated.connect ( (index) => {
984- if (index == open_file_welcome_index) {
985- run_open_file ();
986- } else if (index == last_video_welcome_index) {
987- welcome.hide ();
988- clutter.show_all ();
989-
990- open_file (filename);
991-
992- video_player.playing = false;
993- video_player.progress = double.parse (last_played_videos.nth_data (1));
994- video_player.playing = true;
995- } else if (index == dvd_welcome_index) {
996- run_open_dvd ();
997- } else {
998- var d = new Gtk.Dialog.with_buttons (_("Open location"),
999- this.mainwindow, Gtk.DialogFlags.MODAL,
1000- Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL,
1001- Gtk.Stock.OK, Gtk.ResponseType.OK);
1002-
1003- var grid = new Gtk.Grid ();
1004- var entry = new Gtk.Entry ();
1005-
1006- grid.attach (new Gtk.Image.from_icon_name ("internet-web-browser",
1007- Gtk.IconSize.DIALOG), 0, 0, 1, 2);
1008- grid.attach (new Gtk.Label (_("Choose location")), 1, 0, 1, 1);
1009- grid.attach (entry, 1, 1, 1, 1);
1010-
1011- ((Gtk.Container)d.get_content_area ()).add (grid);
1012- grid.show_all ();
1013-
1014- if (d.run () == Gtk.ResponseType.OK) {
1015- open_file (entry.text, true);
1016- video_player.playing = true;
1017- welcome.hide ();
1018- clutter.show_all ();
1019- }
1020- d.destroy ();
1021- }
1022-
1023- int current_state = mainwindow.get_window ().get_state ();
1024- bool currently_maximized = (current_state & Gdk.WindowState.MAXIMIZED) != 0;
1025-
1026- // video is playing and we are maximized, go fullscreen
1027- if (video_player.playing && currently_maximized) {
1028- mainwindow.fullscreen ();
1029- video_player.fullscreened = true;
1030- }
1031- });
1032-
1033 //media keys
1034 try {
1035 mediakeys = Bus.get_proxy_sync (BusType.SESSION,
1036 "org.gnome.SettingsDaemon", "/org/gnome/SettingsDaemon/MediaKeys");
1037- mediakeys.MediaPlayerKeyPressed.connect ( (bus, app, key) => {
1038+ mediakeys.MediaPlayerKeyPressed.connect ((bus, app, key) => {
1039 if (app != "audience")
1040 return;
1041 switch (key) {
1042@@ -229,138 +183,25 @@
1043 });
1044
1045 mediakeys.GrabMediaPlayerKeys("audience", 0);
1046- } catch (Error e) { warning (e.message); }
1047-
1048- //shortcuts
1049- this.mainwindow.key_press_event.connect ( (e) => {
1050- switch (e.keyval) {
1051- case Gdk.Key.p:
1052- case Gdk.Key.space:
1053- video_player.playing = !video_player.playing;
1054- break;
1055- case Gdk.Key.Escape:
1056- if (video_player.fullscreened)
1057- toggle_fullscreen ();
1058- else
1059- mainwindow.destroy ();
1060- break;
1061- case Gdk.Key.o:
1062- run_open_file ();
1063- break;
1064- case Gdk.Key.f:
1065- case Gdk.Key.F11:
1066- toggle_fullscreen ();
1067- break;
1068- case Gdk.Key.q:
1069- mainwindow.destroy ();
1070- break;
1071- case Gdk.Key.Left:
1072- if ((video_player.progress - 0.05) < 0)
1073- video_player.progress = 0.0;
1074- else
1075- video_player.progress -= 0.05;
1076- break;
1077- case Gdk.Key.Right:
1078- video_player.progress += 0.05;
1079- break;
1080- case Gdk.Key.a:
1081- next_audio ();
1082- break;
1083- case Gdk.Key.s:
1084- next_text ();
1085- break;
1086- default:
1087- break;
1088- }
1089-
1090- return true;
1091+ } catch (Error e) {
1092+ warning (e.message);
1093+ }
1094+
1095+ /*events*/
1096+ video_player.text_tags_changed.connect (bottom_bar.preferences_popover.setup_text);
1097+ video_player.audio_tags_changed.connect (bottom_bar.preferences_popover.setup_audio);
1098+ video_player.progression_changed.connect ((current_time, total_time) => {
1099+ bottom_bar.set_progression_time (current_time, total_time);
1100 });
1101
1102 //end
1103- video_player.ended.connect ( () => {
1104- Idle.add (()=>{
1105+ video_player.ended.connect (() => {
1106+ Idle.add (() => {
1107 playlist.next ();
1108 return false;
1109 });
1110 });
1111
1112- /*open location popover*/
1113- video_player.show_open_context.connect ( () => {
1114- var has_been_stopped = video_player.playing;
1115-
1116- video_player.playing = false;
1117-
1118- if (!has_dvd) { //just one source, so open that one
1119- Timeout.add (300, () => {
1120- run_open_file ();
1121- return false;
1122- });
1123- return;
1124- }
1125-
1126- var pop = new Granite.Widgets.PopOver ();
1127- var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 6);
1128- ((Gtk.Box)pop.get_content_area ()).add (box);
1129-
1130- var fil = new Gtk.Button.with_label (_("Add from Harddrive"));
1131- fil.image = new Gtk.Image.from_icon_name ("document-open", Gtk.IconSize.DIALOG);
1132- var dvd = new Gtk.Button.with_label (_("Play a DVD"));
1133- dvd.image = new Gtk.Image.from_icon_name ("media-cdrom", Gtk.IconSize.DIALOG);
1134- var net = new Gtk.Button.with_label (_("Network File"));
1135- net.image = new Gtk.Image.from_icon_name ("internet-web-browser", Gtk.IconSize.DIALOG);
1136-
1137- fil.clicked.connect ( () => {
1138- pop.destroy ();
1139- run_open_file ();
1140- });
1141- dvd.clicked.connect ( () => {
1142- run_open_dvd ();
1143- pop.destroy ();
1144- });
1145- net.clicked.connect ( () => {
1146- var entry = new Gtk.Entry ();
1147- entry.secondary_icon_stock = Gtk.Stock.OPEN;
1148- entry.icon_release.connect ( (pos, e) => {
1149- open_file (entry.text);
1150- video_player.playing = true;
1151- pop.destroy ();
1152- });
1153- box.remove (net);
1154- box.reorder_child (entry, 2);
1155- entry.show ();
1156- });
1157-
1158- box.pack_start (fil);
1159- if (has_dvd)
1160- box.pack_start (dvd);
1161- //box.pack_start (net); uri temporary dropped
1162-
1163- /*temporary until popover closing gets fixed*/
1164- var canc = new Gtk.Button.from_stock (Gtk.Stock.CANCEL);
1165- box.pack_start (canc);
1166- canc.clicked.connect ( () => {
1167- pop.destroy ();
1168- });
1169-
1170- int x_r, y_r;
1171- this.mainwindow.get_window ().get_origin (out x_r, out y_r);
1172-
1173- pop.move_to_coords ((int)(x_r + clutter.get_stage ().width - 50),
1174- (int)(y_r + stage.height - 18));
1175-
1176- pop.show_all ();
1177-
1178- Timeout.add (300, () => { //for some reason this doesn't cause a crash :)
1179- pop.present ();
1180- pop.run ();
1181- pop.destroy ();
1182- if (has_been_stopped)
1183- video_player.playing = true;
1184-
1185- return false;
1186- });
1187- });
1188-
1189 video_player.error.connect (() => {
1190 welcome.show_all ();
1191 clutter.hide ();
1192@@ -375,196 +216,347 @@
1193 mainwindow.set_keep_above (video_player.playing && settings.stay_on_top);
1194 });
1195
1196- video_player.exit_fullscreen.connect (toggle_fullscreen);
1197-
1198- video_player.toggle_side_pane.connect ((show) => {
1199- if (show) {
1200- tagview.expand ();
1201- } else {
1202- tagview.collapse ();
1203- }
1204- });
1205-
1206- video_player.configure_window.connect ((video_w, video_h) => {
1207-
1208- Gdk.Rectangle monitor;
1209- var screen = Gdk.Screen.get_default ();
1210- screen.get_monitor_geometry (
1211- screen.get_monitor_at_window (mainwindow.get_window ()),
1212- out monitor);
1213-
1214- int width = 0, height = 0;
1215- if (monitor.width > video_w && monitor.height > video_h) {
1216- width = (int)video_w;
1217- height = (int)video_h;
1218- } else {
1219- width = (int)(monitor.width * 0.9);
1220- height = (int)((double)video_h / video_w * width);
1221- }
1222-
1223+ notify["fullscreened"].connect (() => {bottom_bar.fullscreen = fullscreened;});
1224+
1225+ setup_drag_n_drop ();
1226+ video_player.configure_window.connect ((video_w, video_h) => {on_configure_window (video_w, video_h);});
1227+
1228+ //fullscreen on maximize
1229+ mainwindow.window_state_event.connect ((e) => {
1230+ on_window_state_changed (e.window.get_state ());
1231+ return false;
1232+ });
1233+
1234+ mainwindow.size_allocate.connect ((alloc) => {on_size_allocate (alloc);});
1235+ mainwindow.motion_notify_event.connect ((event) => {
1236+ if (event.window == null)
1237+ return false;
1238+
1239+ if (mouse_primary_down && settings.move_window) {
1240+ mouse_primary_down = false;
1241+ mainwindow.begin_move_drag (Gdk.BUTTON_PRIMARY,
1242+ (int)event.x_root, (int)event.y_root, event.time);
1243+ }
1244+
1245+ Gtk.Allocation allocation;
1246+ clutter.get_allocation (out allocation);
1247+ return update_pointer_position (event.y, allocation.height);
1248+ });
1249+
1250+ bottom_bar.time_widget.slider_motion_event.connect ((event) => {
1251+ int x, y;
1252+ bottom_bar.translate_coordinates (mainwindow, (int)event.x, (int)event.y, out x, out y);
1253+ Gtk.Allocation allocation;
1254+ clutter.get_allocation (out allocation);
1255+ update_pointer_position (y, allocation.height);
1256+ });
1257+
1258+ mainwindow.button_press_event.connect ((event) => {
1259+ if (event.type == Gdk.EventType.2BUTTON_PRESS) {
1260+ toggle_fullscreen ();
1261+ }
1262+
1263+ if (event.button == Gdk.BUTTON_PRIMARY)
1264+ mouse_primary_down = true;
1265+
1266+ return false;
1267+ });
1268+
1269+ mainwindow.button_release_event.connect ((event) => {
1270+ if (event.button == Gdk.BUTTON_PRIMARY)
1271+ mouse_primary_down = false;
1272+
1273+ return false;
1274+ });
1275+
1276+ mainwindow.leave_notify_event.connect ((event) => {
1277+ if (event.window == null)
1278+ return false;
1279+
1280+ Gtk.Allocation allocation;
1281+ clutter.get_allocation (out allocation);
1282+ if (event.x == event.window.get_width ())
1283+ return update_pointer_position (event.window.get_height (), allocation.height);
1284+ else if (event.x == 0)
1285+ return update_pointer_position (event.window.get_height (), allocation.height);
1286+ return update_pointer_position (event.y, allocation.height);
1287+ });
1288+ //shortcuts
1289+ this.mainwindow.key_press_event.connect ((e) => {
1290+ return on_key_press_event (e);
1291+ });
1292+
1293+ //save position in video when not finished playing
1294+ mainwindow.destroy.connect (() => {on_destroy ();});
1295+
1296+ //playlist wants us to open a file
1297+ playlist.play.connect ((file) => {
1298+ this.play_file (file.get_uri ());
1299+ });
1300+
1301+ bottom_bar.notify["child-revealed"].connect (() => {
1302+ if (bottom_bar.child_revealed == true) {
1303+ mainwindow.get_window ().set_cursor (null);
1304+ } else {
1305+ mainwindow.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.BLANK_CURSOR));
1306+ }
1307+ });
1308+
1309+ stage.notify["allocation"].connect (() => {allocate_bottombar ();});
1310+
1311+ if (settings.resume_videos == true && settings.last_played_videos.length > 0) {
1312+ welcome.hide ();
1313+ clutter.show_all ();
1314+ foreach (var filename in settings.last_played_videos) {
1315+ open_file (filename);
1316+ }
1317+
1318+ video_player.playing = false;
1319+ video_player.progress = settings.last_stopped;
1320+ video_player.playing = true;
1321+ }
1322+ }
1323+
1324+ private void allocate_bottombar () {
1325+ bottom_actor.width = stage.get_width ();
1326+ bottom_bar.queue_resize ();
1327+ bottom_actor.y = stage.get_height () - bottom_bar_size;
1328+ unfullscreen_actor.y = 6;
1329+ unfullscreen_actor.x = stage.get_width () - bottom_bar_size - 6;
1330+ }
1331+
1332+ private void setup_welcome_screen () {
1333+ welcome = new Granite.Widgets.Welcome (_("No Videos Open"), _("Select a source to begin playing."));
1334+ welcome.append ("document-open", _("Open file"), _("Open a saved file."));
1335+
1336+ //welcome.append ("internet-web-browser", _("Open a location"), _("Watch something from the infinity of the internet"));
1337+ var filename = settings.last_played_videos.length > 0 ? settings.last_played_videos[0] : "";
1338+ var last_file = File.new_for_path (filename);
1339+ welcome.append ("media-playback-start", _("Resume last video"), get_title (last_file.get_basename ()));
1340+ bool show_last_file = settings.last_played_videos.length > 0;
1341+ if (last_file.query_exists () == false) {
1342+ show_last_file = false;
1343+ }
1344+
1345+ welcome.set_item_visible (1, show_last_file);
1346+
1347+ welcome.append ("media-cdrom", _("Play from Disc"), _("Watch a DVD or open a file from disc"));
1348+ welcome.set_item_visible (2, false);
1349+
1350+ //look for dvd
1351+ var disk_manager = DiskManager.get_default ();
1352+ foreach (var volume in disk_manager.get_volumes ()) {
1353+ welcome.set_item_visible (2, true);
1354+ }
1355+
1356+ disk_manager.volume_found.connect ((vol) => {
1357+ welcome.set_item_visible (2, true);
1358+ });
1359+
1360+ disk_manager.volume_removed.connect ((vol) => {
1361+ if (disk_manager.get_volumes ().length () <= 0)
1362+ welcome.set_item_visible (2, false);
1363+ });
1364+
1365+ //handle welcome
1366+ welcome.activated.connect ((index) => {
1367+ switch (index) {
1368+ case 0:
1369+ run_open_file ();
1370+ break;
1371+ case 1:
1372+ welcome.hide ();
1373+ clutter.show_all ();
1374+ open_file (filename);
1375+ video_player.playing = false;
1376+ video_player.progress = settings.last_stopped;
1377+ video_player.playing = true;
1378+ break;
1379+ case 2:
1380+ run_open_dvd ();
1381+ break;
1382+ default:
1383+ var d = new Gtk.Dialog.with_buttons (_("Open location"),
1384+ this.mainwindow, Gtk.DialogFlags.MODAL,
1385+ _("Cancel"), Gtk.ResponseType.CANCEL,
1386+ _("OK"), Gtk.ResponseType.OK);
1387+
1388+ var grid = new Gtk.Grid ();
1389+ var entry = new Gtk.Entry ();
1390+
1391+ grid.attach (new Gtk.Image.from_icon_name ("internet-web-browser",
1392+ Gtk.IconSize.DIALOG), 0, 0, 1, 2);
1393+ grid.attach (new Gtk.Label (_("Choose location")), 1, 0, 1, 1);
1394+ grid.attach (entry, 1, 1, 1, 1);
1395+
1396+ ((Gtk.Container)d.get_content_area ()).add (grid);
1397+ grid.show_all ();
1398+
1399+ if (d.run () == Gtk.ResponseType.OK) {
1400+ open_file (entry.text, true);
1401+ video_player.playing = true;
1402+ welcome.hide ();
1403+ clutter.show_all ();
1404+ }
1405+
1406+ d.destroy ();
1407+ break;
1408+ }
1409+
1410+ int current_state = mainwindow.get_window ().get_state ();
1411+ bool currently_maximized = (current_state & Gdk.WindowState.MAXIMIZED) != 0;
1412+
1413+ // video is playing and we are maximized, go fullscreen
1414+ if (video_player.playing && currently_maximized) {
1415+ mainwindow.fullscreen ();
1416+ fullscreened = true;
1417+ }
1418+ });
1419+ }
1420+
1421+ private bool on_key_press_event (Gdk.EventKey e) {
1422+ switch (e.keyval) {
1423+ case Gdk.Key.p:
1424+ case Gdk.Key.space:
1425+ video_player.playing = !video_player.playing;
1426+ break;
1427+ case Gdk.Key.Escape:
1428+ if (fullscreened)
1429+ toggle_fullscreen ();
1430+ else
1431+ mainwindow.destroy ();
1432+ break;
1433+ case Gdk.Key.o:
1434+ run_open_file ();
1435+ break;
1436+ case Gdk.Key.f:
1437+ case Gdk.Key.F11:
1438+ toggle_fullscreen ();
1439+ break;
1440+ case Gdk.Key.q:
1441+ mainwindow.destroy ();
1442+ break;
1443+ case Gdk.Key.Left:
1444+ if ((video_player.progress - 0.05) < 0)
1445+ video_player.progress = 0.0;
1446+ else
1447+ video_player.progress -= 0.05;
1448+ break;
1449+ case Gdk.Key.Right:
1450+ video_player.progress += 0.05;
1451+ break;
1452+ case Gdk.Key.a:
1453+ bottom_bar.preferences_popover.next_audio ();
1454+ break;
1455+ case Gdk.Key.s:
1456+ bottom_bar.preferences_popover.next_text ();
1457+ break;
1458+ default:
1459+ break;
1460+ }
1461+
1462+ return true;
1463+ }
1464+
1465+ private void on_configure_window (uint video_w, uint video_h) {
1466+ Gdk.Rectangle monitor;
1467+ var screen = Gdk.Screen.get_default ();
1468+ screen.get_monitor_geometry (screen.get_monitor_at_window (mainwindow.get_window ()), out monitor);
1469+
1470+ int width = 0, height = 0;
1471+ if (monitor.width > video_w && monitor.height > video_h) {
1472+ width = (int)video_w;
1473+ height = (int)video_h;
1474+ } else {
1475+ width = (int)(monitor.width * 0.9);
1476+ height = (int)((double)video_h / video_w * width);
1477+ }
1478+
1479+ mainwindow.get_window ().move_resize (monitor.width / 2 - width / 2 + monitor.x,
1480+ monitor.height / 2 - height / 2 + monitor.y,
1481+ width, height);
1482+
1483+ if (settings.keep_aspect) {
1484 var geom = Gdk.Geometry ();
1485- if (settings.keep_aspect) {
1486- geom.min_aspect = geom.max_aspect = video_w / (double)video_h;
1487- } else {
1488- geom.min_aspect = 0.0;
1489- geom.max_aspect = 99999999.0;
1490- }
1491-
1492- mainwindow.get_window ().move_resize (monitor.width / 2 - width / 2 + monitor.x,
1493- monitor.height / 2 - height / 2 + monitor.y,
1494- width, height);
1495-
1496- if (settings.keep_aspect) {
1497- mainwindow.get_window ().set_geometry_hints (geom, Gdk.WindowHints.ASPECT);
1498- }
1499-
1500- });
1501-
1502- //fullscreen on maximize
1503- mainwindow.window_state_event.connect ( (e) => {
1504- bool currently_maximized = (e.window.get_state () & Gdk.WindowState.MAXIMIZED) == 0;
1505-
1506- if (!currently_maximized && !video_player.fullscreened && !welcome.is_visible ()) {
1507- mainwindow.fullscreen ();
1508- video_player.fullscreened = true;
1509-
1510- return true;
1511- }
1512- return false;
1513- });
1514-
1515- //positioning
1516- int old_h = - 1;
1517- int old_w = - 1;
1518- mainwindow.size_allocate.connect ( (alloc) => {
1519- if (alloc.width != old_w ||
1520- alloc.height != old_h) {
1521- if (video_player.relayout ()) {
1522- old_w = alloc.width;
1523- old_h = alloc.height;
1524- }
1525- }
1526-
1527- tagview.x = tagview.expanded ? stage.width - tagview.width + 10 : stage.width;
1528- });
1529-
1530- /*moving the window by drag, fullscreen for dbl-click*/
1531- bool down = false;
1532- bool moving = false;
1533- video_player.button_press_event.connect ( (e) => {
1534- if (e.click_count > 1) {
1535- toggle_fullscreen ();
1536- down = false;
1537- return true;
1538- } else {
1539- down = true;
1540- return true;
1541- }
1542- });
1543- clutter.motion_notify_event.connect ( (e) => {
1544- if (down && settings.move_window) {
1545- down = false;
1546- moving = true;
1547- mainwindow.begin_move_drag (1,
1548- (int)e.x_root, (int)e.y_root, e.time);
1549-
1550- video_player.lock_hide ();
1551-
1552- return true;
1553- }
1554- return false;
1555- });
1556- clutter.button_release_event.connect ( (e) => {
1557- down = false;
1558- return false;
1559- });
1560- mainwindow.focus_in_event.connect (() => {
1561- if (moving) {
1562- video_player.unlock_hide ();
1563- moving = false;
1564- }
1565- return false;
1566- });
1567-
1568- /*DnD*/
1569+ geom.min_aspect = geom.max_aspect = video_w / (double)video_h;
1570+ mainwindow.get_window ().set_geometry_hints (geom, Gdk.WindowHints.ASPECT);
1571+ }
1572+ }
1573+
1574+ private void on_window_state_changed (Gdk.WindowState window_state) {
1575+ bool currently_maximized = (window_state & Gdk.WindowState.MAXIMIZED) == 0;
1576+
1577+ if (!currently_maximized && !fullscreened && !welcome.is_visible ()) {
1578+ mainwindow.fullscreen ();
1579+ fullscreened = true;
1580+ }
1581+ }
1582+
1583+ /*DnD*/
1584+ private void setup_drag_n_drop () {
1585 Gtk.TargetEntry uris = {"text/uri-list", 0, 0};
1586 Gtk.drag_dest_set (mainwindow, Gtk.DestDefaults.ALL, {uris}, Gdk.DragAction.MOVE);
1587 mainwindow.drag_data_received.connect ( (ctx, x, y, sel, info, time) => {
1588- for (var i=1;i<sel.get_uris ().length; i++)
1589- playlist.add_item (File.new_for_uri (sel.get_uris ()[i]));
1590+ foreach (var uri in sel.get_uris ()) {
1591+ playlist.add_item (File.new_for_uri (uri));
1592+ }
1593 open_file (sel.get_uris ()[0]);
1594-
1595 welcome.hide ();
1596 clutter.show_all ();
1597 });
1598-
1599- //save position in video when not finished playing
1600- mainwindow.destroy.connect ( () => {
1601- if (video_player.uri == null || video_player.uri == "" || video_player.uri.has_prefix ("dvd://"))
1602- return;
1603- if (!video_player.at_end) {
1604- for (var i = 0; i < last_played_videos.length (); i += 2){
1605- if (video_player.uri == last_played_videos.nth_data (i)){
1606- last_played_videos.nth (i+1).data = video_player.progress.to_string ();
1607- save_last_played_videos ();
1608-
1609- return;
1610- }
1611- }
1612- //not in list yet, insert at start
1613- last_played_videos.insert (video_player.uri, 0);
1614- last_played_videos.insert (video_player.progress.to_string (), 1);
1615- if (last_played_videos.length () > 10) {
1616- last_played_videos.delete_link (last_played_videos.nth (10));
1617- last_played_videos.delete_link (last_played_videos.nth (11));
1618- }
1619- save_last_played_videos ();
1620- }
1621- });
1622- }
1623-
1624- public void next_audio () {
1625- int n_audio;
1626- video_player.playbin.get ("n-audio", out n_audio);
1627- int current = video_player.current_audio;
1628-
1629- if (n_audio > 1) {
1630- if (current < n_audio - 1) {
1631- current += 1;
1632- } else {
1633- current = 0;
1634- }
1635- }
1636- tagview.languages.active_id = current.to_string ();
1637- }
1638-
1639- public void next_text () {
1640- int n_text;
1641- video_player.playbin.get ("n-text", out n_text);
1642- int current = int.parse (tagview.subtitles.active_id);
1643-
1644- if (n_text > 1) {
1645- if (current < n_text - 1) {
1646- current += 1;
1647- } else {
1648- current = -1;
1649- }
1650- }
1651- tagview.subtitles.active_id = current.to_string ();
1652+ }
1653+
1654+ private void on_destroy () {
1655+ if (video_player.uri == null || video_player.uri == "" || video_player.uri.has_prefix ("dvd://"))
1656+ return;
1657+ if (!video_player.at_end) {
1658+ save_last_played_videos ();
1659+ }
1660+ }
1661+
1662+ private int old_h = - 1;
1663+ private int old_w = - 1;
1664+ private void on_size_allocate (Gtk.Allocation alloc) {
1665+ if (alloc.width != old_w || alloc.height != old_h) {
1666+ if (video_player.relayout ()) {
1667+ old_w = alloc.width;
1668+ old_h = alloc.height;
1669+ }
1670+ }
1671+ }
1672+
1673+ private bool update_pointer_position (double y, int window_height) {
1674+ allocate_bottombar ();
1675+ mainwindow.get_window ().set_cursor (null);
1676+ if (bottom_bar_size == 0) {
1677+ int minimum = 0;
1678+ bottom_bar.get_preferred_height (out minimum, out bottom_bar_size);
1679+ }
1680+
1681+ if (bottom_bar.child_revealed == false)
1682+ bottom_bar.set_reveal_child (true);
1683+
1684+ if (y >= (window_height - bottom_bar_size) && y < window_height) {
1685+ bottom_bar.hovered = true;
1686+ } else {
1687+ bottom_bar.hovered = false;
1688+ }
1689+
1690+ return false;
1691 }
1692
1693 private inline void save_last_played_videos () {
1694- string res = "";
1695- for (var i = 0; i < last_played_videos.length () - 1; i ++)
1696- res += last_played_videos.nth_data (i) + ",";
1697+ playlist.save_playlist_config ();
1698
1699- res += last_played_videos.nth_data (last_played_videos.length () - 1);
1700- settings.last_played_videos = res;
1701+ if (settings.last_played_videos.length > 0)
1702+ settings.last_stopped = video_player.progress;
1703+ else
1704+ settings.last_stopped = 0;
1705 }
1706
1707- private void run_open_file () {
1708+ public void run_open_file () {
1709 var file = new Gtk.FileChooserDialog (_("Open"), mainwindow, Gtk.FileChooserAction.OPEN,
1710- Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, Gtk.Stock.OPEN, Gtk.ResponseType.ACCEPT);
1711+ _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT);
1712 file.select_multiple = true;
1713
1714 var all_files_filter = new Gtk.FileFilter ();
1715@@ -582,92 +574,95 @@
1716 if (file.run () == Gtk.ResponseType.ACCEPT) {
1717 welcome.hide ();
1718 clutter.show_all ();
1719- for (var i=1;i<file.get_files ().length ();i++) {
1720- playlist.add_item (file.get_files ().nth_data (i));
1721- }
1722 open_file (file.get_uri ());
1723 settings.last_folder = file.get_current_folder ();
1724 }
1725+
1726 file.destroy ();
1727 }
1728
1729- private void run_open_dvd () {
1730- open_file ("dvd://", true);
1731+ public void run_open_dvd () {
1732+ read_first_disk.begin ();
1733+ }
1734+
1735+ private async void read_first_disk () {
1736+ var disk_manager = DiskManager.get_default ();
1737+ if (disk_manager.get_volumes ().length () <= 0)
1738+ return;
1739+ var volume = disk_manager.get_volumes ().nth_data (0);
1740+ if (volume.can_mount () == true && volume.get_mount ().can_unmount () == false) {
1741+ try {
1742+ yield volume.mount (MountMountFlags.NONE, null);
1743+ } catch (Error e) {
1744+ critical (e.message);
1745+ }
1746+ }
1747+
1748+ var root = volume.get_mount ().get_default_location ();
1749+ open_file (root.get_uri (), true);
1750 video_player.playing = true;
1751
1752 welcome.hide ();
1753 clutter.show_all ();
1754 }
1755
1756- private void toggle_fullscreen ()
1757- {
1758- if (video_player.fullscreened) {
1759+ private void toggle_fullscreen () {
1760+ if (fullscreened) {
1761 mainwindow.unmaximize ();
1762 mainwindow.unfullscreen ();
1763- video_player.fullscreened = false;
1764+ fullscreened = false;
1765 } else {
1766 mainwindow.fullscreen ();
1767- video_player.fullscreened = true;
1768+ fullscreened = true;
1769 }
1770 }
1771
1772- internal void open_file (string filename, bool dont_modify=false)
1773- {
1774+ internal void open_file (string filename, bool dont_modify = false) {
1775 var file = File.new_for_commandline_arg (filename);
1776
1777 if (file.query_file_type (0) == FileType.DIRECTORY) {
1778 Audience.recurse_over_dir (file, (file_ret) => {
1779 playlist.add_item (file_ret);
1780 });
1781+
1782 file = playlist.get_first_item ();
1783 } else if (is_subtitle (filename) && video_player.playing) {
1784 video_player.set_subtitle_uri (filename);
1785- return;
1786+ } else if (video_player.playing == true) {
1787+ playlist.add_item (file);
1788+ } else {
1789+ playlist.add_item (file);
1790+ play_file (file.get_uri ());
1791 }
1792- else
1793- playlist.add_item (file);
1794+ }
1795
1796- play_file (file.get_uri ());
1797- }
1798-
1799 private bool is_subtitle (string uri) {
1800 if (uri.length < 4 || uri.get_char (uri.length-4) != '.')
1801 return false;
1802+
1803 foreach (string ext in SUBTITLE_EXTENSIONS) {
1804 if (uri.down ().has_suffix (ext))
1805 return true;
1806 }
1807+
1808 return false;
1809 }
1810
1811 public void play_file (string uri) {
1812 debug ("Opening %s", uri);
1813 video_player.uri = uri;
1814+ bottom_bar.set_preview_uri (uri);
1815
1816 mainwindow.title = get_title (uri);
1817 if (!settings.playback_wait)
1818 video_player.playing = true;
1819
1820- if (settings.resume_videos) {
1821- int i;
1822- for (i = 0; i < last_played_videos.length () && i != -1; i += 2) {
1823- if (video_player.uri == last_played_videos.nth_data (i))
1824- break;
1825- if (i == last_played_videos.length () - 1)
1826- i = -1;
1827- }
1828- if (i != -1 && last_played_videos.nth_data (i + 1) != null) {
1829- Idle.add (() => { video_player.progress = double.parse (last_played_videos.nth_data (i + 1)); return false;});
1830- debug ("Resuming video from " + last_played_videos.nth_data (i + 1));
1831- }
1832- }
1833-
1834 Gtk.RecentManager recent_manager = Gtk.RecentManager.get_default ();
1835 recent_manager.add_item (uri);
1836
1837 /*subtitles/audio tracks*/
1838- tagview.setup_setup ("text");
1839- tagview.setup_setup ("audio");
1840+ bottom_bar.preferences_popover.setup_text ();
1841+ bottom_bar.preferences_popover.setup_audio ();
1842 }
1843
1844 //the application started
1845@@ -676,16 +671,15 @@
1846 }
1847
1848 //the application was requested to open some files
1849- public override void open (File [] files, string hint) {
1850+ public override void open (File[] files, string hint) {
1851 if (mainwindow == null)
1852 activate ();
1853
1854- for (var i = 1; i < files.length; i ++)
1855- playlist.add_item (files[i]);
1856-
1857- open_file (files[0].get_path ());
1858 welcome.hide ();
1859 clutter.show_all ();
1860+ foreach (var file in files) {
1861+ open_file (file.get_path ());
1862+ }
1863 }
1864 }
1865 }
1866
1867=== added file 'src/CMakeLists.txt'
1868--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
1869+++ src/CMakeLists.txt 2014-07-06 11:18:29 +0000
1870@@ -0,0 +1,57 @@
1871+# Vala stuff
1872+find_package (Vala REQUIRED)
1873+include (ValaVersion)
1874+ensure_vala_version ("0.22" MINIMUM)
1875+include (ValaPrecompile)
1876+
1877+# Configure file
1878+set (CONFIG_FILE ${CMAKE_CURRENT_BINARY_DIR}/config.vala)
1879+configure_file (${CMAKE_CURRENT_SOURCE_DIR}/Config.vala.cmake ${CONFIG_FILE})
1880+
1881+# pkgconfig, real C code
1882+find_package (PkgConfig)
1883+
1884+set (PKG_DEPS granite clutter-gtk-1.0 gstreamer-1.0 gstreamer-pbutils-1.0 gstreamer-tag-1.0)
1885+set (VALA_DEPS
1886+ granite
1887+ clutter-gtk-1.0
1888+ gdk-x11-3.0
1889+ gstreamer-1.0
1890+ gstreamer-pbutils-1.0
1891+ gstreamer-tag-1.0
1892+)
1893+
1894+pkg_check_modules (DEPS REQUIRED ${PKG_DEPS})
1895+set (CFLAGS ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER})
1896+link_directories (${DEPS_LIBRARY_DIRS})
1897+add_definitions (${CFLAGS})
1898+
1899+set (EXEC_NAME ${CMAKE_PROJECT_NAME})
1900+
1901+vala_precompile (VALA_C ${EXEC_NAME}
1902+ ${CONFIG_FILE}
1903+ Audience.vala
1904+ Consts.vala
1905+ Settings.vala
1906+ Utils.vala
1907+ DiskManager.vala
1908+ Widgets/BottomBar.vala
1909+ Widgets/SettingsPopover.vala
1910+ Widgets/PreviewPopover.vala
1911+ Widgets/TimeWidget.vala
1912+ Widgets/Playlist.vala
1913+ Widgets/PlaylistPopover.vala
1914+ Widgets/VideoPlayer.vala
1915+ desktop-launcher.vala
1916+ PACKAGES
1917+ ${VALA_DEPS}
1918+ OPTIONS
1919+ --enable-experimental
1920+ --target-glib=2.32 # Remember to keep this updated.
1921+ --thread
1922+ -g
1923+)
1924+
1925+add_executable (${EXEC_NAME} ${VALA_C})
1926+target_link_libraries (${EXEC_NAME} ${DEPS_LIBRARIES})
1927+install (TARGETS ${EXEC_NAME} RUNTIME DESTINATION bin)
1928\ No newline at end of file
1929
1930=== modified file 'src/Consts.vala'
1931--- src/Consts.vala 2013-03-31 21:46:37 +0000
1932+++ src/Consts.vala 2014-07-06 11:18:29 +0000
1933@@ -1,6 +1,7 @@
1934
1935 namespace Audience {
1936-
1937 public const int CONTROLS_HEIGHT = 32;
1938+ // 204/255 = 80% opacity
1939+ public const uint GLOBAL_OPACITY = 204;
1940
1941-}
1942+}
1943\ No newline at end of file
1944
1945=== added file 'src/DiskManager.vala'
1946--- src/DiskManager.vala 1970-01-01 00:00:00 +0000
1947+++ src/DiskManager.vala 2014-07-06 11:18:29 +0000
1948@@ -0,0 +1,98 @@
1949+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
1950+/*-
1951+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
1952+ *
1953+ * This program is free software: you can redistribute it and/or modify
1954+ * it under the terms of the GNU General Public License as published by
1955+ * the Free Software Foundation, either version 3 of the License, or
1956+ * (at your option) any later version.
1957+
1958+ * This program is distributed in the hope that it will be useful,
1959+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1960+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1961+ * GNU General Public License for more details.
1962+
1963+ * You should have received a copy of the GNU General Public License
1964+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1965+ *
1966+ * Authored by: Corentin Noël <corentin@elementaryos.org>
1967+ */
1968+
1969+public class Audience.DiskManager : GLib.Object {
1970+ public signal void volume_found (Volume volume);
1971+ public signal void volume_removed (Volume volume);
1972+
1973+ private static DiskManager disk_manager = null;
1974+ public static DiskManager get_default () {
1975+ if (disk_manager == null) {
1976+ disk_manager = new DiskManager ();
1977+ }
1978+
1979+ return disk_manager;
1980+ }
1981+
1982+ private GLib.VolumeMonitor monitor;
1983+ private List<Volume> volumes;
1984+
1985+ private DiskManager () {
1986+ monitor = GLib.VolumeMonitor.get ();
1987+ volumes = monitor.get_volumes ();
1988+
1989+ monitor.drive_changed.connect ((drive) => {
1990+ debug ("Drive changed: %s\n", drive.get_name ());
1991+ });
1992+
1993+ monitor.drive_connected.connect ((drive) => {
1994+ debug ("Drive connected: %s", drive.get_name ());
1995+ });
1996+
1997+ monitor.drive_disconnected.connect ((drive) => {
1998+ debug ("Drive disconnected: %s", drive.get_name ());
1999+ });
2000+
2001+ monitor.drive_eject_button.connect ((drive) => {
2002+ debug ("Drive eject-button: %s", drive.get_name ());
2003+ });
2004+
2005+ monitor.drive_stop_button.connect ((drive) => {
2006+ debug ("Drive stop-button:%s", drive.get_name ());
2007+ });
2008+
2009+ monitor.volume_added.connect ((volume) => {
2010+ check_for_volume (volume);
2011+ debug ("Volume added: %s", volume.get_name ());
2012+ });
2013+
2014+ monitor.volume_changed.connect ((volume) => {
2015+ check_for_volume (volume);
2016+ debug ("Volume changed: %s", volume.get_name ());
2017+ });
2018+
2019+ monitor.volume_removed.connect ((volume) => {
2020+ volumes.remove (volume);
2021+ volume_removed (volume);
2022+ debug ("Volume removed: %s", volume.get_name ());
2023+ });
2024+ }
2025+
2026+ public GLib.List<Volume> get_volumes () {
2027+ return volumes.copy ();
2028+ }
2029+
2030+ private void check_for_volume (Volume volume) {
2031+ if (volume.get_drive ().is_media_check_automatic () == true) {
2032+ if (volume.get_drive ().has_media () == true) {
2033+ var root = volume.get_activation_root ();
2034+ if (root != null) {
2035+ var video = root.get_child ("VIDEO_TS");
2036+ var bdmv = root.get_child ("BDMV");
2037+ var audio = root.get_child ("AUDIO_TS");
2038+ if (audio.query_exists () == true || video.query_exists () == true || bdmv.query_exists () == true) {
2039+ volumes.append (volume);
2040+ volume_found (volume);
2041+ }
2042+ }
2043+ }
2044+ }
2045+ }
2046+}
2047\ No newline at end of file
2048
2049=== modified file 'src/Settings.vala'
2050--- src/Settings.vala 2013-03-31 21:46:37 +0000
2051+++ src/Settings.vala 2014-07-06 11:18:29 +0000
2052@@ -1,19 +1,36 @@
2053-
2054-namespace Audience {
2055-
2056- public class Settings : Granite.Services.Settings {
2057- public bool move_window {get; set;}
2058- public bool keep_aspect {get; set;}
2059- public bool resume_videos {get; set;}
2060- public string last_played_videos {get; set;} /*video1,time,video2,time2,...*/
2061- public string last_folder {get; set;}
2062- public bool playback_wait {get; set;}
2063- public bool stay_on_top {get; set;}
2064- public bool show_window_decoration {get; set;}
2065-
2066- public Settings () {
2067- base ("org.pantheon.Audience");
2068- }
2069-
2070+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2071+/*-
2072+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
2073+ *
2074+ * This program is free software: you can redistribute it and/or modify
2075+ * it under the terms of the GNU General Public License as published by
2076+ * the Free Software Foundation, either version 3 of the License, or
2077+ * (at your option) any later version.
2078+
2079+ * This program is distributed in the hope that it will be useful,
2080+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2081+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2082+ * GNU General Public License for more details.
2083+
2084+ * You should have received a copy of the GNU General Public License
2085+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2086+ *
2087+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
2088+ */
2089+
2090+public class Audience.Settings : Granite.Services.Settings {
2091+ public bool move_window {get; set;}
2092+ public bool keep_aspect {get; set;}
2093+ public bool resume_videos {get; set;}
2094+ public string[] last_played_videos {get; set;}
2095+ public double last_stopped {get; set;}
2096+ public string last_folder {get; set;}
2097+ public bool playback_wait {get; set;}
2098+ public bool stay_on_top {get; set;}
2099+ public bool show_window_decoration {get; set;}
2100+
2101+ public Settings () {
2102+ base ("org.pantheon.Audience");
2103 }
2104-}
2105+
2106+}
2107\ No newline at end of file
2108
2109=== modified file 'src/Utils.vala'
2110--- src/Utils.vala 2014-04-28 12:58:09 +0000
2111+++ src/Utils.vala 2014-07-06 11:18:29 +0000
2112@@ -1,3 +1,22 @@
2113+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2114+/*-
2115+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
2116+ *
2117+ * This program is free software: you can redistribute it and/or modify
2118+ * it under the terms of the GNU General Public License as published by
2119+ * the Free Software Foundation, either version 3 of the License, or
2120+ * (at your option) any later version.
2121+
2122+ * This program is distributed in the hope that it will be useful,
2123+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2124+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2125+ * GNU General Public License for more details.
2126+
2127+ * You should have received a copy of the GNU General Public License
2128+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2129+ *
2130+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
2131+ */
2132
2133 [DBus (name = "org.gnome.SettingsDaemon.MediaKeys")]
2134 public interface GnomeMediaKeys : GLib.Object {
2135@@ -8,7 +27,7 @@
2136
2137 [DBus (name = "org.gnome.SessionManager")]
2138 public interface GnomeSessionManager : GLib.Object {
2139- public abstract bool isSessionRunning() throws GLib.IOError;
2140+ public abstract bool isSessionRunning() throws GLib.IOError;
2141 public abstract uint32 Inhibit (string app_id, uint32 toplevel_xid, string reason, uint32 flags) throws GLib.IOError;
2142 public abstract void Uninhibit (uint32 inhibit_cookie) throws GLib.IOError;
2143 }
2144@@ -18,16 +37,16 @@
2145 public static void recurse_over_dir (File file_to_process, FuncOverDir func) {
2146 if (file_to_process.query_file_type (0) == FileType.DIRECTORY) {
2147 try {
2148- var files = file_to_process.enumerate_children (FileAttribute.STANDARD_NAME, 0);
2149+ var files = file_to_process.enumerate_children (FileAttribute.STANDARD_NAME + "," + FileAttribute.ACCESS_CAN_READ, FileQueryInfoFlags.NONE);
2150 FileInfo info;
2151 while ((info = files.next_file ()) != null) {
2152- var file = GLib.File.new_for_uri (
2153- file_to_process.get_uri () +"/"+info.get_name ());
2154- recurse_over_dir (file,func);
2155+ var file = GLib.File.new_for_uri (file_to_process.get_uri () + "/" + info.get_name ());
2156+ recurse_over_dir (file, func);
2157 }
2158- } catch (Error e) { warning (e.message); }
2159- }
2160- else {
2161+ } catch (Error e) {
2162+ critical (e.message);
2163+ }
2164+ } else {
2165 func (file_to_process);
2166 }
2167 }
2168@@ -40,216 +59,51 @@
2169 }
2170
2171 public static string get_extension (string filename) {
2172- int i=0;
2173- for (i=filename.length;i!=0;i--) {
2174- if (filename [i] == '.')
2175- break;
2176+ for (uint i=filename.length; i!=0; i--) {
2177+ if (filename[i] == '.')
2178+ return filename.substring (i+1);
2179 }
2180- return filename.substring (i+1);
2181+
2182+ return filename;
2183 }
2184
2185 public static string get_basename (string filename) {
2186- int start = 0, end = 0;
2187- for (start=filename.length; start != 0; start--) {
2188+ uint end = 0;
2189+ for (uint start=filename.length; start != 0; start--) {
2190 if (filename[start] == '/') {
2191 start ++;
2192- break;
2193+ return filename.substring (start, end - start);
2194 }
2195+
2196 if (filename[start] == '.' && end == 0)
2197 end = start;
2198 }
2199- return filename.substring (start, end - start);
2200+
2201+ return filename.substring (0, end);
2202 }
2203
2204 public static string seconds_to_time (int seconds) {
2205 int hours = seconds / 3600;
2206- int minutes = (seconds % 3600) / 60;
2207- seconds = seconds % 60;
2208-
2209- string time = (hours > 0) ? hours.to_string() + ":" : "";
2210- time += (((hours > 0) && (minutes < 10)) ? "0" : "") + minutes.to_string() + ":";
2211- time += ((seconds < 10) ? "0" : "") + seconds.to_string();
2212- return time;
2213+ string min = normalize_time ((seconds % 3600) / 60);
2214+ string sec = normalize_time (seconds % 60);
2215+
2216+ if (hours > 0) {
2217+ return ("%d:%s:%s".printf (hours, min, sec));
2218+ } else {
2219+ return ("%s:%s".printf (min, sec));
2220+ }
2221+ }
2222+
2223+ public static string normalize_time (int time) {
2224+ if (time < 10) {
2225+ return "0%d".printf (time);
2226+ } else {
2227+ return "%d".printf (time);
2228+ }
2229 }
2230
2231 public static bool has_dvd () {
2232- var volume_monitor = GLib.VolumeMonitor.get ();
2233- var volumes = volume_monitor.get_connected_drives ();
2234-
2235- for (var i=0; i < volumes.length ();i++) {
2236- if (volumes.nth_data (i).get_name ().index_of ("DVD") != -1 &&
2237- volumes.nth_data (i).has_media ())
2238- return true;
2239- }
2240-
2241- return false;
2242- }
2243-
2244- public static dynamic Gst.Element get_clutter_sink ()
2245- {
2246- var sink = Gst.ElementFactory.make ("autocluttersink", "videosink");
2247- if (sink == null) {
2248- warning ("autocluttersink not available");
2249- sink = Gst.ElementFactory.make ("cluttersink", "videosink");
2250- }
2251-
2252- return sink;
2253- }
2254-
2255- /*
2256- * get a thumbnail from a file
2257- * @param file the file
2258- * @param position the position in the video or -1 for 5%
2259- * @param pixbuf gtkclutter texture to put the pixbuf in once it's ready
2260- * TODO appears not to load thumbs for bigger files
2261- **/
2262- /* NOT NEEDED CURRENTLY
2263- public static void get_thumb (File file, int64 position, GtkClutter.Texture tex) {
2264- //pipeline
2265- bool got_video = false;
2266- var pipe = new Gst.Pipeline ("pipeline");
2267- var src = Gst.ElementFactory.make ("filesrc", "file");
2268- dynamic Gst.Element dec = Gst.ElementFactory.make ("decodebin2", "dec");
2269-
2270- pipe.add_many (src, dec);
2271- src.link (dec);
2272- src.set ("location", file.get_path ());
2273- dynamic Gst.Element sink = null;
2274- dec.pad_added.connect ( (new_pad) => {
2275- if (got_video)
2276- return;
2277-
2278- var csp = Gst.ElementFactory.make ("ffmpegcolorspace", "f");
2279- var scale = Gst.ElementFactory.make ("videoscale", "s");
2280- var filter = Gst.ElementFactory.make ("capsfilter", "c");
2281- sink = Gst.ElementFactory.make ("gdkpixbufsink", "sink");
2282-
2283- pipe.add_many (csp, scale, filter, sink);
2284-
2285- var sinkpad = csp.get_static_pad ("sink");
2286- new_pad.link (sinkpad);
2287-
2288- csp.link (scale);
2289- scale.link (filter);
2290- filter.link (sink);
2291-
2292- sink.set_state (Gst.State.PAUSED);
2293- filter.set_state (Gst.State.PAUSED);
2294- scale.set_state (Gst.State.PAUSED);
2295- csp.set_state (Gst.State.PAUSED);
2296-
2297- got_video = true;
2298- });
2299-
2300- pipe.get_bus ().add_signal_watch ();
2301-
2302- pipe.set_state (Gst.State.PAUSED);
2303-
2304- bool ready = false;
2305- pipe.get_bus ().message.connect ( (bus, msg) => {
2306- switch (msg.type) {
2307- case Gst.MessageType.ASYNC_DONE:
2308- if (msg.src != pipe)
2309- break;
2310- var fmt = Gst.Format.TIME;
2311- int64 pos;
2312- pipe.query_position (fmt, out pos);
2313- if (pos > 1)
2314- ready = true;
2315- else
2316- break;
2317- if (position == -1) {
2318- int64 dur;
2319- pipe.query_duration (fmt, out dur);
2320- pipe.seek_simple (Gst.Format.TIME, Gst.SeekFlags.ACCURATE |
2321- Gst.SeekFlags.FLUSH, (int64)(dur*0.5));
2322- }else {
2323- pipe.seek_simple (Gst.Format.TIME, Gst.SeekFlags.ACCURATE |
2324- Gst.SeekFlags.FLUSH, position);
2325- }
2326- break;
2327- case Gst.MessageType.ELEMENT:
2328- if (!ready)
2329- break;
2330- if (msg.src != sink)
2331- break;
2332- if (!msg.get_structure ().has_name ("prerollpixbuf") &&
2333- !msg.get_structure ().has_name ("pixbuf"))
2334- break;
2335- var val = msg.get_structure ().get_value ("pixbuf");
2336- var pixbuf = (Gdk.Pixbuf)val.dup_object ();
2337- if (pixbuf == null)
2338- return;
2339- try {
2340- tex.set_from_pixbuf (pixbuf);
2341- } catch (Error e) {warning (e.message);}
2342- pipe.set_state (Gst.State.NULL);
2343- break;
2344- default:
2345- break;
2346- }
2347- });
2348-
2349- pipe.set_state (Gst.State.PLAYING);
2350- }*/
2351-
2352- namespace Drawing {
2353-
2354- /**
2355- * Draws a popover shape
2356- */
2357- public static void cairo_popover (Cairo.Context cr, double x, double y, double width, double height,
2358- double radius, double arrow_height, double arrow_width)
2359- {
2360- double edge_width = (width - radius * 2);
2361- double arrow_offset = (edge_width - arrow_width) / 2;
2362-
2363-
2364- cr.arc (x + width - radius, y + radius, radius, Math.PI * 1.5, Math.PI * 2);
2365- cr.arc (x + width - radius, y + height - radius, radius, 0, Math.PI * 0.5);
2366-
2367- cr.arc (x + radius, y + height - radius, radius, Math.PI * 0.5, Math.PI);
2368- cr.arc (x + radius, y + radius, radius, Math.PI, Math.PI * 1.5);
2369- cr.move_to (x + radius + arrow_offset, y + height);
2370-
2371- cr.rel_line_to (arrow_width / 2, arrow_height);
2372- cr.rel_line_to (arrow_width / 2, -arrow_height);
2373-
2374- cr.close_path ();
2375- }
2376-
2377- /**
2378- * Draws a 'pill' shape (rounded rectangle with boder radius such that both ends are semicircles)
2379- */
2380- public static void cairo_pill (Cairo.Context cr, double x, double y, double width, double height) {
2381- Granite.Drawing.Utilities.cairo_rounded_rectangle (cr, x, y, width, height, height / 2);
2382- }
2383-
2384- /**
2385- * Draws a ' halfpill' shape (rounded rectangle with boder radius such that one ends is a semicircle)
2386- */
2387- public static void cairo_half_pill (Cairo.Context cr, double x, double y, double width, double height, Gtk.PositionType side) {
2388- double radius = height / 2;
2389- cr.move_to (x + radius, y);
2390- switch (side) {
2391- case Gtk.PositionType.LEFT:
2392- cr.arc (x + width - radius, y + radius, radius, Math.PI * 1.5, Math.PI * 0.5);
2393- cr.line_to ((int)x, y + height); // (int) required to not draw 'half' pixels (blurry)
2394- cr.line_to ((int)x, y);
2395- cr.line_to ((int)(x + width - radius), y);
2396- break;
2397- case Gtk.PositionType.RIGHT:
2398- cr.arc (x + radius, y + height - radius, radius, Math.PI * 0.5, Math.PI * 1.5);
2399- cr.line_to ((int)(x + width), y);
2400- cr.line_to ((int)(x + width), y + height);
2401- cr.line_to ((int)(x + radius), y + height);
2402- break;
2403- default:
2404- assert_not_reached();
2405- }
2406- cr.close_path ();
2407- }
2408-
2409-
2410+ var disk_manager = DiskManager.get_default ();
2411+ return disk_manager.get_volumes ().length () > 0;
2412 }
2413 }
2414\ No newline at end of file
2415
2416=== added file 'src/Widgets/BottomBar.vala'
2417--- src/Widgets/BottomBar.vala 1970-01-01 00:00:00 +0000
2418+++ src/Widgets/BottomBar.vala 2014-07-06 11:18:29 +0000
2419@@ -0,0 +1,160 @@
2420+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
2421+/*-
2422+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
2423+ *
2424+ * This program is free software: you can redistribute it and/or modify
2425+ * it under the terms of the GNU General Public License as published by
2426+ * the Free Software Foundation, either version 3 of the License, or
2427+ * (at your option) any later version.
2428+
2429+ * This program is distributed in the hope that it will be useful,
2430+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2431+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2432+ * GNU General Public License for more details.
2433+
2434+ * You should have received a copy of the GNU General Public License
2435+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2436+ *
2437+ * Authored by: Corentin Noël <corentin@elementaryos.org>
2438+ */
2439+
2440+public class Audience.Widgets.BottomBar : Gtk.Revealer {
2441+ public signal void play_toggled ();
2442+ public signal void unfullscreen ();
2443+ public signal void seeked (double val);
2444+
2445+ public bool hovered { get; set; default=false; }
2446+ public bool fullscreen { get; set; default=false; }
2447+ public SettingsPopover preferences_popover;
2448+ public TimeWidget time_widget;
2449+
2450+ private Gtk.Button play_button;
2451+ private Gtk.Button preferences_button;
2452+ private Gtk.Revealer unfullscreen_revealer;
2453+ private PlaylistPopover playlist_popover;
2454+ private bool is_playing = false;
2455+ private uint hiding_timer = 0;
2456+
2457+ public BottomBar () {
2458+ transition_type = Gtk.RevealerTransitionType.CROSSFADE;
2459+ var main_actionbar = new Gtk.ActionBar ();
2460+ main_actionbar.opacity = GLOBAL_OPACITY;
2461+
2462+ play_button = new Gtk.Button.from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.BUTTON);
2463+ play_button.tooltip_text = _("Play");
2464+ play_button.clicked.connect (() => {play_toggled ();});
2465+
2466+ var playlist_button = new Gtk.Button.from_icon_name ("view-list-symbolic", Gtk.IconSize.BUTTON);
2467+ playlist_button.tooltip_text = _("Playlist");
2468+ playlist_button.clicked.connect (() => {playlist_popover.show_all (); playlist_popover.queue_resize ();});
2469+
2470+ preferences_button = new Gtk.Button.from_icon_name ("document-properties-symbolic", Gtk.IconSize.BUTTON);
2471+ preferences_button.tooltip_text = _("Settings");
2472+ preferences_button.clicked.connect (() => {preferences_popover.show_all (); preferences_popover.queue_resize ();});
2473+
2474+ time_widget = new TimeWidget ();
2475+ time_widget.seeked.connect ((val) => {seeked (val);});
2476+
2477+ playlist_popover = new PlaylistPopover ();
2478+ playlist_popover.relative_to = playlist_button;
2479+ preferences_popover = new SettingsPopover ();
2480+ preferences_popover.relative_to = preferences_button;
2481+
2482+ main_actionbar.pack_start (play_button);
2483+ main_actionbar.set_center_widget (time_widget);
2484+ main_actionbar.pack_end (preferences_button);
2485+ main_actionbar.pack_end (playlist_button);
2486+ add (main_actionbar);
2487+
2488+ notify["hovered"].connect (() => {
2489+ if (hovered == false) {
2490+ set_timeout ();
2491+ } else {
2492+ if (hiding_timer != 0) {
2493+ Source.remove (hiding_timer);
2494+ hiding_timer = 0;
2495+ }
2496+ }
2497+ });
2498+
2499+ notify["fullscreen"].connect (() => {
2500+ if (fullscreen == true && child_revealed == true) {
2501+ unfullscreen_revealer.set_reveal_child (true);
2502+ } else if (fullscreen == false && child_revealed == true) {
2503+ unfullscreen_revealer.set_reveal_child (false);
2504+ }
2505+ });
2506+
2507+ show_all ();
2508+ }
2509+
2510+ public void set_preview_uri (string uri) {
2511+ time_widget.set_preview_uri (uri);
2512+ }
2513+
2514+ public Gtk.Revealer get_unfullscreen_button () {
2515+ unfullscreen_revealer = new Gtk.Revealer ();
2516+ unfullscreen_revealer.opacity = GLOBAL_OPACITY;
2517+ unfullscreen_revealer.get_style_context ().add_class ("header-bar");
2518+ unfullscreen_revealer.transition_type = Gtk.RevealerTransitionType.CROSSFADE;
2519+ var unfullscreen_button = new Gtk.Button.from_icon_name ("view-restore-symbolic", Gtk.IconSize.BUTTON);
2520+ unfullscreen_button.tooltip_text = _("Unfullscreen");
2521+ unfullscreen_button.clicked.connect (() => {unfullscreen ();});
2522+ unfullscreen_revealer.add (unfullscreen_button);
2523+ unfullscreen_revealer.show_all ();
2524+ return unfullscreen_revealer;
2525+ }
2526+
2527+ public void toggle_play_pause () {
2528+ is_playing = !is_playing;
2529+ if (is_playing == true) {
2530+ play_button.image = new Gtk.Image.from_icon_name ("media-playback-pause-symbolic", Gtk.IconSize.BUTTON);
2531+ play_button.tooltip_text = _("Pause");
2532+ set_timeout ();
2533+ } else {
2534+ play_button.image = new Gtk.Image.from_icon_name ("media-playback-start-symbolic", Gtk.IconSize.BUTTON);
2535+ play_button.tooltip_text = _("Play");
2536+ set_reveal_child (true);
2537+ }
2538+ }
2539+
2540+ public new void set_reveal_child (bool reveal) {
2541+ base.set_reveal_child (reveal);
2542+ if (reveal == true && fullscreen == true) {
2543+ unfullscreen_revealer.set_reveal_child (reveal);
2544+ } else if (reveal == false) {
2545+ unfullscreen_revealer.set_reveal_child (reveal);
2546+ }
2547+ }
2548+
2549+ public override void get_preferred_width (out int minimum_width, out int natural_width) {
2550+ base.get_preferred_width (out minimum_width, out natural_width);
2551+ if (parent.get_window () == null)
2552+ return;
2553+
2554+ var width = parent.get_window ().get_width ();
2555+ if (width > 0 && width >= minimum_width) {
2556+ natural_width = width;
2557+ }
2558+ }
2559+
2560+ public void set_progression_time (double current_time, double total_time) {
2561+ time_widget.set_progression_time (current_time, total_time);
2562+ }
2563+
2564+ private void set_timeout () {
2565+ if (hiding_timer != 0)
2566+ Source.remove (hiding_timer);
2567+
2568+ hiding_timer = GLib.Timeout.add (2000, () => {
2569+ if (hovered == true || preferences_popover.visible == true || playlist_popover.visible == true || is_playing == false) {
2570+ hiding_timer = 0;
2571+ return false;
2572+ }
2573+ set_reveal_child (false);
2574+ unfullscreen_revealer.set_reveal_child (false);
2575+ hiding_timer = 0;
2576+ return false;
2577+ });
2578+ }
2579+}
2580\ No newline at end of file
2581
2582=== removed file 'src/Widgets/Button.vala'
2583--- src/Widgets/Button.vala 2013-05-19 17:10:26 +0000
2584+++ src/Widgets/Button.vala 1970-01-01 00:00:00 +0000
2585@@ -1,53 +0,0 @@
2586-
2587-namespace Audience.Widgets{
2588-
2589- public class Button : GtkClutter.Texture {
2590- public signal void clicked ();
2591-
2592- bool pressed = false;
2593-
2594- public Button (string icon, string fallback, string alt_fallback=""){
2595- set_icon (icon, fallback, alt_fallback);
2596-
2597- reactive = true;
2598- width = 16;
2599- height = 16;
2600- opacity = 255;
2601- }
2602-
2603- public override bool leave_event (Clutter.CrossingEvent event) {
2604- animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity:255);
2605- return true;
2606- }
2607-
2608- public override bool enter_event (Clutter.CrossingEvent event) {
2609- animate (Clutter.AnimationMode.EASE_OUT_QUAD, 200, opacity:170);
2610- return true;
2611- }
2612-
2613- public override bool button_press_event (Clutter.ButtonEvent event) {
2614- pressed = true;
2615- return true;
2616- }
2617-
2618- public override bool button_release_event (Clutter.ButtonEvent event) {
2619- if (pressed) {
2620- clicked ();
2621- pressed = false;
2622- }
2623- return true;
2624- }
2625-
2626- public void set_icon (string icon, string fallback, string alt_fallback="") {
2627- try {
2628- var ti = new ThemedIcon.from_names ({icon, alt_fallback, fallback});
2629- var l = Gtk.IconTheme.get_default ().lookup_by_gicon (ti, 16, 0);
2630- if (l != null) {
2631- this.set_from_pixbuf (l.load_symbolic ({1.0,1.0,1.0,1.0}, null, null, null, null));
2632- } else {
2633- warning("NULL detected when trying to load icon: " + icon + " (or " + fallback + ")");
2634- }
2635- } catch (Error e){warning (e.message);}
2636- }
2637- }
2638-}
2639
2640=== removed file 'src/Widgets/ControlsBar.vala'
2641--- src/Widgets/ControlsBar.vala 2013-05-19 17:10:26 +0000
2642+++ src/Widgets/ControlsBar.vala 1970-01-01 00:00:00 +0000
2643@@ -1,137 +0,0 @@
2644-using Clutter;
2645-
2646-namespace Audience.Widgets
2647-{
2648- public class Controls : Actor
2649- {
2650- public MediaSlider slider;
2651- public Button play;
2652- public Button view;
2653- public Button open;
2654-
2655- public Text current;
2656- public Text remaining;
2657-
2658- private Gdk.Pixbuf play_pix;
2659- private Gdk.Pixbuf pause_pix;
2660-
2661- public bool showing_view = false;
2662- public bool hovered { get; set; }
2663-
2664- public Controls ()
2665- {
2666- layout_manager = new BoxLayout ();
2667- content = new Canvas ();
2668-
2669- (layout_manager as BoxLayout).spacing = 10;
2670-
2671- this.current = new Text.full ("", "0", {255,255,255,255});
2672- this.remaining = new Text.full ("", "0", {255,255,255,255});
2673-
2674- this.slider = new MediaSlider ();
2675-
2676- this.play = new Button ("media-playback-start-symbolic", Gtk.Stock.MEDIA_PLAY);
2677-
2678- this.view = new Button ("pane-show-symbolic", Gtk.Stock.GO_BACK, "go-previous-symbolic");
2679-
2680- this.open = new Button ("list-add-symbolic", Gtk.Stock.OPEN);
2681-
2682- var spacer_left = new Rectangle.with_color ({0,0,0,0});
2683- spacer_left.width = 0;
2684- var spacer_right = new Rectangle.with_color ({0,0,0,0});
2685- spacer_right.width = 0;
2686-
2687- this.add_child (spacer_left);
2688- this.add_child (this.play);
2689- this.add_child (this.current);
2690- this.add_child (this.slider);
2691- this.add_child (this.remaining);
2692- this.add_child (this.open);
2693- this.add_child (this.view);
2694- this.add_child (spacer_right);
2695-
2696- (layout_manager as BoxLayout).set_expand (slider, true);
2697- (layout_manager as BoxLayout).set_fill (slider, true, true);
2698-
2699- /*setup a css style for the control background*/
2700- var style_holder = new Gtk.EventBox ();
2701- var css = new Gtk.CssProvider ();
2702- try{css.load_from_data ("""
2703- * {
2704- engine: unico;
2705- background-image: -gtk-gradient (linear,
2706- left top, left bottom,
2707- from (alpha(#323232, 0.698)),
2708- to (alpha(#242424, 0.698)));
2709-
2710- -unico-outer-stroke-gradient: -gtk-gradient (linear,
2711- left top, left bottom,
2712- from (alpha(#161616, 0.698)),
2713- to (alpha(#000000, 0.698)));
2714- -unico-inner-stroke-gradient: -gtk-gradient (linear,
2715- left top, left bottom,
2716- from (alpha(#ffffff, 0.149)),
2717- color-stop (0.1, alpha(#ffffff, 0.035)),
2718- color-stop (0.9, alpha(#ffffff, 0.024)),
2719- to (alpha(#ffffff, 0.059)));
2720- -unico-inner-stroke-width: 1;
2721- -unico-outer-stroke-width: 1;
2722- }
2723- """, -1);}catch (Error e){warning (e.message);}
2724- style_holder.get_style_context ().add_provider (css, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
2725-
2726- (content as Canvas).draw.connect ( (ctx) => {
2727- ctx.set_operator (Cairo.Operator.CLEAR);
2728- ctx.paint ();
2729- ctx.set_operator (Cairo.Operator.OVER);
2730-
2731- style_holder.get_style_context ().render_background (ctx, -2, 0, width+4, CONTROLS_HEIGHT+1);
2732- style_holder.get_style_context ().render_frame (ctx, -2, 0, width+4, CONTROLS_HEIGHT+1);
2733-
2734- return false;
2735- });
2736- (content as Canvas).set_size (500, CONTROLS_HEIGHT);
2737-
2738- try {
2739- var l = Gtk.IconTheme.get_default ().lookup_icon ("media-playback-pause-symbolic", 16, 0);
2740- if (l == null)
2741- this.pause_pix = new Gtk.Image.from_stock (Gtk.Stock.MEDIA_PAUSE, Gtk.IconSize.LARGE_TOOLBAR).pixbuf;
2742- else
2743- this.pause_pix = l.load_symbolic ({1.0,1.0,1.0,1.0}, null, null, null, null);
2744- } catch (Error e) { warning (e.message); }
2745-
2746- try {
2747- var l = Gtk.IconTheme.get_default ().lookup_icon ("media-playback-start-symbolic", 16, 0);
2748- if (l == null)
2749- this.play_pix = new Gtk.Image.from_stock (Gtk.Stock.MEDIA_PLAY, Gtk.IconSize.LARGE_TOOLBAR).pixbuf;
2750- else
2751- this.play_pix = l.load_symbolic ({1.0,1.0,1.0,1.0}, null, null, null, null);
2752- } catch (Error e) { warning (e.message); }
2753-
2754- this.height = CONTROLS_HEIGHT;
2755-
2756- this.reactive = true;
2757- this.enter_event.connect ( () => {
2758- this.hovered = true;
2759- return false;
2760- });
2761- this.leave_event.connect ( (e) => {
2762- if (!contains (e.related))
2763- this.hovered = false;
2764- return false;
2765- });
2766- }
2767-
2768- // catch all button presses
2769- public override bool button_press_event (Clutter.ButtonEvent event) {
2770- return true;
2771- }
2772-
2773- public void show_play_button (bool show){ /*or show pause button*/
2774- try{
2775- this.play.set_from_pixbuf ((show)?play_pix:pause_pix);
2776- }catch (Error e){warning (e.message);}
2777- }
2778- }
2779-
2780-}
2781
2782=== removed file 'src/Widgets/LLabel.vala'
2783--- src/Widgets/LLabel.vala 2012-08-21 14:56:49 +0000
2784+++ src/Widgets/LLabel.vala 1970-01-01 00:00:00 +0000
2785@@ -1,27 +0,0 @@
2786-
2787-namespace Audience.Widgets{
2788-
2789- class LLabel : Gtk.Label {
2790- public LLabel (string label) {
2791- this.set_halign (Gtk.Align.START);
2792- this.label = label;
2793- }
2794- public LLabel.indent (string label) {
2795- this (label);
2796- this.margin_left = 10;
2797- }
2798- public LLabel.markup (string label) {
2799- this (label);
2800- this.use_markup = true;
2801- }
2802- public LLabel.right (string label) {
2803- this.set_halign (Gtk.Align.END);
2804- this.label = label;
2805- }
2806- public LLabel.right_with_markup (string label) {
2807- this.set_halign (Gtk.Align.END);
2808- this.use_markup = true;
2809- this.label = label;
2810- }
2811- }
2812-}
2813
2814=== removed file 'src/Widgets/MediaSlider.vala'
2815--- src/Widgets/MediaSlider.vala 2014-04-28 12:58:09 +0000
2816+++ src/Widgets/MediaSlider.vala 1970-01-01 00:00:00 +0000
2817@@ -1,238 +0,0 @@
2818-
2819-namespace Audience.Widgets{
2820-
2821- public class MediaSlider : Clutter.Group {
2822-
2823- public signal void seeked (double new_progress);
2824-
2825- public Clutter.Texture preview;
2826- public Clutter.Actor preview_bg;
2827- dynamic Gst.Element preview_playbin;
2828- dynamic Gst.Element sink;
2829-
2830- double progress_stacked = 0.0;
2831- bool seeking = false;
2832-
2833- private double _buffered;
2834- public double buffered{
2835- get { return _buffered; }
2836- set { _buffered = value; this.bar.invalidate (); }
2837- }
2838-
2839- private double _progress;
2840- public double progress{
2841- get { return _progress; }
2842- set { _progress = value; this.bar.invalidate (); }
2843- }
2844-
2845- private Clutter.CairoTexture bar;
2846-
2847- private const int BAR_HEIGHT = 8;
2848-
2849- /*the mouse is currently on the controls*/
2850- public bool mouse_grabbed = false;
2851-
2852- public MediaSlider () {
2853- this.preview = new Clutter.Texture ();
2854- this._buffered = 0.0;
2855- this._progress = 0.0;
2856- this.bar = new Clutter.CairoTexture (1, BAR_HEIGHT);
2857-
2858- preview.filter_quality = Clutter.TextureQuality.HIGH;
2859- preview.scale_x = 0.0;
2860- preview.scale_y = 0.0;
2861- preview.scale_gravity = Clutter.Gravity.CENTER;
2862- preview.height = 90.0f;
2863- // preview.width is set in VideoPlayer.vala
2864-
2865- // connect gstreamer stuff
2866- preview_playbin = Gst.ElementFactory.make ("playbin", "play");
2867- preview_playbin.get_bus ().add_signal_watch ();
2868- preview_playbin.get_bus ().message.connect ((msg) => {
2869- switch (msg.type) {
2870- case Gst.MessageType.STATE_CHANGED:
2871- if (progress_stacked != 0)
2872- seek (progress_stacked);
2873- break;
2874- case Gst.MessageType.ASYNC_DONE:
2875- if (seeking) {
2876- seeking = false;
2877- if (progress_stacked != 0)
2878- seek (progress_stacked);
2879- }
2880- break;
2881- }
2882- });
2883- sink = Audience.get_clutter_sink ();
2884- sink.texture = preview;
2885- preview_playbin.video_sink = sink;
2886-
2887- preview_bg = new Clutter.Actor ();
2888- preview_bg.y = -120.0f;
2889- preview_bg.add_constraint (new Clutter.BindConstraint (preview, Clutter.BindCoordinate.WIDTH, 30.0f));
2890- preview_bg.add_constraint (new Clutter.BindConstraint (preview, Clutter.BindCoordinate.HEIGHT, 45.0f));
2891- preview_bg.opacity = 0;
2892- preview_bg.content = new Clutter.Canvas ();
2893- preview_bg.allocation_changed.connect (() => {
2894- (preview_bg.content as Clutter.Canvas).set_size ((int)preview_bg.width, (int)preview_bg.height);
2895- });
2896- var ARROW_HEIGHT = 17;
2897- var ARROW_WIDTH = 20;
2898- var popover_grad = new Cairo.Pattern.linear (0, 0, 0, preview_bg.height);
2899- popover_grad.add_color_stop_rgba (0.0, 0.243, 0.243, 0.243, 0.7);
2900- popover_grad.add_color_stop_rgba (1.0, 0.094, 0.094, 0.094, 0.7);
2901-
2902- var popover_inset_grad = new Cairo.Pattern.linear (0, 0, 0, preview_bg.height);
2903- popover_inset_grad.add_color_stop_rgba (0.0, 1, 1, 1, 0.3);
2904- popover_inset_grad.add_color_stop_rgba (1.0, 1, 1, 1, 0.1);
2905- (preview_bg.content as Clutter.Canvas).draw.connect ( (ctx) => {
2906- ctx.set_operator (Cairo.Operator.CLEAR);
2907- ctx.paint ();
2908- ctx.set_operator (Cairo.Operator.OVER);
2909-
2910- // Outline
2911- Drawing.cairo_popover (ctx, 0, 0, preview_bg.width,
2912- preview_bg.height - ARROW_HEIGHT, 3, ARROW_WIDTH, ARROW_HEIGHT);
2913- ctx.set_source_rgba (0, 0, 0, 0.7);
2914- ctx.fill ();
2915-
2916- // Inset border
2917- Drawing.cairo_popover (ctx, 1, 1, preview_bg.width - 2,
2918- preview_bg.height - 2 - ARROW_HEIGHT, 3, ARROW_WIDTH - 2, ARROW_HEIGHT - 2);
2919- ctx.set_source (popover_inset_grad);
2920- ctx.fill ();
2921-
2922- ctx.set_operator(Cairo.Operator.SOURCE);
2923- // Fill
2924- Drawing.cairo_popover (ctx, 2, 2, preview_bg.width - 4,
2925- preview_bg.height - 4 - ARROW_HEIGHT, 3, ARROW_WIDTH - 4, ARROW_HEIGHT - 4);
2926- ctx.set_source (popover_grad);
2927- ctx.fill ();
2928-
2929- ctx.set_operator(Cairo.Operator.OVER);
2930- return true;
2931- });
2932-
2933- this.bar.y = CONTROLS_HEIGHT / 2 - BAR_HEIGHT / 2;
2934- this.bar.auto_resize = true;
2935- var bar_grad = new Cairo.Pattern.linear (0, 0, 0, BAR_HEIGHT);
2936- bar_grad.add_color_stop_rgba (0.0, 0.254, 0.247, 0.231, 0.4);
2937- bar_grad.add_color_stop_rgba (1.0, 0.298, 0.290, 0.282, 0.4);
2938- var bar_shadow_grad = new Cairo.Pattern.linear (0, 0, 0, BAR_HEIGHT);
2939- bar_shadow_grad.add_color_stop_rgba (0.0, 1, 1, 1, 0);
2940- bar_shadow_grad.add_color_stop_rgba (1.0, 1, 1, 1, 0.2);
2941- this.bar.draw.connect ( (ctx) => {
2942- this.bar.clear();
2943- //drop shadow
2944- Drawing.cairo_pill (ctx, 0, 0, this.bar.width, BAR_HEIGHT);
2945- ctx.set_source (bar_shadow_grad);
2946- ctx.fill ();
2947- //outline
2948- Drawing.cairo_pill (ctx, 1, 1, this.bar.width - 2, BAR_HEIGHT - 2);
2949- ctx.set_source_rgba (0, 0, 0, 0.4);
2950- ctx.fill ();
2951- //bg
2952- Drawing.cairo_pill (ctx, 2, 2, this.bar.width - 4, BAR_HEIGHT - 4);
2953- ctx.set_source (bar_grad);
2954- ctx.fill ();
2955- //buffering
2956- if (this._buffered != 0.0){
2957- int64 duration;
2958- preview_playbin.query_duration (Gst.Format.TIME, out duration);
2959- Drawing.cairo_half_pill (ctx, 2, 2,
2960- (this._buffered / duration * this.bar.width) - 4, BAR_HEIGHT - 4, Gtk.PositionType.RIGHT);
2961- ctx.set_source_rgb (0.6, 0.6, 0.6);
2962- ctx.fill ();
2963- }
2964- //progress
2965- if (this._progress != 0.0){
2966- Drawing.cairo_half_pill (ctx, 2, 2, (this._progress * this.width) - 4, BAR_HEIGHT - 4, Gtk.PositionType.RIGHT);
2967- ctx.set_source_rgb (1.0, 1.0, 1.0);
2968- ctx.fill ();
2969- }
2970- return true;
2971- });
2972-
2973- var scalex = new Clutter.BindConstraint (this, Clutter.BindCoordinate.WIDTH, 0);
2974- bar.add_constraint (scalex);
2975-
2976- //seek
2977- preview.reactive = true;
2978-
2979- reactive = true;
2980- add_child (bar);
2981- add_child (preview_bg);
2982- }
2983-
2984- public override bool motion_event (Clutter.MotionEvent event)
2985- {
2986- float local_x, local_y;
2987- this.transform_stage_point (event.x, event.y, out local_x, out local_y);
2988-
2989- preview.x = event.x - preview.width / 2;
2990- preview_bg.x = local_x - preview.width / 2 - 15.0f;
2991-
2992- seek (float.max (local_x, 0.0000001f) / this.width);
2993-
2994- return true;
2995- }
2996-
2997- public override bool enter_event (Clutter.CrossingEvent event)
2998- {
2999- this.preview.animate (Clutter.AnimationMode.EASE_OUT_ELASTIC, 800,
3000- scale_x:1.0, scale_y:1.0);
3001- preview_bg.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 500, opacity:240);
3002- preview_toggle_playing (true);
3003- this.mouse_grabbed = true;
3004- return false;
3005- }
3006-
3007- public override bool leave_event (Clutter.CrossingEvent event)
3008- {
3009- preview.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 150,
3010- scale_x:0.0, scale_y:0.0);
3011- preview_bg.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 150, opacity:0);
3012- preview_toggle_playing (false);
3013- mouse_grabbed = false;
3014- return false;
3015- }
3016-
3017- public override bool button_release_event (Clutter.ButtonEvent event)
3018- {
3019- float x, y;
3020- this.transform_stage_point (event.x, event.y, out x, out y);
3021- this.seeked (x / this.width);
3022- return true;
3023- }
3024-
3025- public void set_preview_uri (string uri)
3026- {
3027- preview_playbin.set_state (Gst.State.READY);
3028- preview_playbin.uri = uri;
3029- preview_playbin.volume = 0.0;
3030- }
3031-
3032- void preview_toggle_playing (bool play)
3033- {
3034- this.preview_playbin.set_state (play ? Gst.State.PLAYING : Gst.State.PAUSED);
3035- }
3036-
3037- void seek (double progress)
3038- {
3039- if (seeking) {
3040- progress_stacked = progress;
3041- return;
3042- }
3043-
3044- int64 duration;
3045- preview_playbin.query_duration (Gst.Format.TIME, out duration);
3046- preview_playbin.seek (1.0, Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
3047- Gst.SeekType.SET, (int64)(progress * duration),
3048- Gst.SeekType.NONE, (int64)Gst.CLOCK_TIME_NONE);
3049-
3050- this.progress_stacked = 0;
3051-
3052- seeking = true;
3053- }
3054- }
3055-}
3056
3057=== modified file 'src/Widgets/Playlist.vala'
3058--- src/Widgets/Playlist.vala 2012-08-21 14:56:49 +0000
3059+++ src/Widgets/Playlist.vala 2014-07-06 11:18:29 +0000
3060@@ -1,93 +1,98 @@
3061-
3062+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
3063+/*-
3064+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
3065+ *
3066+ * This program is free software: you can redistribute it and/or modify
3067+ * it under the terms of the GNU General Public License as published by
3068+ * the Free Software Foundation, either version 3 of the License, or
3069+ * (at your option) any later version.
3070+
3071+ * This program is distributed in the hope that it will be useful,
3072+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3073+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3074+ * GNU General Public License for more details.
3075+
3076+ * You should have received a copy of the GNU General Public License
3077+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3078+ *
3079+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
3080+ */
3081
3082 namespace Audience.Widgets {
3083-
3084 public class Playlist : Gtk.TreeView {
3085-
3086- /*the player is requested to play path*/
3087+ // the player is requested to play path
3088 public signal void play (File path);
3089
3090- private int current;
3091- private Gtk.ListStore playlist;
3092+ private enum Columns {
3093+ PLAYING,
3094+ TITLE,
3095+ FILENAME,
3096+ N_COLUMNS
3097+ }
3098+
3099+ private int current = 0;
3100+ private Gtk.ListStore playlist;
3101
3102 public Playlist () {
3103- this.current = 0;
3104- this.playlist = new Gtk.ListStore (4, typeof (Gdk.Pixbuf), /*playing*/
3105- typeof (Gdk.Pixbuf), /*icon*/
3106- typeof (string), /*title*/
3107- typeof (string)); /*filename*/
3108+ this.playlist = new Gtk.ListStore (Columns.N_COLUMNS, typeof (Icon), typeof (string), typeof (string));
3109 this.model = this.playlist;
3110 this.expand = true;
3111 this.headers_visible = false;
3112+ this.activate_on_single_click = true;
3113+ this.can_focus = false;
3114+ get_selection ().mode = Gtk.SelectionMode.NONE;
3115
3116 var text_render = new Gtk.CellRendererText ();
3117 text_render.ellipsize = Pango.EllipsizeMode.END;
3118
3119- this.insert_column_with_attributes (-1, "", new Gtk.CellRendererPixbuf (),
3120- "pixbuf", 0);
3121- this.insert_column_with_attributes (-1, "", new Gtk.CellRendererPixbuf (),
3122- "pixbuf", 1);
3123- this.insert_column_with_attributes (-1, "", text_render, "text", 2);
3124+ this.insert_column_with_attributes (-1, "Playing", new Gtk.CellRendererPixbuf (), "gicon", Columns.PLAYING);
3125+ this.insert_column_with_attributes (-1, "Title", text_render, "text", Columns.TITLE);
3126
3127- this.row_activated.connect ( (path ,col) => {
3128+ this.row_activated.connect ((path ,col) => {
3129 Gtk.TreeIter iter;
3130 playlist.get_iter (out iter, path);
3131 string filename;
3132- playlist.get (iter, 3, out filename);
3133+ playlist.get (iter, Columns.FILENAME, out filename);
3134 play (File.new_for_commandline_arg (filename));
3135 change_current_symbol (iter);
3136 this.current = int.parse (path.to_string ());
3137 });
3138
3139 this.reorderable = true;
3140- this.model.row_inserted.connect ( (path, iter) => {
3141+ this.model.row_inserted.connect ((path, iter) => {
3142 Gtk.TreeIter it;
3143 playlist.get_iter (out it, path);
3144 Gdk.Pixbuf playing;
3145- playlist.get (it, 0, out playing);
3146+ playlist.get (it, Columns.PLAYING, out playing);
3147 if (playing != null) //if playing is not null it's the current item
3148 this.current = int.parse (path.to_string ());
3149 });
3150-
3151- var css_fix = new Gtk.CssProvider ();
3152- try {
3153- css_fix.load_from_data ("
3154- * {
3155- background-image:none;
3156- background-color:@transparent;
3157- border-color:@transparent;
3158- }", -1);
3159- } catch (Error e) { warning (e.message); }
3160- this.get_style_context ().add_provider (css_fix, 20000);
3161 }
3162
3163 private inline void change_current_symbol (Gtk.TreeIter new_item) {
3164- try{
3165- playlist.set (new_item, 0, Gtk.IconTheme.get_default ().
3166- load_icon ("media-playback-start-symbolic", 16, 0));
3167- }catch (Error e) { warning (e.message); }
3168 Gtk.TreeIter old_item;
3169 playlist.get_iter_from_string (out old_item, this.current.to_string ());
3170- playlist.set (old_item, 0, null);
3171+ playlist.set (old_item, Columns.PLAYING, null);
3172+ playlist.set (new_item, Columns.PLAYING, new ThemedIcon ("media-playback-start-symbolic"));
3173 }
3174
3175 public void next () {
3176- Gtk.TreeIter it;
3177- if (playlist.get_iter_from_string (out it, (this.current + 1).to_string ())){
3178+ Gtk.TreeIter iter;
3179+ if (playlist.get_iter_from_string (out iter, (this.current + 1).to_string ())){
3180 string filename;
3181- playlist.get (it, 3, out filename);
3182- change_current_symbol (it);
3183+ playlist.get (iter, Columns.FILENAME, out filename);
3184+ change_current_symbol (iter);
3185 current++;
3186 play (File.new_for_commandline_arg (filename));
3187 }
3188 }
3189
3190 public void previous () {
3191- Gtk.TreeIter it;
3192- if (playlist.get_iter_from_string (out it, (this.current - 1).to_string ())){
3193+ Gtk.TreeIter iter;
3194+ if (playlist.get_iter_from_string (out iter, (this.current - 1).to_string ())){
3195 string filename;
3196- playlist.get (it, 3, out filename);
3197- change_current_symbol (it);
3198+ playlist.get (iter, Columns.FILENAME, out filename);
3199+ change_current_symbol (iter);
3200 current--;
3201 play (File.new_for_commandline_arg (filename));
3202 }
3203@@ -95,37 +100,67 @@
3204
3205 public void add_item (File path) {
3206 Gtk.TreeIter iter;
3207- Gdk.Pixbuf pix = null; //may becoming the thumb...
3208
3209- Gdk.Pixbuf? playing = null;
3210+ Icon? playing = null;
3211 Gtk.TreeIter dummy;
3212- if (!playlist.get_iter_first (out dummy)){ //first item
3213- try {
3214- playing = Gtk.IconTheme.get_default ().lookup_icon ("media-playback-start-symbolic",
3215- 16, 0).load_symbolic ({0, 0, 0, 255}, null, null, null);
3216- } catch (Error e) { warning (e.message); }
3217+ if (!playlist.get_iter_first (out dummy)){
3218+ playing = new ThemedIcon ("media-playback-start-symbolic");
3219 } else {
3220 playing = null;
3221 }
3222
3223 playlist.append (out iter);
3224- playlist.set (iter, 0, playing, 1, pix,
3225- 2, Audience.get_title (path.get_basename ()), 3, path.get_path ());
3226+ playlist.set (iter, Columns.PLAYING, playing,
3227+ Columns.TITLE, Audience.get_title (path.get_basename ()),
3228+ Columns.FILENAME, path.get_path ());
3229 }
3230
3231 public void remove_item (File path) {
3232 /*not needed up to now*/
3233 }
3234+
3235 public File? get_first_item () {
3236- Gtk.TreeIter it;
3237- if (playlist.get_iter_from_string (out it, 0.to_string ())){
3238+ Gtk.TreeIter iter;
3239+ if (playlist.get_iter_first (out iter)){
3240 string filename;
3241- playlist.get (it, 3, out filename);
3242+ playlist.get (iter, Columns.FILENAME, out filename);
3243 return File.new_for_commandline_arg (filename);
3244 }
3245 return null;
3246 }
3247
3248+ public List<string> get_all_items () {
3249+ var list = new List<string> ();
3250+ playlist.foreach ((model, path, iter) => {
3251+ Value filename;
3252+ playlist.get_value (iter, Columns.FILENAME, out filename);
3253+ string name = filename.get_string ();
3254+ list.append (name);
3255+ return false;
3256+ });
3257+ return list.copy ();
3258+ }
3259+
3260+ public void save_playlist_config () {
3261+ var list = new List<string> ();
3262+ playlist.foreach ((model, path, iter) => {
3263+ Value filename;
3264+ playlist.get_value (iter, Columns.FILENAME, out filename);
3265+ string name = filename.get_string ();
3266+ list.append (name);
3267+ return false;
3268+ });
3269+
3270+ uint i = 0;
3271+ var videos = new string[list.length ()];
3272+ foreach (var filename in list) {
3273+ videos[i] = filename;
3274+ i++;
3275+ }
3276+
3277+ settings.last_played_videos = videos;
3278+ }
3279+
3280 }
3281
3282-}
3283+}
3284\ No newline at end of file
3285
3286=== added file 'src/Widgets/PlaylistPopover.vala'
3287--- src/Widgets/PlaylistPopover.vala 1970-01-01 00:00:00 +0000
3288+++ src/Widgets/PlaylistPopover.vala 2014-07-06 11:18:29 +0000
3289@@ -0,0 +1,116 @@
3290+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
3291+/*-
3292+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
3293+ *
3294+ * This program is free software: you can redistribute it and/or modify
3295+ * it under the terms of the GNU General Public License as published by
3296+ * the Free Software Foundation, either version 3 of the License, or
3297+ * (at your option) any later version.
3298+
3299+ * This program is distributed in the hope that it will be useful,
3300+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3301+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3302+ * GNU General Public License for more details.
3303+
3304+ * You should have received a copy of the GNU General Public License
3305+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3306+ *
3307+ * Authored by: Corentin Noël <corentin@elementaryos.org>
3308+ */
3309+
3310+public class Audience.Widgets.PlaylistPopover : Gtk.Popover {
3311+ Gtk.ScrolledWindow playlist_scrolled;
3312+ public PlaylistPopover () {
3313+ opacity = GLOBAL_OPACITY;
3314+ var grid = new Gtk.Grid ();
3315+ grid.row_spacing = 6;
3316+ grid.column_spacing = 12;
3317+ grid.margin = 6;
3318+
3319+ var fil = new Gtk.Button.with_label (_("Add from Harddrive…"));
3320+ fil.image = new Gtk.Image.from_icon_name ("document-open", Gtk.IconSize.DIALOG);
3321+ var dvd = new Gtk.Button.with_label (_("Play a DVD…"));
3322+ dvd.image = new Gtk.Image.from_icon_name ("media-cdrom", Gtk.IconSize.DIALOG);
3323+ dvd.no_show_all = true;
3324+ var net = new Gtk.Button.with_label (_("Network File…"));
3325+ net.image = new Gtk.Image.from_icon_name ("internet-web-browser", Gtk.IconSize.DIALOG);
3326+
3327+ playlist_scrolled = new Gtk.ScrolledWindow (null, null);
3328+ var app = ((Audience.App) GLib.Application.get_default ());
3329+ playlist_scrolled.add (app.playlist);
3330+
3331+ fil.clicked.connect ( () => {
3332+ hide ();
3333+ app.run_open_file ();
3334+ });
3335+
3336+ dvd.clicked.connect ( () => {
3337+ hide ();
3338+ app.run_open_dvd ();
3339+ });
3340+
3341+ net.clicked.connect ( () => {
3342+ /*var entry = new Gtk.Entry ();
3343+ entry.secondary_icon_stock = Gtk.Stock.OPEN;
3344+ entry.icon_release.connect ( (pos, e) => {
3345+ open_file (entry.text);
3346+ video_player.playing = true;
3347+ pop.destroy ();
3348+ });
3349+ box.remove (net);
3350+ box.reorder_child (entry, 2);
3351+ entry.show ();*/
3352+ });
3353+
3354+ grid.attach (playlist_scrolled, 0, 0, 2, 1);
3355+ grid.attach (fil, 0, 1, 1, 1);
3356+ grid.attach (dvd, 1, 1, 1, 1);
3357+
3358+ //look for dvd
3359+ var disk_manager = DiskManager.get_default ();
3360+ foreach (var volume in disk_manager.get_volumes ()) {
3361+ dvd.no_show_all = false;
3362+ dvd.show ();
3363+ }
3364+
3365+ disk_manager.volume_found.connect ((vol) => {
3366+ dvd.no_show_all = false;
3367+ dvd.show ();
3368+ });
3369+
3370+ disk_manager.volume_removed.connect ((vol) => {
3371+ if (disk_manager.get_volumes ().length () <= 0) {
3372+ dvd.no_show_all = true;
3373+ dvd.hide ();
3374+ }
3375+ });
3376+
3377+ //grid.add (net);
3378+ add (grid);
3379+ }
3380+
3381+ //Override because the Popover doesn't auto-rejust his size.
3382+ public override void get_preferred_height (out int minimum_height, out int natural_height) {
3383+ base.get_preferred_height (out minimum_height, out natural_height);
3384+ int p_minimum_height;
3385+ int p_natural_height;
3386+ var app = ((Audience.App) GLib.Application.get_default ());
3387+ app.playlist.get_preferred_height (out p_minimum_height, out p_natural_height);
3388+ int temp_minimum_height = minimum_height + p_minimum_height;
3389+ int r_minimum_height;
3390+ int r_natural_height;
3391+ relative_to.get_preferred_height (out r_minimum_height, out r_natural_height);
3392+ if (temp_minimum_height < app.mainwindow.get_window ().get_height () - r_minimum_height*2) {
3393+ minimum_height = temp_minimum_height;
3394+ } else {
3395+ minimum_height = app.mainwindow.get_window ().get_height () - r_minimum_height*2;
3396+ }
3397+
3398+ int temp_natural_height = natural_height + p_natural_height;
3399+ if (temp_natural_height < app.mainwindow.get_window ().get_height () - r_natural_height*2) {
3400+ natural_height = temp_natural_height;
3401+ } else {
3402+ natural_height = minimum_height;
3403+ }
3404+ }
3405+}
3406\ No newline at end of file
3407
3408=== added file 'src/Widgets/PreviewPopover.vala'
3409--- src/Widgets/PreviewPopover.vala 1970-01-01 00:00:00 +0000
3410+++ src/Widgets/PreviewPopover.vala 2014-07-06 11:18:29 +0000
3411@@ -0,0 +1,90 @@
3412+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
3413+/*-
3414+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
3415+ *
3416+ * This program is free software: you can redistribute it and/or modify
3417+ * it under the terms of the GNU General Public License as published by
3418+ * the Free Software Foundation, either version 3 of the License, or
3419+ * (at your option) any later version.
3420+
3421+ * This program is distributed in the hope that it will be useful,
3422+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3423+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3424+ * GNU General Public License for more details.
3425+
3426+ * You should have received a copy of the GNU General Public License
3427+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3428+ *
3429+ * Authored by: Corentin Noël <corentin@elementaryos.org>
3430+ */
3431+
3432+public class Audience.Widgets.PreviewPopover : Gtk.Popover {
3433+ public Clutter.Actor preview_actor;
3434+ dynamic Gst.Element preview_playbin;
3435+ Clutter.Texture video;
3436+ double ratio = 0;
3437+ public PreviewPopover () {
3438+ opacity = GLOBAL_OPACITY;
3439+ can_focus = false;
3440+ sensitive = false;
3441+ modal = false;
3442+
3443+ // connect gstreamer stuff
3444+ preview_playbin = Gst.ElementFactory.make ("playbin", "play");
3445+ preview_playbin.get_bus ().add_signal_watch ();
3446+ preview_playbin.get_bus ().message.connect ((msg) => {
3447+ switch (msg.type) {
3448+ case Gst.MessageType.STATE_CHANGED:
3449+ break;
3450+ case Gst.MessageType.ASYNC_DONE:
3451+ break;
3452+ }
3453+ });
3454+ video = new Clutter.Texture ();
3455+
3456+ dynamic Gst.Element video_sink = Gst.ElementFactory.make ("cluttersink", "source");
3457+ video_sink.texture = video;
3458+ preview_playbin.video_sink = video_sink;
3459+ var clutter = new GtkClutter.Embed ();
3460+ clutter.margin = 6;
3461+ var stage = (Clutter.Stage)clutter.get_stage ();
3462+ stage.background_color = {0, 0, 0, 0};
3463+ stage.use_alpha = true;
3464+
3465+ video.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.WIDTH, 0));
3466+ video.add_constraint (new Clutter.BindConstraint (stage, Clutter.BindCoordinate.HEIGHT, 0));
3467+
3468+ stage.add_child (video);
3469+ add (clutter);
3470+ //show_all ();
3471+ closed.connect (() => {preview_playbin.set_state (Gst.State.PAUSED);});
3472+ }
3473+
3474+ public void set_preview_uri (string uri) {
3475+ preview_playbin.set_state (Gst.State.READY);
3476+ preview_playbin.uri = uri;
3477+ preview_playbin.volume = 0.0;
3478+
3479+ try {
3480+ var info = new Gst.PbUtils.Discoverer (10 * Gst.SECOND).discover_uri (uri);
3481+ var video = info.get_video_streams ();
3482+ if (video.data != null) {
3483+ var video_info = (Gst.PbUtils.DiscovererVideoInfo)video.data;
3484+ uint video_width = video_info.get_width ();
3485+ uint video_height = video_info.get_height ();
3486+ ratio = ((double) video_height) / ((double) video_width);
3487+ set_size_request (200, (int) (ratio*200));
3488+ }
3489+ } catch (Error e) {
3490+ warning (e.message);
3491+ return;
3492+ }
3493+ }
3494+
3495+ public void set_preview_progress (double progress) {
3496+ int64 length;
3497+ preview_playbin.query_duration (Gst.Format.TIME, out length);
3498+ preview_playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, (int64)(double.max (progress, 0.0) * length));
3499+ preview_playbin.set_state (Gst.State.PLAYING);
3500+ }
3501+}
3502\ No newline at end of file
3503
3504=== added file 'src/Widgets/SettingsPopover.vala'
3505--- src/Widgets/SettingsPopover.vala 1970-01-01 00:00:00 +0000
3506+++ src/Widgets/SettingsPopover.vala 2014-07-06 11:18:29 +0000
3507@@ -0,0 +1,166 @@
3508+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
3509+/*-
3510+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
3511+ *
3512+ * This program is free software: you can redistribute it and/or modify
3513+ * it under the terms of the GNU General Public License as published by
3514+ * the Free Software Foundation, either version 3 of the License, or
3515+ * (at your option) any later version.
3516+
3517+ * This program is distributed in the hope that it will be useful,
3518+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3519+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3520+ * GNU General Public License for more details.
3521+
3522+ * You should have received a copy of the GNU General Public License
3523+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3524+ *
3525+ * Authored by: Corentin Noël <corentin@elementaryos.org>
3526+ */
3527+
3528+public class Audience.Widgets.SettingsPopover : Gtk.Popover {
3529+ private Gtk.ComboBoxText languages;
3530+ private Gtk.ComboBoxText subtitles;
3531+ private Gtk.FileChooserButton external_subtitle_file;
3532+
3533+ public SettingsPopover () {
3534+ opacity = GLOBAL_OPACITY;
3535+
3536+ languages = new Gtk.ComboBoxText ();
3537+ subtitles = new Gtk.ComboBoxText ();
3538+ external_subtitle_file = new Gtk.FileChooserButton (_("External Subtitles"), Gtk.FileChooserAction.OPEN);
3539+
3540+ var lang_label = new Gtk.Label (_("Audio:"));
3541+ lang_label.halign = Gtk.Align.END;
3542+
3543+ var sub_label = new Gtk.Label (_("Subtitles:"));
3544+ sub_label.halign = Gtk.Align.END;
3545+
3546+ var sub_ext_label = new Gtk.Label (_("External Subtitles:"));
3547+ sub_ext_label.halign = Gtk.Align.END;
3548+
3549+ var setupgrid = new Gtk.Grid ();
3550+ setupgrid.row_spacing = 6;
3551+ setupgrid.margin = 6;
3552+ setupgrid.attach (lang_label, 0, 1, 1, 1);
3553+ setupgrid.attach (languages, 1, 1, 1, 1);
3554+ setupgrid.attach (sub_label, 0, 2, 1, 1);
3555+ setupgrid.attach (subtitles, 1, 2, 1, 1);
3556+ setupgrid.attach (sub_ext_label, 0, 3, 1, 1);
3557+ setupgrid.attach (external_subtitle_file, 1, 3, 1, 1);
3558+ setupgrid.column_homogeneous = true;
3559+ setupgrid.column_spacing = 12;
3560+
3561+ external_subtitle_file.file_set.connect (() => {
3562+ VideoPlayer.get_default ().set_subtitle_uri (external_subtitle_file.get_uri ());
3563+ });
3564+
3565+ VideoPlayer.get_default ().external_subtitle_changed.connect ((uri) => {
3566+ external_subtitle_file.select_uri (uri);
3567+ });
3568+
3569+ subtitles.changed.connect (() => {
3570+ if (subtitles.active_id == null)
3571+ return;
3572+
3573+ var id = int.parse (subtitles.active_id);
3574+ VideoPlayer.get_default ().current_text = id;
3575+ });
3576+
3577+ languages.changed.connect ( () => { //place it here to not get problems
3578+ if (languages.active_id == null)
3579+ return;
3580+
3581+ VideoPlayer.get_default ().current_audio = int.parse (languages.active_id);
3582+ });
3583+
3584+ add (setupgrid);
3585+ }
3586+
3587+ public void setup_text () {
3588+ subtitles.sensitive = false;
3589+ if (subtitles.model.iter_n_children (null) > 0)
3590+ subtitles.remove_all ();
3591+
3592+ int n_text;
3593+ VideoPlayer.get_default ().playbin.get ("n-text", out n_text);
3594+ for (var i=0; i<n_text; i++) {
3595+ Gst.TagList tags = null;
3596+ Signal.emit_by_name (VideoPlayer.get_default ().playbin, "get-text-tags", i, out tags);
3597+ if (tags == null)
3598+ continue;
3599+
3600+ string desc;
3601+ string readable = null;
3602+ tags.get_string (Gst.Tags.LANGUAGE_CODE, out desc);
3603+ if (desc == null)
3604+ tags.get_string (Gst.Tags.CODEC, out desc);
3605+
3606+ if (desc != null) {
3607+ readable = Gst.Tag.get_language_name (desc);
3608+ var language = Gst.Tag.get_language_name (desc);
3609+ subtitles.append (i.to_string (), language == null ? desc : language);
3610+ subtitles.sensitive = true;
3611+ }
3612+ }
3613+
3614+ subtitles.append ("-1", _("None"));
3615+ subtitles.active_id = VideoPlayer.get_default ().current_text.to_string ();
3616+ }
3617+
3618+ public void setup_audio () {
3619+ languages.sensitive = false;
3620+ if (languages.model.iter_n_children (null) > 0)
3621+ languages.remove_all ();
3622+
3623+ int n_audio;
3624+ VideoPlayer.get_default ().playbin.get ("n-audio", out n_audio);
3625+ for (var i=0; i<n_audio; i++) {
3626+ Gst.TagList tags = null;
3627+ Signal.emit_by_name (VideoPlayer.get_default ().playbin, "get-audio-tags", i, out tags);
3628+ if (tags == null)
3629+ continue;
3630+
3631+ string desc;
3632+ string readable = null;
3633+ tags.get_string (Gst.Tags.LANGUAGE_CODE, out desc);
3634+ if (desc == null)
3635+ tags.get_string (Gst.Tags.CODEC, out desc);
3636+
3637+ if (desc != null) {
3638+ readable = Gst.Tag.get_language_name (desc);
3639+ languages.append (i.to_string (), readable == null ? desc : readable);
3640+ languages.sensitive = true;
3641+ }
3642+ }
3643+
3644+ if (languages.model.iter_n_children (null) <= 0) {
3645+ languages.append ("def", _("Default"));
3646+ languages.active = 0;
3647+ } else {
3648+ languages.active_id = VideoPlayer.get_default ().current_audio.to_string ();
3649+ }
3650+ }
3651+
3652+ public void next_audio () {
3653+ int current = int.parse (languages.active_id);
3654+ if (current < languages.model.iter_n_children (null) - 1) {
3655+ current++;
3656+ } else {
3657+ current = 0;
3658+ }
3659+
3660+ languages.active_id = current.to_string ();
3661+ }
3662+
3663+ public void next_text () {
3664+ int current = int.parse (subtitles.active_id);
3665+ if (current < subtitles.model.iter_n_children (null)) {
3666+ current++;
3667+ } else {
3668+ current = 0;
3669+ }
3670+
3671+ subtitles.active_id = current.to_string ();
3672+ }
3673+}
3674\ No newline at end of file
3675
3676=== removed file 'src/Widgets/TagView.vala'
3677--- src/Widgets/TagView.vala 2014-05-15 07:10:20 +0000
3678+++ src/Widgets/TagView.vala 1970-01-01 00:00:00 +0000
3679@@ -1,253 +0,0 @@
3680-
3681-/*
3682- The panel on the right hand side
3683-*/
3684-
3685-public const string LIGHT_WINDOW_STYLE = """
3686- .content-view-window {
3687- background-image:none;
3688- background-color:@bg_color;
3689-
3690- border-radius: 6px;
3691-
3692- border-width:1px;
3693- border-style: solid;
3694- border-color: alpha (#000, 0.25);
3695- }
3696-""";
3697-
3698-namespace Audience.Widgets
3699-{
3700- public class TagView : GtkClutter.Actor
3701- {
3702- public bool expanded;
3703- public Gtk.Grid taggrid;
3704- public Audience.App app;
3705-
3706- public Gtk.ComboBoxText languages;
3707- public Gtk.ComboBoxText subtitles;
3708- private Gtk.FileChooserButton external_subtitle_file;
3709-
3710- private Granite.Drawing.BufferSurface buffer;
3711- int shadow_blur = 30;
3712- int shadow_x = 0;
3713- int shadow_y = 0;
3714- double shadow_alpha = 0.5;
3715-
3716- bool currently_parsing = false;
3717-
3718- public signal void select_external_subtitle (string uri);
3719-
3720- public TagView (Audience.App app) {
3721- this.app = app;
3722- this.reactive = true;
3723- this.buffer = new Granite.Drawing.BufferSurface (100, 100);
3724-
3725- var notebook = new Granite.Widgets.StaticNotebook (false);
3726-
3727- /*tags*/
3728- var tagview = new Gtk.ScrolledWindow (null, null);
3729- taggrid = new Gtk.Grid ();
3730- taggrid.column_spacing = 10;
3731- taggrid.margin = 12;
3732- tagview.add_with_viewport (taggrid);
3733-
3734- /*setup*/
3735- var setupgrid = new Gtk.Grid ();
3736- this.languages = new Gtk.ComboBoxText ();
3737- this.subtitles = new Gtk.ComboBoxText ();
3738- this.external_subtitle_file = new Gtk.FileChooserButton (_("External Subtitles"), Gtk.FileChooserAction.OPEN);
3739- var lang_lbl = new LLabel.right (_("Audio")+":");
3740- var sub_lbl = new LLabel.right (_("Subtitles")+":");
3741- var sub_ext_lbl = new LLabel.right (_("External Subtitles") + ":");
3742- setupgrid.attach (lang_lbl, 0, 1, 1, 1);
3743- setupgrid.attach (languages, 1, 1, 1, 1);
3744- setupgrid.attach (sub_lbl, 0, 2, 1, 1);
3745- setupgrid.attach (subtitles, 1, 2, 1, 1);
3746- setupgrid.attach (sub_ext_lbl, 0, 3, 1, 1);
3747- setupgrid.attach (this.external_subtitle_file, 1, 3, 1, 1);
3748- setupgrid.column_homogeneous = true;
3749- setupgrid.margin = 12;
3750- setupgrid.column_spacing = 12;
3751-
3752- external_subtitle_file.file_set.connect (() => {
3753- select_external_subtitle (external_subtitle_file.get_uri ());
3754- });
3755- app.video_player.external_subtitle_changed.connect ( (uri) => {
3756- external_subtitle_file.set_uri (uri);
3757- });
3758- this.subtitles.changed.connect ( () => {
3759- if (subtitles.active_id == null || currently_parsing)
3760- return;
3761- var id = int.parse (this.subtitles.active_id);
3762- app.video_player.current_text = id;
3763- });
3764-
3765- languages.changed.connect ( () => { //place it here to not get problems
3766- if (languages.active_id == null || currently_parsing)
3767- return;
3768- app.video_player.current_audio = int.parse (this.languages.active_id);
3769- });
3770-
3771- var playlist_scrolled = new Gtk.ScrolledWindow (null, null);
3772- playlist_scrolled.add (this.app.playlist);
3773-
3774- notebook.append_page (playlist_scrolled, new Gtk.Label (_("Playlist")));
3775- notebook.append_page (setupgrid, new Gtk.Label (_("Options")));
3776-
3777- /*draw the window stylish!*/
3778- var css = new Gtk.CssProvider ();
3779- try {
3780- css.load_from_data (LIGHT_WINDOW_STYLE, -1);
3781- } catch (Error e) { warning (e.message); }
3782-
3783- var draw_ref = new Gtk.Window ();
3784- draw_ref.get_style_context ().add_class ("content-view-window");
3785- draw_ref.get_style_context ().add_provider (css, Gtk.STYLE_PROVIDER_PRIORITY_FALLBACK);
3786-
3787- var w = -1; var h = -1;
3788- this.get_widget ().size_allocate.connect ( () => {
3789- if (w == this.get_widget ().get_allocated_width () &&
3790- h == this.get_widget ().get_allocated_height ())
3791- return;
3792- w = this.get_widget ().get_allocated_width ();
3793- h = this.get_widget ().get_allocated_height ();
3794-
3795- this.buffer = new Granite.Drawing.BufferSurface (w, h);
3796-
3797- this.buffer.context.rectangle (shadow_blur + shadow_x,
3798- shadow_blur + shadow_y, w - shadow_blur*2 + shadow_x, h - shadow_blur*2 + shadow_y);
3799- this.buffer.context.set_source_rgba (0, 0, 0, shadow_alpha);
3800- this.buffer.context.fill ();
3801- this.buffer.exponential_blur (shadow_blur / 2);
3802-
3803- draw_ref.get_style_context ().render_activity (this.buffer.context,
3804- shadow_blur + shadow_x, shadow_blur + shadow_y,
3805- w - shadow_blur*2 + shadow_x, h - shadow_blur*2 + shadow_y);
3806- });
3807- this.get_widget ().draw.connect ( (ctx) => {
3808- ctx.set_operator (Cairo.Operator.SOURCE);
3809- ctx.rectangle (0, 0, this.width, this.height);
3810- ctx.set_source_rgba (0.0, 0.0, 0.0, 0.0);
3811- ctx.fill ();
3812-
3813- ctx.set_source_surface (this.buffer.surface, 0, 0);
3814- ctx.paint ();
3815-
3816- return false;
3817- });
3818-
3819- var no_bg = new Gtk.CssProvider ();
3820- try {
3821- no_bg.load_from_data ("""
3822- * {
3823- background-color: alpha(#fff, 0);
3824- }
3825- .view:selected:focused {
3826- color: @selected_bg_color;
3827- }
3828- """, -1);
3829- } catch (Error e) { warning (e.message); }
3830- setupgrid.get_parent ().get_style_context ().add_provider (no_bg, 20000);
3831- app.playlist.get_style_context ().add_provider (no_bg, 20000);
3832-
3833- playlist_scrolled.margin = 3;
3834- notebook.margin = shadow_blur + 2;
3835- notebook.margin_top += 3;
3836- this.get_widget ().get_style_context ().add_class ("content-view");
3837- ((Gtk.Bin)this.get_widget ()).add (notebook);
3838- this.get_widget ().show_all ();
3839- this.width = 350;
3840- this.opacity = 0;
3841- this.expanded = false;
3842- }
3843-
3844- public override void allocate (Clutter.ActorBox box, Clutter.AllocationFlags flags) {
3845- //have a minimum height in order to not get the negative allocation warnings
3846- if (box.y2 - box.y1 < 100) {
3847- box.y2 = box.y1 + 100;
3848- }
3849- base.allocate (box, flags);
3850- }
3851-
3852- public void expand (){
3853- //make sure it comes from right bounds
3854- x = get_stage ().width + 100;
3855-
3856- var x2 = this.get_stage ().width - this.width + 10;
3857- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, x:x2);
3858- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, opacity:255);
3859- this.expanded = true;
3860- }
3861-
3862- public void collapse (){
3863- var x2 = this.get_stage ().width;
3864- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, x:x2);
3865- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, opacity:0);
3866- this.expanded = false;
3867- }
3868-
3869- public void setup_text_setup () { setup_setup ("text"); }
3870- public void setup_audio_setup () { setup_setup ("audio"); }
3871- /*target is either "text" or "audio"*/
3872- public void setup_setup (string target) {
3873- currently_parsing = true;
3874-
3875- if (target == "audio" && languages.model.iter_n_children (null) > 0)
3876- languages.remove_all ();
3877- else if (target == "text" && subtitles.model.iter_n_children (null) > 0)
3878- subtitles.remove_all ();
3879-
3880- Value num = 0;
3881- app.video_player.playbin.get_property ("n-"+target, ref num);
3882-
3883- int used = 0;
3884- for (var i=0;i<num.get_int ();i++) {
3885- Gst.TagList tags = null;
3886- Signal.emit_by_name (app.video_player.playbin, "get-"+target+"-tags", i, out tags);
3887- if (tags == null)
3888- continue;
3889-
3890- string desc;
3891- string readable = null;
3892- tags.get_string (Gst.Tags.LANGUAGE_CODE, out desc);
3893- if (desc == null)
3894- tags.get_string (Gst.Tags.CODEC, out desc);
3895-
3896- if (desc != null)
3897- readable = Gst.Tag.get_language_name (desc);
3898-
3899- if (target == "audio" && desc != null) {
3900- this.languages.append (i.to_string (), readable == null ? desc : readable);
3901- used ++;
3902- } else if (desc != null) {
3903- var language = Gst.Tag.get_language_name (desc);
3904- this.subtitles.append (i.to_string (), language == null ? desc : language);
3905- used ++;
3906- }
3907- }
3908-
3909- if (target == "audio") {
3910-
3911- if (used == 0) {
3912- languages.append ("def", _("Default"));
3913- languages.active = 0;
3914- languages.sensitive = false;
3915- } else {
3916- languages.sensitive = true;
3917- languages.active_id = app.video_player.current_audio.to_string ();
3918- }
3919- } else {
3920- if (used == 0)
3921- subtitles.sensitive = false;
3922- else
3923- subtitles.sensitive = true;
3924-
3925- subtitles.append ("-1", _("None"));
3926- subtitles.active_id = app.video_player.current_text.to_string ();
3927- }
3928-
3929- currently_parsing = false;
3930- }
3931- }
3932-}
3933
3934=== added file 'src/Widgets/TimeWidget.vala'
3935--- src/Widgets/TimeWidget.vala 1970-01-01 00:00:00 +0000
3936+++ src/Widgets/TimeWidget.vala 2014-07-06 11:18:29 +0000
3937@@ -0,0 +1,127 @@
3938+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
3939+/*-
3940+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
3941+ *
3942+ * This program is free software: you can redistribute it and/or modify
3943+ * it under the terms of the GNU General Public License as published by
3944+ * the Free Software Foundation, either version 3 of the License, or
3945+ * (at your option) any later version.
3946+
3947+ * This program is distributed in the hope that it will be useful,
3948+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3949+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3950+ * GNU General Public License for more details.
3951+
3952+ * You should have received a copy of the GNU General Public License
3953+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3954+ *
3955+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
3956+ * Corentin Noël <corentin@elementaryos.org>
3957+ */
3958+
3959+public class Audience.Widgets.TimeWidget : Gtk.Grid {
3960+ public signal void slider_motion_event (Gdk.EventMotion event);
3961+
3962+ public Gtk.Label progression_label;
3963+ public Gtk.Label time_label;
3964+ public Gtk.Scale scale;
3965+ public signal void seeked (double val);
3966+ private Audience.Widgets.PreviewPopover preview_popover;
3967+ private bool is_seeking = false;
3968+ private bool released = true;
3969+ private uint timeout_id = 0;
3970+ private int original = 0;
3971+
3972+ public TimeWidget () {
3973+ orientation = Gtk.Orientation.HORIZONTAL;
3974+ column_spacing = 12;
3975+ halign = Gtk.Align.CENTER;
3976+ progression_label = new Gtk.Label ("");
3977+ time_label = new Gtk.Label ("");
3978+
3979+ scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 1, 0.1);
3980+ scale.expand = true;
3981+ scale.draw_value = false;
3982+ scale.can_focus = false;
3983+ scale.events |= Gdk.EventMask.POINTER_MOTION_MASK;
3984+ scale.events |= Gdk.EventMask.LEAVE_NOTIFY_MASK;
3985+ scale.events |= Gdk.EventMask.ENTER_NOTIFY_MASK;
3986+ scale.button_press_event.connect ((event) => {
3987+ is_seeking = true;
3988+ released = false;
3989+
3990+ if (timeout_id != 0)
3991+ Source.remove (timeout_id);
3992+
3993+ timeout_id = Timeout.add (300, () => {
3994+ if (released == false)
3995+ return true;
3996+ seeked (scale.get_value ());
3997+ is_seeking = false;
3998+
3999+ timeout_id = 0;
4000+
4001+ return false;
4002+ });
4003+
4004+ return false;
4005+ });
4006+
4007+ scale.enter_notify_event.connect ((event) => {
4008+ preview_popover.show_all ();
4009+ return false;
4010+ });
4011+
4012+ scale.leave_notify_event.connect ((event) => {
4013+ preview_popover.hide ();
4014+ return false;
4015+ });
4016+
4017+ // XXX: Store the original size because the popover doesn't update his x=0 position when resizing.
4018+ scale.motion_notify_event.connect ((event) => {
4019+ if (original == 0)
4020+ original = event.window.get_width ();
4021+
4022+ var pointing = preview_popover.pointing_to;
4023+ var distance = original - event.window.get_width ();
4024+ pointing.x = (int)(event.x) - event.window.get_width ()/2 - distance/2;
4025+ preview_popover.set_pointing_to ((Gdk.Rectangle)pointing);
4026+ preview_popover.set_preview_progress (((double)event.x)/((double)event.window.get_width ()));
4027+
4028+ slider_motion_event (event);
4029+
4030+ return false;
4031+ });
4032+
4033+ scale.button_release_event.connect ((event) => {released = true; return false;});
4034+ preview_popover = new Audience.Widgets.PreviewPopover ();
4035+ preview_popover.relative_to = this;
4036+
4037+ add (progression_label);
4038+ add (scale);
4039+ add (time_label);
4040+ }
4041+
4042+ public void set_preview_uri (string uri) {
4043+ preview_popover.set_preview_uri (uri);
4044+ }
4045+
4046+ public override void get_preferred_width (out int minimum_width, out int natural_width) {
4047+ base.get_preferred_width (out minimum_width, out natural_width);
4048+
4049+ if (parent.get_window () == null)
4050+ return;
4051+ var width = parent.get_window ().get_width ();
4052+ if (width > 0 && width >= minimum_width) {
4053+ natural_width = width;
4054+ }
4055+ }
4056+
4057+ public void set_progression_time (double current_time, double total_time) {
4058+ if (is_seeking == true)
4059+ return;
4060+ scale.set_value (current_time/total_time);
4061+ progression_label.label = seconds_to_time ((int)(current_time / 1000000000));
4062+ time_label.label = seconds_to_time ((int)((total_time - current_time) / 1000000000));
4063+ }
4064+}
4065\ No newline at end of file
4066
4067=== removed file 'src/Widgets/TopPanel.vala'
4068--- src/Widgets/TopPanel.vala 2013-05-19 17:10:26 +0000
4069+++ src/Widgets/TopPanel.vala 1970-01-01 00:00:00 +0000
4070@@ -1,87 +0,0 @@
4071-
4072-namespace Audience.Widgets{
4073-
4074- /*a bar only shown for fullscreen including volume and unfullscreen*/
4075- public class TopPanel : Clutter.Box {
4076-
4077- public Button exit;
4078- public GtkClutter.Actor volume;
4079- public Gtk.VolumeButton vol;
4080-
4081- bool _hidden;
4082- public bool hidden{
4083- get { return _hidden; }
4084- set {
4085- if (_hidden && !value){
4086- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 400, y : 0.0f);
4087- }else if (!_hidden && value){
4088- this.animate (Clutter.AnimationMode.EASE_OUT_QUAD, 1000, y : -this.height);
4089- }
4090- this._hidden = value;
4091- }
4092- }
4093-
4094- public signal void unfullscreen ();
4095-
4096- public TopPanel () {
4097- layout_manager = new Clutter.BoxLayout ();
4098-
4099- this.exit = new Button ("view-restore-symbolic", Gtk.Stock.LEAVE_FULLSCREEN);
4100- this.volume = new GtkClutter.Actor ();
4101- var buf = new Clutter.Rectangle.with_color ({0,0,0,0});
4102- this.vol = new Gtk.VolumeButton ();
4103- this.vol.use_symbolic = true;
4104- this._hidden = true;
4105-
4106- exit.reactive = true;
4107- exit.y = 2;
4108- exit.button_release_event.connect ((e) => {
4109- unfullscreen ();
4110- return true;
4111- });
4112-
4113- var css = new Gtk.CssProvider ();
4114- try {
4115- css.load_from_data ("""
4116- * {
4117- color: #fff;
4118- transition: 2ms linear;
4119- }
4120- *:hover {
4121- color: #aaa;
4122- transition: 2ms linear;
4123- }
4124- .button {
4125- background-image: none;
4126- background-color: alpha (#000, 0);
4127- border-color: alpha (#000, 0);
4128- border-image: none;
4129- -unico-border-gradient: none;
4130- -unico-inner-stroke-width: 0px;
4131- -unico-outer-stroke-width: 0px;
4132- }
4133- """, -1);
4134- }catch (Error e) { warning (e.message); }
4135- this.vol.get_child ().get_style_context ().add_provider (css, 20000);
4136- this.vol.get_style_context ().add_provider (css, 20000);
4137-
4138- ((Gtk.Container)this.volume.get_widget ()).add (this.vol);
4139- this.volume.get_widget ().draw.connect ( (ctx) => {
4140- ctx.rectangle (0, 0, this.volume.width, this.volume.height);
4141- ctx.set_operator (Cairo.Operator.SOURCE);
4142- ctx.set_source_rgba (0, 0, 0, 0);
4143- ctx.fill ();
4144- return false;
4145- });
4146-
4147- buf.width = 10;
4148-
4149- //this.add_child (this.volume); removed until we get it to control global volume
4150- this.add_child (buf);
4151- this.add_child (this.exit);
4152-
4153- y = -height;
4154- }
4155- }
4156-}
4157-
4158
4159=== modified file 'src/Widgets/VideoPlayer.vala'
4160--- src/Widgets/VideoPlayer.vala 2014-05-15 07:10:20 +0000
4161+++ src/Widgets/VideoPlayer.vala 2014-07-06 11:18:29 +0000
4162@@ -1,3 +1,24 @@
4163+// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*-
4164+/*-
4165+ * Copyright (c) 2013-2014 Audience Developers (http://launchpad.net/pantheon-chat)
4166+ *
4167+ * This program is free software: you can redistribute it and/or modify
4168+ * it under the terms of the GNU General Public License as published by
4169+ * the Free Software Foundation, either version 3 of the License, or
4170+ * (at your option) any later version.
4171+
4172+ * This program is distributed in the hope that it will be useful,
4173+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4174+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4175+ * GNU General Public License for more details.
4176+
4177+ * You should have received a copy of the GNU General Public License
4178+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4179+ *
4180+ * Authored by: Tom Beckmann <tomjonabc@gmail.com>
4181+ * Corentin Noël <corentin@elementaryos.org>
4182+ */
4183+
4184 using Clutter;
4185
4186 enum PlayFlags {
4187@@ -14,14 +35,17 @@
4188 SOFT_COLORBALANCE = (1 << 10)
4189 }
4190
4191-namespace Audience.Widgets
4192-{
4193- public class VideoPlayer : Actor
4194- {
4195-
4196+namespace Audience.Widgets {
4197+ public class VideoPlayer : Actor {
4198+ private static VideoPlayer? video_player = null;
4199+ public static VideoPlayer get_default () {
4200+ if (video_player == null)
4201+ video_player = new VideoPlayer ();
4202+ return video_player;
4203+ }
4204+
4205 public bool at_end;
4206-
4207- bool paused;
4208+
4209 bool _playing;
4210 public bool playing {
4211 get {
4212@@ -30,47 +54,31 @@
4213 set {
4214 if (value == playing)
4215 return;
4216-
4217- controls.show_play_button (!value);
4218-
4219- playbin.set_state (value ? Gst.State.PLAYING : Gst.State.PAUSED);
4220
4221 set_screensaver (!value);
4222 set_screenlock (!value);
4223-
4224- if (!value) {
4225- paused = true;
4226- lock_hide ();
4227- }
4228- if (value && paused) {
4229- paused = false;
4230- unlock_hide ();
4231- }
4232-
4233+ playbin.set_state (value ? Gst.State.PLAYING : Gst.State.PAUSED);
4234 _playing = value;
4235 }
4236 }
4237-
4238+
4239 public double progress {
4240 get {
4241 int64 length, prog;
4242-
4243 playbin.query_duration (Gst.Format.TIME, out length);
4244 playbin.query_position (Gst.Format.TIME, out prog);
4245-
4246 if (length == 0)
4247 return 0;
4248-
4249+
4250 return prog / (double)length;
4251 }
4252 set {
4253 int64 length;
4254 playbin.query_duration (Gst.Format.TIME, out length);
4255- playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE,
4256- (int64)(double.max (value, 0.0) * length));
4257+ playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, (int64)(double.max (value, 0.0) * length));
4258 }
4259 }
4260-
4261+
4262 public double volume {
4263 get {
4264 return playbin.volume;
4265@@ -79,7 +87,7 @@
4266 playbin.volume = value;
4267 }
4268 }
4269-
4270+
4271 public string uri {
4272 owned get {
4273 return playbin.current_uri;
4274@@ -101,38 +109,20 @@
4275 warning (e.message);
4276 return;
4277 }
4278-
4279+
4280 intial_relayout = true;
4281-
4282 playing = false;
4283 playbin.set_state (Gst.State.READY);
4284 playbin.suburi = null;
4285 subtitle_uri = null;
4286 playbin.uri = value;
4287 volume = 1.0;
4288- controls.slider.set_preview_uri (value);
4289 at_end = false;
4290-
4291+
4292 relayout ();
4293 playing = true;
4294 }
4295 }
4296-
4297- bool _controls_hidden;
4298- public bool controls_hidden
4299- {
4300- get { return _controls_hidden; }
4301- set {
4302- if (_controls_hidden && !value) {
4303- float y2 = get_stage ().height - controls.height;
4304- controls.animate (Clutter.AnimationMode.EASE_OUT_CUBIC, 300, y:y2);
4305- } else if (!_controls_hidden && value){
4306- float y2 = get_stage ().height;
4307- controls.animate (Clutter.AnimationMode.EASE_IN_QUAD, 600, y:y2);
4308- }
4309- _controls_hidden = value;
4310- }
4311- }
4312
4313 public int current_audio {
4314 get {
4315@@ -167,161 +157,73 @@
4316 }
4317 }
4318 }
4319-
4320+
4321 public dynamic Gst.Element playbin;
4322 Clutter.Texture video;
4323- Controls controls;
4324- TopPanel panel;
4325
4326 uint video_width;
4327 uint video_height;
4328-
4329- // we will only hide if hide lock is 0
4330- public int hide_lock = 0;
4331-
4332- uint hiding_timer;
4333-
4334+
4335 public GnomeSessionManager session_manager;
4336 uint32 inhibit_cookie;
4337-
4338- public bool fullscreened { get; set; }
4339-
4340+
4341 public signal void ended ();
4342 public signal void toggle_side_pane (bool show);
4343 public signal void text_tags_changed ();
4344 public signal void audio_tags_changed ();
4345- public signal void show_open_context ();
4346- public signal void exit_fullscreen ();
4347 public signal void error ();
4348 public signal void plugin_install_done ();
4349 public signal void configure_window (uint video_w, uint video_h);
4350+ public signal void progression_changed (double current_time, double total_time);
4351 public signal void external_subtitle_changed (string? uri);
4352
4353- public VideoPlayer ()
4354- {
4355- reactive = true;
4356-
4357- controls = new Controls ();
4358- controls.add_constraint (new BindConstraint (this, BindCoordinate.WIDTH, 0));
4359- controls.slider.preview.add_constraint (new BindConstraint (controls, Clutter.BindCoordinate.Y, -105.0f));
4360-
4361- panel = new TopPanel ();
4362-
4363+ private VideoPlayer () {
4364 video = new Clutter.Texture ();
4365- video.reactive = true;
4366-
4367+
4368+ dynamic Gst.Element video_sink = Gst.ElementFactory.make ("cluttersink", "source");
4369+ video_sink.texture = video;
4370+
4371 playbin = Gst.ElementFactory.make ("playbin", "playbin");
4372- var video_sink = Audience.get_clutter_sink ();
4373- video_sink.texture = video;
4374-
4375 playbin.video_sink = video_sink;
4376-
4377+
4378 add_child (video);
4379- add_child (controls);
4380- add_child (panel);
4381- add_child (controls.slider.preview);
4382-
4383- controls.slider.seeked.connect ( (v) => {
4384- debug ("Seeked to %f", v);
4385- progress = v;
4386- });
4387 Timeout.add (100, () => {
4388 int64 length, prog;
4389 playbin.query_position (Gst.Format.TIME, out prog);
4390 playbin.query_duration (Gst.Format.TIME, out length);
4391-
4392 if (length == 0)
4393 return true;
4394-
4395- controls.slider.progress = prog / (double)length;
4396-
4397- controls.current.text = seconds_to_time ((int)(prog / 1000000000));
4398- controls.remaining.text = "-" + seconds_to_time ((int)(length / 1000000000) - (int)(prog / 1000000000));
4399-
4400+
4401+ progression_changed ((double)prog, (double)length);
4402 return true;
4403 });
4404+
4405 playbin.about_to_finish.connect (() => {
4406 at_end = true;
4407 ended ();
4408 });
4409
4410- notify["fullscreened"].connect (() => {
4411- if (hide_lock > 0)
4412- panel.hidden = !fullscreened;
4413- });
4414- panel.unfullscreen.connect (() => {
4415- exit_fullscreen ();
4416- });
4417-
4418- bool last_state = false;
4419- controls.notify["hovered"].connect (() => {
4420- if (controls.hovered == last_state)
4421- return;
4422-
4423- last_state = controls.hovered;
4424-
4425- if (controls.hovered)
4426- lock_hide ();
4427- else
4428- unlock_hide ();
4429- });
4430-
4431- controls.open.clicked.connect (() => {
4432- show_open_context ();
4433- });
4434- controls.play.clicked.connect (() => playing = !playing );
4435- controls.view.clicked.connect (() => {
4436- if (!controls.showing_view) {
4437- toggle_side_pane (true);
4438- controls.view.set_icon ("pane-hide-symbolic", Gtk.Stock.GO_FORWARD, "go-next-symbolic");
4439- controls.showing_view = true;
4440-
4441- lock_hide ();
4442- } else {
4443- toggle_side_pane (false);
4444- controls.view.set_icon ("pane-show-symbolic", Gtk.Stock.GO_BACK, "go-previous-symbolic");
4445- controls.showing_view = false;
4446-
4447- unlock_hide ();
4448- }
4449- });
4450-
4451- panel.vol.value_changed.connect ( (value) => {
4452- volume = value;
4453- });
4454- panel.vol.value = 1.0;
4455-
4456 playbin.text_tags_changed.connect ((el) => {
4457 var structure = new Gst.Structure.empty ("tags-changed");
4458 structure.set_value ("type", "text");
4459 el.post_message (new Gst.Message.application (el, (owned) structure));
4460 });
4461+
4462 playbin.audio_tags_changed.connect ((el) => {
4463 var structure = new Gst.Structure.empty ("tags-changed");
4464 structure.set_value ("type", "audio");
4465 el.post_message (new Gst.Message.application (el, (owned) structure));
4466 });
4467-
4468+
4469 playbin.get_bus ().add_signal_watch ();
4470 playbin.get_bus ().message.connect (watch);
4471 }
4472
4473- public void lock_hide () {
4474- if (hide_lock == 0)
4475- toggle_controls (true);
4476- hide_lock++;
4477- }
4478- public void unlock_hide () {
4479- hide_lock--;
4480-
4481- if (hide_lock < 1)
4482- toggle_controls (false);
4483- }
4484-
4485 void watch () {
4486 var msg = playbin.get_bus ().peek ();
4487 if (msg == null)
4488 return;
4489+
4490 switch (msg.type) {
4491 case Gst.MessageType.APPLICATION:
4492 if (msg.get_structure ().get_name () == "tags-changed") {
4493@@ -374,23 +276,7 @@
4494 }
4495 }
4496
4497- public override bool motion_event (Clutter.MotionEvent event)
4498- {
4499- if (!controls.slider.mouse_grabbed)
4500- get_stage ().cursor_visible = true;
4501-
4502- Gst.State state;
4503- playbin.get_state (out state, null, 0);
4504- if (state == Gst.State.PLAYING) {
4505- if (hiding_timer < 1)
4506- lock_hide ();
4507- set_timeout ();
4508- }
4509- return true;
4510- }
4511-
4512- public void set_subtitle_uri (string? uri)
4513- {
4514+ public void set_subtitle_uri (string? uri) {
4515 subtitle_uri = uri;
4516 if (!check_text_layer (subtitle_uri != null)) {
4517 apply_subtitles ();
4518@@ -400,8 +286,7 @@
4519
4520 // checks whether text layer has to be enabled
4521 // returns if apply_subtitles has been called
4522- bool check_text_layer (bool enable)
4523- {
4524+ bool check_text_layer (bool enable) {
4525 int flags;
4526 playbin.get ("flags", out flags);
4527
4528@@ -419,8 +304,7 @@
4529 }
4530
4531 // ported from totem bvw widget set_subtitle_uri
4532- void apply_subtitles ()
4533- {
4534+ void apply_subtitles () {
4535 int64 time;
4536 playbin.query_position (Gst.Format.TIME, out time);
4537
4538@@ -434,7 +318,6 @@
4539 }
4540
4541 playbin.suburi = subtitle_uri;
4542-
4543 if (current > Gst.State.READY) {
4544 playbin.set_state (current);
4545 playbin.get_state (null, null, Gst.CLOCK_TIME_NONE);
4546@@ -451,10 +334,9 @@
4547 playbin.get_state (null, null, Gst.CLOCK_TIME_NONE);
4548 }
4549 }
4550-
4551+
4552 bool intial_relayout = false;
4553- public bool relayout ()
4554- {
4555+ public bool relayout () {
4556 if (video_width < 1 || video_height < 1 || uri == null)
4557 return false;
4558
4559@@ -464,136 +346,100 @@
4560 }
4561
4562 var stage = get_stage ();
4563-
4564 var aspect = stage.width / video_width < stage.height / video_height ?
4565 stage.width / video_width : stage.height / video_height;
4566 video.width = video_width * aspect;
4567 video.height = video_height * aspect;
4568 video.x = (stage.width - video.width) / 2;
4569 video.y = (stage.height - video.height) / 2;
4570-
4571- if (controls.get_animation () != null)
4572- controls.detach_animation ();
4573- controls.y = controls_hidden ? stage.height : stage.height - controls.height;
4574-
4575- (controls.content as Clutter.Canvas).set_size ((int)controls.width, (int)controls.height);
4576- controls.content.invalidate ();
4577-
4578- panel.x = get_stage ().width - panel.width - 10;
4579- controls.slider.preview.width = (float) video_width / video_height * controls.slider.preview.height;
4580
4581 return true;
4582 }
4583-
4584- void show_error (string? message=null)
4585- {
4586- var dlg = new Gtk.Dialog.with_buttons (_("Error"), null, Gtk.DialogFlags.MODAL, Gtk.Stock.OK, Gtk.ResponseType.OK);
4587+
4588+ void show_error (string? message=null) {
4589+ var dlg = new Gtk.Dialog.with_buttons (_("Error"), null, Gtk.DialogFlags.MODAL, _("_OK"), Gtk.ResponseType.OK);
4590 var grid = new Gtk.Grid ();
4591- var err = new Gtk.Image.from_stock (Gtk.Stock.DIALOG_ERROR, Gtk.IconSize.DIALOG);
4592-
4593+ var err = new Gtk.Image.from_icon_name ("dialog-error", Gtk.IconSize.DIALOG);
4594 err.margin_right = 12;
4595+
4596+ var err_label = new Gtk.Label ("");
4597+ err_label.set_markup ("<b>%s</b>".printf (_("Oops! Audience can't play this file!")));
4598+
4599 grid.margin = 12;
4600 grid.attach (err, 0, 0, 1, 1);
4601- grid.attach (new Widgets.LLabel.markup ("<b>"+
4602- _("Oops! Audience can't play this file!")+"</b>"), 1, 0, 1, 1);
4603+ grid.attach (err_label, 1, 0, 1, 1);
4604 if (message != null)
4605- grid.attach (new Widgets.LLabel (message), 1, 1, 1, 2);
4606+ grid.attach (new Gtk.Label (message), 1, 1, 1, 2);
4607
4608 error ();
4609-
4610 ((Gtk.Box)dlg.get_content_area ()).add (grid);
4611 dlg.show_all ();
4612 dlg.run ();
4613 dlg.destroy ();
4614 }
4615-
4616- void handle_missing_plugin (Gst.Message msg)
4617- {
4618+
4619+ void handle_missing_plugin (Gst.Message msg) {
4620 var detail = Gst.PbUtils.missing_plugin_message_get_description (msg);
4621- var dlg = new Gtk.Dialog.with_buttons ("Missing plugin", null,
4622- Gtk.DialogFlags.MODAL);
4623+ var dlg = new Gtk.Dialog.with_buttons ("Missing plugin", null, Gtk.DialogFlags.MODAL);
4624 var grid = new Gtk.Grid ();
4625- var err = new Gtk.Image.from_stock (Gtk.Stock.DIALOG_ERROR,
4626- Gtk.IconSize.DIALOG);
4627- var phrase = new Widgets.LLabel (_("Some media files need extra software to be played. Audience can install this software automatically."));
4628-
4629+ var err = new Gtk.Image.from_icon_name ("dialog-error", Gtk.IconSize.DIALOG);
4630+ var phrase = new Gtk.Label (_("Some media files need extra software to be played. Audience can install this software automatically."));
4631+
4632 err.margin_right = 12;
4633+
4634+ var err_label = new Gtk.Label ("");
4635+ err_label.set_markup ("<b>%s</b>".printf (_("Audience needs %s to play this file.").printf (detail)));
4636+
4637 grid.margin = 12;
4638 grid.attach (err, 0, 0, 1, 1);
4639- grid.attach (new Widgets.LLabel.markup ("<b>"+
4640- _("Audience needs %s to play this file.").printf (detail)+"</b>"), 1, 0, 1, 1);
4641+ grid.attach (err_label, 1, 0, 1, 1);
4642 grid.attach (phrase, 1, 1, 1, 2);
4643
4644 dlg.add_button (_("Don't install"), 1);
4645 dlg.add_button (_("Install")+" "+detail, 0);
4646-
4647+
4648 (dlg.get_content_area () as Gtk.Container).add (grid);
4649-
4650 dlg.show_all ();
4651 if (dlg.run () == 0) {
4652 var installer = Gst.PbUtils.missing_plugin_message_get_installer_detail (msg);
4653 var context = new Gst.PbUtils.InstallPluginsContext ();
4654- Gst.PbUtils.install_plugins_async ({installer}, context,
4655- () => { //finished
4656- debug ("Finished plugin install\n");
4657+ Gst.PbUtils.install_plugins_async ({installer}, context, () => { //finished
4658+ debug ("Finished plugin install");
4659 Gst.update_registry ();
4660 plugin_install_done ();
4661 playing = true;
4662 });
4663 }
4664+
4665 dlg.destroy ();
4666 }
4667-
4668- void set_timeout ()
4669- {
4670- if (hiding_timer != 0)
4671- Source.remove (hiding_timer);
4672-
4673- hiding_timer = GLib.Timeout.add (2000, () => {
4674- unlock_hide ();
4675- hiding_timer = 0;
4676- return false;
4677- });
4678- }
4679-
4680- void toggle_controls (bool show)
4681- {
4682- if (show) {
4683- controls_hidden = false;
4684- get_stage ().cursor_visible = true;
4685- if (fullscreened)
4686- panel.hidden = false;
4687- } else {
4688- get_stage ().cursor_visible = false;
4689- controls_hidden = true;
4690- panel.hidden = true;
4691- }
4692- }
4693-
4694+
4695+ //TODO: Remove X Dependency!
4696 //store the default values for setting back
4697 X.Display dpy; int timeout = -1; int interval; int prefer_blanking; int allow_exposures;
4698- void set_screensaver (bool enable)
4699- {
4700+ void set_screensaver (bool enable) {
4701 if (dpy == null)
4702 dpy = new X.Display ();
4703-
4704+
4705 if (timeout == -1)
4706 dpy.get_screensaver (out timeout, out interval, out prefer_blanking, out allow_exposures);
4707+
4708 dpy.set_screensaver (enable ? timeout : 0, interval, prefer_blanking, allow_exposures);
4709 }
4710-
4711+
4712 //prevent screenlocking in Gnome 3 using org.gnome.SessionManager
4713- void set_screenlock (bool enable)
4714- {
4715- try{
4716+ void set_screenlock (bool enable) {
4717+ try {
4718 session_manager = Bus.get_proxy_sync (BusType.SESSION,
4719 "org.gnome.SessionManager", "/org/gnome/SessionManager");
4720 if (enable) {
4721 session_manager.Uninhibit (inhibit_cookie);
4722- }else{
4723+ } else {
4724 inhibit_cookie = session_manager.Inhibit ("audience", 0, "Playing Video using Audience", 12);
4725 }
4726- } catch (Error e) { warning (e.message); }
4727+ } catch (Error e) {
4728+ warning (e.message);
4729+ }
4730 }
4731 }
4732-}
4733+}
4734\ No newline at end of file

Subscribers

People subscribed via source and target branches