From 09f71131fbadc2e956eda0df250407a63df93b07 Mon Sep 17 00:00:00 2001 From: Mathieu Duponchelle Date: Sat, 5 Nov 2016 09:18:49 +0100 Subject: [PATCH] Split out documentation into subfolders. https://bugzilla.gnome.org/show_bug.cgi?id=773976 --- .gitmodules | 2 +- Makefile | 12 +- TODO.md | 4 +- attachments/filter-element-multi.png | Bin 4383 -> 0 bytes attachments/filter-element.png | Bin 2718 -> 0 bytes attachments/simple-player.png | Bin 53147 -> 0 bytes attachments/sink-element.png | Bin 3369 -> 0 bytes attachments/src-element.png | Bin 3611 -> 0 bytes .../android-tutorial-1/AndroidManifest.xml | 2 +- .../tutorials}/android-tutorial-1/jni/Android.mk | 0 .../android-tutorial-1}/jni/Application.mk | 0 .../tutorials}/android-tutorial-1/jni/tutorial-1.c | 0 .../res/drawable-hdpi/gstreamer_logo_1.png | Bin .../res/drawable-ldpi/gstreamer_logo_1.png | Bin .../res/drawable-mdpi/gstreamer_logo_1.png | Bin .../res/drawable-xhdpi/gstreamer_logo_1.png | Bin .../res/drawable-xxhdpi/gstreamer_logo_1.png | Bin .../res/drawable-xxxhdpi/gstreamer_logo_1.png | Bin .../android-tutorial-1/res/layout/main.xml | 26 +- .../android-tutorial-1/res/values/strings.xml | 0 .../gstreamer/tutorials/tutorial_1/Tutorial1.java | 2 +- .../android-tutorial-2/AndroidManifest.xml | 2 +- .../tutorials}/android-tutorial-2/jni/Android.mk | 0 .../android-tutorial-2}/jni/Application.mk | 0 .../tutorials}/android-tutorial-2/jni/tutorial-2.c | 0 .../res/drawable-hdpi/gstreamer_logo_2.png | Bin .../res/drawable-ldpi/gstreamer_logo_2.png | Bin .../res/drawable-mdpi/gstreamer_logo_2.png | Bin .../res/drawable-xhdpi/gstreamer_logo_2.png | Bin .../res/drawable-xxhdpi/gstreamer_logo_2.png | Bin .../res/drawable-xxxhdpi/gstreamer_logo_2.png | Bin .../android-tutorial-2/res/layout/main.xml | 74 +- .../android-tutorial-2/res/values/strings.xml | 0 .../gstreamer/tutorials/tutorial_2/Tutorial2.java | 2 +- .../android-tutorial-3/AndroidManifest.xml | 2 +- .../tutorials}/android-tutorial-3/jni/Android.mk | 0 .../android-tutorial-3}/jni/Application.mk | 0 .../tutorials}/android-tutorial-3/jni/tutorial-3.c | 0 .../res/drawable-hdpi/gstreamer_logo_3.png | Bin .../res/drawable-ldpi/gstreamer_logo_3.png | Bin .../res/drawable-mdpi/gstreamer_logo_3.png | Bin .../res/drawable-xhdpi/gstreamer_logo_3.png | Bin .../res/drawable-xxhdpi/gstreamer_logo_3.png | Bin .../res/drawable-xxxhdpi/gstreamer_logo_3.png | Bin .../android-tutorial-3/res/layout/main.xml | 90 +- .../android-tutorial-3/res/values/strings.xml | 0 .../gstreamer/tutorial_3/GStreamerSurfaceView.java | 0 .../gstreamer/tutorial_3/Tutorial3.java | 2 +- .../android-tutorial-4/AndroidManifest.xml | 2 +- .../tutorials}/android-tutorial-4/jni/Android.mk | 0 .../android-tutorial-4}/jni/Application.mk | 0 .../tutorials}/android-tutorial-4/jni/tutorial-4.c | 1124 ++++++++++---------- .../res/drawable-hdpi/gstreamer_logo_4.png | Bin .../res/drawable-ldpi/gstreamer_logo_4.png | Bin .../res/drawable-mdpi/gstreamer_logo_4.png | Bin .../res/drawable-xhdpi/gstreamer_logo_4.png | Bin .../res/drawable-xxhdpi/gstreamer_logo_4.png | Bin .../res/drawable-xxxhdpi/gstreamer_logo_4.png | Bin .../android-tutorial-4/res/layout/main.xml | 136 +-- .../android-tutorial-4/res/values/strings.xml | 0 .../tutorial_4/GStreamerSurfaceView.java | 0 .../gst_sdk_tutorials/tutorial_4/Tutorial4.java | 2 +- .../android-tutorial-5/AndroidManifest.xml | 0 .../tutorials}/android-tutorial-5/jni/Android.mk | 0 .../android-tutorial-5/jni/Application.mk | 1 + .../tutorials}/android-tutorial-5/jni/tutorial-5.c | 0 .../android-tutorial-5/res/drawable-ldpi/file.png | Bin .../res/drawable-ldpi/folder.png | Bin .../res/drawable-ldpi/gstreamer_logo_5.png | Bin .../res/drawable-mdpi/gstreamer_logo_5.png | Bin .../res/drawable-xhdpi/gstreamer_logo_5.png | Bin .../res/drawable-xxhdpi/gstreamer_logo_5.png | Bin .../res/drawable-xxxhdpi/gstreamer_logo_5.png | Bin .../res/layout/file_dialog_main.xml | 0 .../res/layout/file_dialog_row.xml | 0 .../android-tutorial-5/res/layout/main.xml | 154 +-- .../android-tutorial-5/res/values/strings.xml | 0 .../tutorial_5/GStreamerSurfaceView.java | 0 .../gst_sdk_tutorials/tutorial_5/Tutorial5.java | 2 +- .../src/com/lamerman/FileDialog.java | 8 +- .../tutorials}/basic-tutorial-1.c | 56 +- .../tutorials}/basic-tutorial-12.c | 198 ++-- .../tutorials}/basic-tutorial-13.c | 46 +- .../tutorials}/basic-tutorial-15.c | 40 +- .../tutorials}/basic-tutorial-2.c | 150 +-- .../tutorials}/basic-tutorial-3.c | 298 +++--- .../tutorials}/basic-tutorial-4.c | 312 +++--- .../tutorials}/basic-tutorial-5.c | 118 +- .../tutorials}/basic-tutorial-6.c | 414 +++---- .../tutorials}/basic-tutorial-7.c | 26 +- .../tutorials}/basic-tutorial-8.c | 74 +- .../tutorials}/basic-tutorial-9.c | 94 +- .../tutorials}/icons/gstreamer-logo-1.svg | 0 .../tutorials}/icons/gstreamer-logo-2.svg | 0 .../tutorials}/icons/gstreamer-logo-3.svg | 0 .../tutorials}/icons/gstreamer-logo-4.svg | 0 .../tutorials}/icons/gstreamer-logo-5.svg | 0 .../tutorials}/playback-tutorial-1.c | 442 ++++---- .../tutorials}/playback-tutorial-2.c | 446 ++++---- .../tutorials}/playback-tutorial-3.c | 58 +- .../tutorials}/playback-tutorial-4.c | 56 +- .../tutorials}/playback-tutorial-5.c | 44 +- .../tutorials}/playback-tutorial-6.c | 36 +- .../tutorials}/playback-tutorial-7.c | 110 +- .../basic-tutorial-1/basic-tutorial-1.vcxproj | 190 ++-- .../basic-tutorial-1.vcxproj.filters | 10 +- .../basic-tutorial-12/basic-tutorial-12.vcxproj | 190 ++-- .../basic-tutorial-12.vcxproj.filters | 10 +- .../basic-tutorial-13/basic-tutorial-13.vcxproj | 190 ++-- .../basic-tutorial-13.vcxproj.filters | 10 +- .../basic-tutorial-15/basic-tutorial-15.vcxproj | 200 ++-- .../basic-tutorial-15.vcxproj.filters | 10 +- .../basic-tutorial-2/basic-tutorial-2.vcxproj | 190 ++-- .../basic-tutorial-2.vcxproj.filters | 10 +- .../basic-tutorial-3/basic-tutorial-3.vcxproj | 190 ++-- .../basic-tutorial-3.vcxproj.filters | 10 +- .../basic-tutorial-4/basic-tutorial-4.vcxproj | 190 ++-- .../basic-tutorial-4.vcxproj.filters | 10 +- .../basic-tutorial-5/basic-tutorial-5.vcxproj | 198 ++-- .../basic-tutorial-5.vcxproj.filters | 10 +- .../basic-tutorial-6/basic-tutorial-6.vcxproj | 190 ++-- .../basic-tutorial-6.vcxproj.filters | 10 +- .../basic-tutorial-7/basic-tutorial-7.vcxproj | 190 ++-- .../basic-tutorial-7.vcxproj.filters | 10 +- .../basic-tutorial-8/basic-tutorial-8.vcxproj | 190 ++-- .../basic-tutorial-8.vcxproj.filters | 10 +- .../basic-tutorial-9/basic-tutorial-9.vcxproj | 194 ++-- .../basic-tutorial-9.vcxproj.filters | 10 +- .../playback-tutorial-1.vcxproj | 190 ++-- .../playback-tutorial-1.vcxproj.filters | 10 +- .../playback-tutorial-2.vcxproj | 190 ++-- .../playback-tutorial-2.vcxproj.filters | 10 +- .../playback-tutorial-3.vcxproj | 190 ++-- .../playback-tutorial-3.vcxproj.filters | 10 +- .../playback-tutorial-4.vcxproj | 190 ++-- .../playback-tutorial-4.vcxproj.filters | 10 +- .../playback-tutorial-5.vcxproj | 194 ++-- .../playback-tutorial-5.vcxproj.filters | 10 +- .../playback-tutorial-6.vcxproj | 190 ++-- .../playback-tutorial-6.vcxproj.filters | 10 +- .../playback-tutorial-7.vcxproj | 190 ++-- .../playback-tutorial-7.vcxproj.filters | 10 +- .../tutorials}/vs2010/tutorials.sln | 412 +++---- .../project.pbxproj | 0 .../project.xcworkspace/contents.xcworkspacedata | 0 .../tutorials/xcode iOS/Tutorial 1}/AppDelegate.h | 0 .../tutorials/xcode iOS/Tutorial 1}/AppDelegate.m | 4 +- .../xcode iOS/Tutorial 1/GStreamerBackend.h | 0 .../xcode iOS/Tutorial 1/GStreamerBackend.m | 1 - .../AppIcon-1.appiconset}/Contents.json | 0 .../AppIcon-1.appiconset/Icon-60@2x.png | Bin .../AppIcon-1.appiconset/Icon-72.png | Bin .../AppIcon-1.appiconset/Icon-72@2x.png | Bin .../AppIcon-1.appiconset/Icon-76.png | Bin .../AppIcon-1.appiconset/Icon-76@2x.png | Bin .../AppIcon-1.appiconset/Icon-83.5@2x.png | Bin .../AppIcon-1.appiconset/Icon.png | Bin .../AppIcon-1.appiconset/Icon@2x.png | Bin .../Tutorial 1/Images-1.xcassets}/Contents.json | 0 .../LaunchImage-1.launchimage}/Contents.json | 0 .../Default-568h@2x-1.png | Bin .../LaunchImage-1.launchimage}/Default-568h@2x.png | Bin .../xcode iOS/Tutorial 1/Tutorial 1-Info.plist | 0 .../xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch | 0 .../tutorials/xcode iOS/Tutorial 1}/Ubuntu-R.ttf | Bin .../xcode iOS/Tutorial 1/ViewController.h | 0 .../xcode iOS/Tutorial 1/ViewController.m | 2 +- .../Tutorial 1/en.lproj/InfoPlist.strings | 1 - .../en.lproj/MainStoryboard_iPad.storyboard | 0 .../en.lproj/MainStoryboard_iPhone.storyboard | 0 .../tutorials/xcode iOS/Tutorial 1}/fonts.conf | 1 - .../tutorials}/xcode iOS/Tutorial 1/gst_ios_init.h | 0 .../tutorials/xcode iOS/Tutorial 1}/gst_ios_init.m | 8 +- .../tutorials/xcode iOS/Tutorial 1}/main.m | 0 .../tutorials/xcode iOS/Tutorial 2}/AppDelegate.h | 0 .../tutorials/xcode iOS/Tutorial 2}/AppDelegate.m | 4 +- .../xcode iOS/Tutorial 2/GStreamerBackend.h | 0 .../xcode iOS/Tutorial 2/GStreamerBackend.m | 13 +- .../Tutorial 2}/GStreamerBackendDelegate.h | 0 .../AppIcon-2.appiconset}/Contents.json | 0 .../AppIcon-2.appiconset/Icon-60@2x.png | Bin .../AppIcon-2.appiconset/Icon-72.png | Bin .../AppIcon-2.appiconset/Icon-72@2x.png | Bin .../AppIcon-2.appiconset/Icon-76.png | Bin .../AppIcon-2.appiconset/Icon-76@2x.png | Bin .../AppIcon-2.appiconset/Icon-83.5@2x.png | Bin .../AppIcon-2.appiconset/Icon.png | Bin .../AppIcon-2.appiconset/Icon@2x.png | Bin .../Tutorial 2/Images-2.xcassets}/Contents.json | 0 .../LaunchImage-2.launchimage}/Contents.json | 0 .../Default-568h@2x-1.png | Bin .../LaunchImage-2.launchimage}/Default-568h@2x.png | Bin .../xcode iOS/Tutorial 2/Tutorial 2-Info.plist | 0 .../xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch | 0 .../xcode iOS/Tutorial 2/Tutorial2-Info.plist | 0 .../tutorials/xcode iOS/Tutorial 2}/Ubuntu-R.ttf | Bin .../xcode iOS/Tutorial 2/ViewController.h | 0 .../xcode iOS/Tutorial 2/ViewController.m | 2 +- .../Tutorial 2/en.lproj/InfoPlist.strings | 1 - .../en.lproj/MainStoryboard_iPad.storyboard | 0 .../en.lproj/MainStoryboard_iPhone.storyboard | 0 .../tutorials/xcode iOS/Tutorial 2}/fonts.conf | 1 - .../tutorials}/xcode iOS/Tutorial 2/gst_ios_init.h | 0 .../tutorials/xcode iOS/Tutorial 2}/gst_ios_init.m | 8 +- .../tutorials/xcode iOS/Tutorial 2}/main.m | 0 .../tutorials}/xcode iOS/Tutorial 3/AppDelegate.h | 0 .../tutorials}/xcode iOS/Tutorial 3/AppDelegate.m | 4 +- .../tutorials}/xcode iOS/Tutorial 3/EaglUIVIew.h | 1 - .../tutorials/xcode iOS/Tutorial 3}/EaglUIVIew.m | 0 .../xcode iOS/Tutorial 3/GStreamerBackend.h | 0 .../xcode iOS/Tutorial 3/GStreamerBackend.m | 13 +- .../Tutorial 3}/GStreamerBackendDelegate.h | 0 .../AppIcon-3.appiconset/Contents.json | 0 .../AppIcon-3.appiconset/Icon-60@2x.png | Bin .../AppIcon-3.appiconset/Icon-72.png | Bin .../AppIcon-3.appiconset/Icon-72@2x.png | Bin .../AppIcon-3.appiconset/Icon-76.png | Bin .../AppIcon-3.appiconset/Icon-76@2x.png | Bin .../AppIcon-3.appiconset/Icon-83.5@2x.png | Bin .../AppIcon-3.appiconset/Icon.png | Bin .../AppIcon-3.appiconset/Icon@2x.png | Bin .../Tutorial 3/Images-3.xcassets/Contents.json | 0 .../LaunchImage-3.launchimage/Contents.json | 0 .../Default-568h@2x-1.png | Bin .../LaunchImage-3.launchimage/Default-568h@2x.png | Bin .../xcode iOS/Tutorial 3/Tutorial 3-Info.plist | 0 .../xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch | 0 .../tutorials}/xcode iOS/Tutorial 3/Ubuntu-R.ttf | Bin .../xcode iOS/Tutorial 3/ViewController.h | 0 .../xcode iOS/Tutorial 3/ViewController.m | 4 +- .../Tutorial 3/en.lproj/InfoPlist.strings | 1 - .../en.lproj/MainStoryboard_iPad.storyboard | 0 .../en.lproj/MainStoryboard_iPhone.storyboard | 0 .../tutorials/xcode iOS/Tutorial 3}/fonts.conf | 1 - .../tutorials}/xcode iOS/Tutorial 3/gst_ios_init.h | 0 .../tutorials}/xcode iOS/Tutorial 3/gst_ios_init.m | 8 +- .../tutorials}/xcode iOS/Tutorial 3/main.m | 0 .../tutorials/xcode iOS/Tutorial 4}/AppDelegate.h | 0 .../tutorials/xcode iOS/Tutorial 4}/AppDelegate.m | 4 +- .../tutorials/xcode iOS/Tutorial 4}/EaglUIVIew.h | 1 - .../tutorials}/xcode iOS/Tutorial 4/EaglUIVIew.m | 0 .../xcode iOS/Tutorial 4}/GStreamerBackend.h | 0 .../xcode iOS/Tutorial 4/GStreamerBackend.m | 773 +++++++------- .../Tutorial 4}/GStreamerBackendDelegate.h | 0 .../AppIcon-4.appiconset}/Contents.json | 0 .../AppIcon-4.appiconset/Icon-60@2x.png | Bin .../AppIcon-4.appiconset/Icon-72.png | Bin .../AppIcon-4.appiconset/Icon-72@2x.png | Bin .../AppIcon-4.appiconset/Icon-76.png | Bin .../AppIcon-4.appiconset/Icon-76@2x.png | Bin .../AppIcon-4.appiconset/Icon-83.5@2x.png | Bin .../AppIcon-4.appiconset/Icon.png | Bin .../AppIcon-4.appiconset/Icon@2x.png | Bin .../Tutorial 4/Images-4.xcassets}/Contents.json | 0 .../LaunchImage-4.launchimage}/Contents.json | 0 .../Default-568h@2x-1.png | Bin .../LaunchImage-4.launchimage}/Default-568h@2x.png | Bin .../xcode iOS/Tutorial 4/Tutorial 4-Info.plist | 0 .../xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch | 0 .../tutorials/xcode iOS/Tutorial 4}/Ubuntu-R.ttf | Bin .../xcode iOS/Tutorial 4}/VideoViewController.h | 0 .../xcode iOS/Tutorial 4/VideoViewController.m | 4 +- .../Tutorial 4/en.lproj/InfoPlist.strings | 1 - .../en.lproj/MainStoryboard_iPad.storyboard | 0 .../en.lproj/MainStoryboard_iPhone.storyboard | 0 .../tutorials}/xcode iOS/Tutorial 4/fonts.conf | 1 - .../tutorials}/xcode iOS/Tutorial 4/gst_ios_init.h | 0 .../tutorials/xcode iOS/Tutorial 4}/gst_ios_init.m | 8 +- .../tutorials/xcode iOS/Tutorial 4}/main.m | 0 .../Tutorial 4}/ssl/certs/ca-certificates.crt | 0 .../tutorials/xcode iOS/Tutorial 5}/AppDelegate.h | 0 .../tutorials/xcode iOS/Tutorial 5/AppDelegate.m | 38 + .../tutorials/xcode iOS/Tutorial 5}/EaglUIVIew.h | 1 - .../tutorials/xcode iOS/Tutorial 5}/EaglUIVIew.m | 0 .../xcode iOS/Tutorial 5}/GStreamerBackend.h | 0 .../xcode iOS/Tutorial 5/GStreamerBackend.m | 11 +- .../Tutorial 5}/GStreamerBackendDelegate.h | 0 .../AppIcon-5.appiconset}/Contents.json | 0 .../AppIcon-5.appiconset/Icon-60@2x.png | Bin .../AppIcon-5.appiconset/Icon-72.png | Bin .../AppIcon-5.appiconset/Icon-72@2x.png | Bin .../AppIcon-5.appiconset/Icon-76.png | Bin .../AppIcon-5.appiconset/Icon-76@2x.png | Bin .../AppIcon-5.appiconset/Icon-83.5@2x.png | Bin .../AppIcon-5.appiconset/Icon.png | Bin .../AppIcon-5.appiconset/Icon@2x.png | Bin .../Tutorial 5/Images-5.xcassets}/Contents.json | 0 .../LaunchImage-5.launchimage}/Contents.json | 0 .../Default-568h@2x-1.png | Bin .../LaunchImage-5.launchimage}/Default-568h@2x.png | Bin .../xcode iOS/Tutorial 5/LibraryViewController.h | 0 .../xcode iOS/Tutorial 5/LibraryViewController.m | 0 .../xcode iOS/Tutorial 5/Tutorial 5-Info.plist | 0 .../xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch | 0 .../tutorials/xcode iOS/Tutorial 5}/Ubuntu-R.ttf | Bin .../xcode iOS/Tutorial 5}/VideoViewController.h | 0 .../xcode iOS/Tutorial 5/VideoViewController.m | 4 +- .../Tutorial 5/en.lproj/InfoPlist.strings | 1 + .../en.lproj/MainStoryboard_iPad.storyboard | 0 .../en.lproj/MainStoryboard_iPhone.storyboard | 0 examples/tutorials/xcode iOS/Tutorial 5/fonts.conf | 125 +++ .../tutorials}/xcode iOS/Tutorial 5/gst_ios_init.h | 0 .../tutorials/xcode iOS/Tutorial 5}/gst_ios_init.m | 8 +- .../tutorials/xcode iOS/Tutorial 5}/main.m | 0 .../Tutorial 5}/ssl/certs/ca-certificates.crt | 0 .../GStreamer Tutorials.xcodeproj/project.pbxproj | 0 .../project.xcworkspace/contents.xcworkspacedata | 0 .../xcshareddata/xcschemes/01-Tutorial 1.xcscheme | 0 .../xcshareddata/xcschemes/02-Tutorial 2.xcscheme | 0 .../xcshareddata/xcschemes/03-Turorial 3.xcscheme | 0 .../xcshareddata/xcschemes/04-Tutorial 4.xcscheme | 0 .../xcshareddata/xcschemes/05-Tutorial 5.xcscheme | 0 .../xcshareddata/xcschemes/06-Tutorial 6.xcscheme | 0 .../xcshareddata/xcschemes/07-Tutorial 7.xcscheme | 0 .../xcshareddata/xcschemes/08-Tutorial 8.xcscheme | 0 .../xcshareddata/xcschemes/09-Tutorial 9.xcscheme | 0 .../xcshareddata/xcschemes/12-Tutorial 12.xcscheme | 0 .../xcshareddata/xcschemes/13-Tutorial 13.xcscheme | 0 .../xcshareddata/xcschemes/15-Tutorial 15.xcscheme | 0 .../xcschemes/21-Playback Tutorial 1.xcscheme | 0 .../xcschemes/22-Playback Tutorial 2.xcscheme | 0 .../xcschemes/23-Playback Tutorial 3.xcscheme | 0 .../xcschemes/24-Playback Tutorial 4.xcscheme | 0 .../xcschemes/25-Playback Tutorial 5.xcscheme | 0 .../xcschemes/26-Playback Tutorial 6.xcscheme | 0 .../xcschemes/27-Playback Tutorial 7.xcscheme | 0 .../xcschemes/xcschememanagement.plist | 0 hotdoc.json | 8 +- .../WindowsInstall-BuildSolution.png | Bin .../WindowsInstall-Configuration.png | Bin {attachments => images}/WindowsInstall1.png | Bin {attachments => images}/WindowsInstall10.png | Bin {attachments => images}/WindowsInstall11.png | Bin {attachments => images}/WindowsInstall2.png | Bin {attachments => images}/WindowsInstall3.png | Bin {attachments => images}/WindowsInstall4.png | Bin {attachments => images}/WindowsInstall5.png | Bin {attachments => images}/WindowsInstall6.png | Bin {attachments => images}/WindowsInstall7.png | Bin {attachments => images}/WindowsInstall8.png | Bin {attachments => images}/WindowsInstall9.png | Bin {attachments => images}/android.png | Bin {attachments => images}/contact.png | Bin {attachments => images}/deploy.png | Bin {attachments => images}/download.png | Bin {attachments => images}/emoticons/information.png | Bin {attachments => images}/faq.png | Bin {attachments => images}/figure-1.png | Bin {attachments => images}/ios.jpeg | Bin {attachments => images}/legal.png | Bin {attachments => images}/linux.png | Bin {attachments => images}/mac.png | Bin {attachments => images}/reference.png | Bin {attachments => images}/releases.png | Bin {attachments => images}/tutorials.png | Bin ...android-a-complete-media-player-screenshot.png} | Bin .../android-a-running-pipeline-screenshot.png} | Bin .../android-link-against-gstreamer-screenshot.png} | Bin .../android-media-player-screenshot.png} | Bin .../android-video-screenshot.png} | Bin .../tutorials}/basic-tutorial-5.png | Bin .../tutorials}/basic-tutorial-7.png | Bin .../tutorials}/basic-tutorial-8.png | Bin .../ios-a-basic-media-player-screenshot.png} | Bin .../ios-a-complete-media-player-screenshot-0.png} | Bin .../ios-a-complete-media-player-screenshot-1.png} | Bin .../ios-a-running-pipeline-screenshot.png} | Bin .../ios-link-against-gstreamer-screenshot.png} | Bin .../ios-video-screenshot.png} | Bin {attachments => images}/windows.png | Bin .../deploying/index.md | 6 +- .../deploying/mac-osx.md | 4 +- .../deploying/multiplatform-using-cerbero.md | 8 +- .../deploying/windows.md | 4 +- .../for-later/basic-media-player.md | 0 .../for-later/qt-gstreamer-vs-c-gstreamer.md | 0 .../for-later/using-appsink-appsrc-in-qt.md | 0 index.md => markdown/index.md | 4 +- .../building-from-source-using-cerbero.md | 2 +- .../installing/for-android-development.md | 4 +- .../installing/for-ios-development.md | 4 +- installing.md => markdown/installing/index.md | 10 +- .../installing/on-linux.md | 2 +- .../installing/on-mac-osx.md | 6 +- .../installing/on-windows.md | 14 +- .../legal-information.md | 52 +- .../manual/advanced/autoplugging.md | 15 +- .../manual/advanced/buffering.md | 19 +- .../manual/advanced/clocks.md | 1 - .../manual/advanced/dataaccess.md | 45 +- .../manual/advanced/dparams.md | 9 +- .../manual/advanced/index.md | 1 - .../manual/advanced/interfaces.md | 3 +- .../manual/advanced/metadata.md | 7 +- .../manual/advanced/queryevents.md | 5 +- .../manual/advanced/threads.md | 19 +- .../manual/appendix/checklist-element.md | 3 +- .../manual/appendix/compiling.md | 3 +- .../manual/appendix/index.md | 1 - .../manual/appendix/integration.md | 17 +- .../manual/appendix/licensing.md | 1 - .../manual/appendix/porting-1.0.md | 15 +- .../manual/appendix/porting.md | 7 +- .../manual/appendix/programs.md | 61 +- .../manual/appendix/quotes.md | 145 ++- manual-bins.md => markdown/manual/building/bins.md | 11 +- manual-bus.md => markdown/manual/building/bus.md | 13 +- manual-data.md => markdown/manual/building/data.md | 3 +- .../manual/building/elements.md | 25 +- .../manual/building/helloworld.md | 13 +- .../manual/building/index.md | 1 - manual-init.md => markdown/manual/building/init.md | 5 +- manual-pads.md => markdown/manual/building/pads.md | 49 +- .../manual/highlevel/index.md | 1 - .../manual/highlevel/playback-components.md | 15 +- manual-index.md => markdown/manual/index.md | 13 +- .../manual/introduction/basics.md | 1 - .../manual/introduction/gstreamer.md | 1 - .../manual/introduction/index.md | 1 - .../manual/introduction/motivation.md | 1 - .../pwg/advanced/allocation.md | 23 +- .../pwg/advanced/building-types.md | 3 +- .../pwg/advanced/clock.md | 1 - pwg-dparams.md => markdown/pwg/advanced/dparams.md | 9 +- .../pwg/advanced/events.md | 11 +- pwg-advanced.md => markdown/pwg/advanced/index.md | 1 - .../pwg/advanced/interfaces.md | 17 +- .../pwg/advanced/negotiation.md | 11 +- .../pwg/advanced/qos.md | 7 +- .../pwg/advanced/request.md | 9 +- .../pwg/advanced/scheduling.md | 49 +- .../pwg/advanced/tagging.md | 5 +- .../pwg/appendix/checklist-element.md | 17 +- pwg-appendix.md => markdown/pwg/appendix/index.md | 1 - .../pwg/appendix/licensing-advisory.md | 1 - .../pwg/appendix/porting-1_0.md | 1 - pwg-porting.md => markdown/pwg/appendix/porting.md | 17 +- .../pwg/building/args.md | 5 +- .../pwg/building/boiler.md | 39 +- .../pwg/building/chainfn.md | 17 +- .../pwg/building/eventfn.md | 3 +- pwg-building.md => markdown/pwg/building/index.md | 3 +- .../pwg/building/pads.md | 3 +- .../pwg/building/queryfn.md | 3 +- .../pwg/building/signals.md | 1 - .../pwg/building/statemanage-states.md | 21 +- .../pwg/building/testapp.md | 3 +- pwg-index.md => markdown/pwg/index.md | 0 .../pwg/introduction/basics.md | 9 +- .../pwg/introduction/index.md | 1 - .../pwg/introduction/preface.md | 87 +- pwg-other-base.md => markdown/pwg/other/base.md | 7 +- pwg-other.md => markdown/pwg/other/index.md | 1 - .../pwg/other/manager.md | 1 - .../pwg/other/ntoone.md | 5 +- .../pwg/other/oneton.md | 7 +- rtp.md => markdown/rtp.md | 1 - splitup.md => markdown/splitup.md | 6 +- tool-ges-launch.md => markdown/tools/ges-launch.md | 2 +- .../tools/gst-inspect.md | 0 tool-gst-launch.md => markdown/tools/gst-launch.md | 0 .../tools/index.md | 0 .../tutorials/android/a-complete-media-player.md | 6 +- .../tutorials/android/a-running-pipeline.md | 10 +- .../tutorials/android/index.md | 8 +- .../tutorials/android/link-against-gstreamer.md | 8 +- .../tutorials/android/media-player.md | 24 +- .../tutorials/android/video.md | 8 +- .../tutorials/basic/concepts.md | 20 +- .../tutorials/basic/debugging-tools.md | 0 .../tutorials/basic/dynamic-pipelines.md | 22 +- .../tutorials/basic/gstreamer-tools.md | 24 +- .../tutorials/basic/handy-elements.md | 18 +- .../tutorials/basic/hello-world.md | 26 +- .../tutorials/basic/index.md | 0 .../basic/media-formats-and-pad-capabilities.md | 8 +- .../tutorials/basic/media-information-gathering.md | 6 +- .../basic/multithreading-and-pad-availability.md | 10 +- .../tutorials/basic/platform-specific-elements.md | 4 +- .../tutorials/basic/playback-speed.md | 6 +- .../tutorials/basic/short-cutting-the-pipeline.md | 18 +- .../tutorials/basic/streaming.md | 4 +- .../tutorials/basic/time-management.md | 6 +- .../tutorials/basic/toolkit-integration.md | 16 +- tutorials.md => markdown/tutorials/index.md | 12 +- .../tutorials/ios/a-basic-media-player.md | 18 +- .../tutorials/ios/a-complete-media-player.md | 8 +- .../tutorials/ios/a-running-pipeline.md | 12 +- .../tutorials/ios/index.md | 8 +- .../tutorials/ios/link-against-gstreamer.md | 6 +- .../tutorials/ios/video.md | 8 +- .../tutorials/playback/audio-visualization.md | 14 +- .../tutorials/playback/color-balance.md | 14 +- .../tutorials/playback/custom-playbin-sinks.md | 14 +- .../playback/digital-audio-pass-through.md | 4 +- .../hardware-accelerated-video-decoding.md | 0 .../tutorials/playback/index.md | 0 .../tutorials/playback/playbin-usage.md | 16 +- .../tutorials/playback/progressive-streaming.md | 22 +- .../playback/short-cutting-the-pipeline.md | 12 +- .../tutorials/playback/subtitle-management.md | 8 +- .../tutorials/qt-tutorials.md | 4 +- .../tutorials/table-of-concepts.md | 26 +- sitemap.txt | 250 ++--- {extra_theme => theme/extra}/images/favicon.png | Bin .../extra}/images/gstreamer-logo.svg | 0 .../extra}/templates/extra_head.html | 0 {extra_theme => theme/extra}/templates/navbar.html | 0 .../hotdoc_bootstrap_theme | 0 {less => theme/less}/variables.less | 0 tutorials/android-tutorial-5/jni/Application.mk | 2 - tutorials/xcode iOS/Tutorial 5/AppDelegate.m | 38 - .../Tutorial 5/en.lproj/InfoPlist.strings | 2 - tutorials/xcode iOS/Tutorial 5/fonts.conf | 126 --- 514 files changed, 5908 insertions(+), 5997 deletions(-) delete mode 100644 attachments/filter-element-multi.png delete mode 100644 attachments/filter-element.png delete mode 100644 attachments/simple-player.png delete mode 100644 attachments/sink-element.png delete mode 100644 attachments/src-element.png rename {tutorials => examples/tutorials}/android-tutorial-1/AndroidManifest.xml (98%) rename {tutorials => examples/tutorials}/android-tutorial-1/jni/Android.mk (100%) rename {tutorials/android-tutorial-4 => examples/tutorials/android-tutorial-1}/jni/Application.mk (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/jni/tutorial-1.c (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-hdpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-ldpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-mdpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-xhdpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-xxhdpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/drawable-xxxhdpi/gstreamer_logo_1.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/layout/main.xml (94%) rename {tutorials => examples/tutorials}/android-tutorial-1/res/values/strings.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java (97%) rename {tutorials => examples/tutorials}/android-tutorial-2/AndroidManifest.xml (98%) rename {tutorials => examples/tutorials}/android-tutorial-2/jni/Android.mk (100%) rename {tutorials/android-tutorial-3 => examples/tutorials/android-tutorial-2}/jni/Application.mk (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/jni/tutorial-2.c (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-hdpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-ldpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-mdpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-xhdpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-xxhdpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/drawable-xxxhdpi/gstreamer_logo_2.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/layout/main.xml (96%) rename {tutorials => examples/tutorials}/android-tutorial-2/res/values/strings.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java (99%) rename {tutorials => examples/tutorials}/android-tutorial-3/AndroidManifest.xml (98%) rename {tutorials => examples/tutorials}/android-tutorial-3/jni/Android.mk (100%) rename {tutorials/android-tutorial-2 => examples/tutorials/android-tutorial-3}/jni/Application.mk (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/jni/tutorial-3.c (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-hdpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-ldpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-mdpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-xhdpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-xxhdpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/drawable-xxxhdpi/gstreamer_logo_3.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/layout/main.xml (97%) rename {tutorials => examples/tutorials}/android-tutorial-3/res/values/strings.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/GStreamerSurfaceView.java (100%) rename {tutorials => examples/tutorials}/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java (99%) rename {tutorials => examples/tutorials}/android-tutorial-4/AndroidManifest.xml (98%) rename {tutorials => examples/tutorials}/android-tutorial-4/jni/Android.mk (100%) rename {tutorials/android-tutorial-1 => examples/tutorials/android-tutorial-4}/jni/Application.mk (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/jni/tutorial-4.c (97%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-hdpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-ldpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-mdpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-xhdpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-xxhdpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/drawable-xxxhdpi/gstreamer_logo_4.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/layout/main.xml (96%) rename {tutorials => examples/tutorials}/android-tutorial-4/res/values/strings.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/GStreamerSurfaceView.java (100%) rename {tutorials => examples/tutorials}/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java (99%) rename {tutorials => examples/tutorials}/android-tutorial-5/AndroidManifest.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/jni/Android.mk (100%) create mode 100644 examples/tutorials/android-tutorial-5/jni/Application.mk rename {tutorials => examples/tutorials}/android-tutorial-5/jni/tutorial-5.c (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-ldpi/file.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-ldpi/folder.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-ldpi/gstreamer_logo_5.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-mdpi/gstreamer_logo_5.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-xhdpi/gstreamer_logo_5.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-xxhdpi/gstreamer_logo_5.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/drawable-xxxhdpi/gstreamer_logo_5.png (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/layout/file_dialog_main.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/layout/file_dialog_row.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/layout/main.xml (97%) rename {tutorials => examples/tutorials}/android-tutorial-5/res/values/strings.xml (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/GStreamerSurfaceView.java (100%) rename {tutorials => examples/tutorials}/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java (99%) rename {tutorials => examples/tutorials}/android-tutorial-5/src/com/lamerman/FileDialog.java (99%) rename {tutorials => examples/tutorials}/basic-tutorial-1.c (94%) rename {tutorials => examples/tutorials}/basic-tutorial-12.c (94%) rename {tutorials => examples/tutorials}/basic-tutorial-13.c (98%) rename {tutorials => examples/tutorials}/basic-tutorial-15.c (98%) rename {tutorials => examples/tutorials}/basic-tutorial-2.c (94%) rename {tutorials => examples/tutorials}/basic-tutorial-3.c (95%) rename {tutorials => examples/tutorials}/basic-tutorial-4.c (95%) rename {tutorials => examples/tutorials}/basic-tutorial-5.c (98%) rename {tutorials => examples/tutorials}/basic-tutorial-6.c (95%) rename {tutorials => examples/tutorials}/basic-tutorial-7.c (99%) rename {tutorials => examples/tutorials}/basic-tutorial-8.c (98%) rename {tutorials => examples/tutorials}/basic-tutorial-9.c (97%) rename {tutorials => examples/tutorials}/icons/gstreamer-logo-1.svg (100%) rename {tutorials => examples/tutorials}/icons/gstreamer-logo-2.svg (100%) rename {tutorials => examples/tutorials}/icons/gstreamer-logo-3.svg (100%) rename {tutorials => examples/tutorials}/icons/gstreamer-logo-4.svg (100%) rename {tutorials => examples/tutorials}/icons/gstreamer-logo-5.svg (100%) rename {tutorials => examples/tutorials}/playback-tutorial-1.c (96%) rename {tutorials => examples/tutorials}/playback-tutorial-2.c (96%) rename {tutorials => examples/tutorials}/playback-tutorial-3.c (98%) rename {tutorials => examples/tutorials}/playback-tutorial-4.c (98%) rename {tutorials => examples/tutorials}/playback-tutorial-5.c (98%) rename {tutorials => examples/tutorials}/playback-tutorial-6.c (97%) rename {tutorials => examples/tutorials}/playback-tutorial-7.c (95%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj (98%) rename {tutorials => examples/tutorials}/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters (93%) rename {tutorials => examples/tutorials}/vs2010/tutorials.sln (98%) rename {tutorials => examples/tutorials}/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.pbxproj (100%) rename {tutorials => examples/tutorials}/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 1}/AppDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 1}/AppDelegate.m (98%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/GStreamerBackend.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/GStreamerBackend.m (99%) rename {tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset => examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset}/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-60@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-83.5@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon@2x.png (100%) rename {tutorials/xcode iOS/Tutorial 5/Images-5.xcassets => examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage => examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage => examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage}/Default-568h@2x-1.png (100%) rename {tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage => examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage}/Default-568h@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Tutorial 1-Info.plist (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 1}/Ubuntu-R.ttf (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/ViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/ViewController.m (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings (97%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPad.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPhone.storyboard (100%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 1}/fonts.conf (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 1/gst_ios_init.h (100%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 1}/gst_ios_init.m (99%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 1}/main.m (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 2}/AppDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 2}/AppDelegate.m (98%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/GStreamerBackend.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/GStreamerBackend.m (99%) rename {tutorials/xcode iOS/Tutorial 3 => examples/tutorials/xcode iOS/Tutorial 2}/GStreamerBackendDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset => examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset}/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-60@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-83.5@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon@2x.png (100%) rename {tutorials/xcode iOS/Tutorial 4/Images-4.xcassets => examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage => examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage => examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage}/Default-568h@2x-1.png (100%) rename {tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage => examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage}/Default-568h@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Tutorial 2-Info.plist (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/Tutorial2-Info.plist (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 2}/Ubuntu-R.ttf (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/ViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/ViewController.m (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings (97%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPad.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPhone.storyboard (100%) rename {tutorials/xcode iOS/Tutorial 3 => examples/tutorials/xcode iOS/Tutorial 2}/fonts.conf (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 2/gst_ios_init.h (100%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 2}/gst_ios_init.m (99%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 2}/main.m (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/AppDelegate.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/AppDelegate.m (98%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/EaglUIVIew.h (99%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 3}/EaglUIVIew.m (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/GStreamerBackend.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/GStreamerBackend.m (99%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 3}/GStreamerBackendDelegate.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-60@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-83.5@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x-1.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Tutorial 3-Info.plist (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/Ubuntu-R.ttf (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/ViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/ViewController.m (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings (97%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPad.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPhone.storyboard (100%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 3}/fonts.conf (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/gst_ios_init.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/gst_ios_init.m (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 3/main.m (100%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 4}/AppDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 4}/AppDelegate.m (98%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/EaglUIVIew.h (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/EaglUIVIew.m (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/GStreamerBackend.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/GStreamerBackend.m (97%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/GStreamerBackendDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset => examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset}/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-60@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-83.5@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon@2x.png (100%) rename {tutorials/xcode iOS/Tutorial 2/Images-2.xcassets => examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage => examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage => examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage}/Default-568h@2x-1.png (100%) rename {tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage => examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage}/Default-568h@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Tutorial 4-Info.plist (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch (100%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 4}/Ubuntu-R.ttf (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/VideoViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/VideoViewController.m (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings (97%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPad.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPhone.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/fonts.conf (99%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 4/gst_ios_init.h (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/gst_ios_init.m (99%) rename {tutorials/xcode iOS/Tutorial 2 => examples/tutorials/xcode iOS/Tutorial 4}/main.m (100%) rename {tutorials/xcode iOS/Tutorial 5 => examples/tutorials/xcode iOS/Tutorial 4}/ssl/certs/ca-certificates.crt (100%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 5}/AppDelegate.h (100%) create mode 100644 examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.m rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/EaglUIVIew.h (99%) rename {tutorials/xcode iOS/Tutorial 3 => examples/tutorials/xcode iOS/Tutorial 5}/EaglUIVIew.m (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/GStreamerBackend.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/GStreamerBackend.m (99%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/GStreamerBackendDelegate.h (100%) rename {tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset => examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset}/Contents.json (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-60@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-83.5@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon@2x.png (100%) rename {tutorials/xcode iOS/Tutorial 1/Images-1.xcassets => examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage => examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage}/Contents.json (100%) rename {tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage => examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage}/Default-568h@2x-1.png (100%) rename {tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage => examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage}/Default-568h@2x.png (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/LibraryViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/LibraryViewController.m (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Tutorial 5-Info.plist (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch (100%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 5}/Ubuntu-R.ttf (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/VideoViewController.h (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/VideoViewController.m (99%) create mode 100644 examples/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPad.storyboard (100%) rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPhone.storyboard (100%) create mode 100644 examples/tutorials/xcode iOS/Tutorial 5/fonts.conf rename {tutorials => examples/tutorials}/xcode iOS/Tutorial 5/gst_ios_init.h (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/gst_ios_init.m (99%) rename {tutorials/xcode iOS/Tutorial 1 => examples/tutorials/xcode iOS/Tutorial 5}/main.m (100%) rename {tutorials/xcode iOS/Tutorial 4 => examples/tutorials/xcode iOS/Tutorial 5}/ssl/certs/ca-certificates.crt (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/01-Tutorial 1.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/02-Tutorial 2.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/03-Turorial 3.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/04-Tutorial 4.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/05-Tutorial 5.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/06-Tutorial 6.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/07-Tutorial 7.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/08-Tutorial 8.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/09-Tutorial 9.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/12-Tutorial 12.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/13-Tutorial 13.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/15-Tutorial 15.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/21-Playback Tutorial 1.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/22-Playback Tutorial 2.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/23-Playback Tutorial 3.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/24-Playback Tutorial 4.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/25-Playback Tutorial 5.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/26-Playback Tutorial 6.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/27-Playback Tutorial 7.xcscheme (100%) rename {tutorials => examples/tutorials}/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist (100%) rename {attachments => images}/WindowsInstall-BuildSolution.png (100%) rename {attachments => images}/WindowsInstall-Configuration.png (100%) rename {attachments => images}/WindowsInstall1.png (100%) rename {attachments => images}/WindowsInstall10.png (100%) rename {attachments => images}/WindowsInstall11.png (100%) rename {attachments => images}/WindowsInstall2.png (100%) rename {attachments => images}/WindowsInstall3.png (100%) rename {attachments => images}/WindowsInstall4.png (100%) rename {attachments => images}/WindowsInstall5.png (100%) rename {attachments => images}/WindowsInstall6.png (100%) rename {attachments => images}/WindowsInstall7.png (100%) rename {attachments => images}/WindowsInstall8.png (100%) rename {attachments => images}/WindowsInstall9.png (100%) rename {attachments => images}/android.png (100%) rename {attachments => images}/contact.png (100%) rename {attachments => images}/deploy.png (100%) rename {attachments => images}/download.png (100%) rename {attachments => images}/emoticons/information.png (100%) rename {attachments => images}/faq.png (100%) rename {attachments => images}/figure-1.png (100%) rename {attachments => images}/ios.jpeg (100%) rename {attachments => images}/legal.png (100%) rename {attachments => images}/linux.png (100%) rename {attachments => images}/mac.png (100%) rename {attachments => images}/reference.png (100%) rename {attachments => images}/releases.png (100%) rename {attachments => images}/tutorials.png (100%) rename images/{tutorial-android-a-complete-media-player-screenshot.png => tutorials/android-a-complete-media-player-screenshot.png} (100%) rename images/{tutorial-android-a-running-pipeline-screenshot.png => tutorials/android-a-running-pipeline-screenshot.png} (100%) rename images/{tutorial-android-link-against-gstreamer-screenshot.png => tutorials/android-link-against-gstreamer-screenshot.png} (100%) rename images/{tutorial-android-media-player-screenshot.png => tutorials/android-media-player-screenshot.png} (100%) rename images/{tutorial-android-video-screenshot.png => tutorials/android-video-screenshot.png} (100%) rename {attachments => images/tutorials}/basic-tutorial-5.png (100%) rename {attachments => images/tutorials}/basic-tutorial-7.png (100%) rename {attachments => images/tutorials}/basic-tutorial-8.png (100%) rename images/{tutorial-ios-a-basic-media-player-screenshot.png => tutorials/ios-a-basic-media-player-screenshot.png} (100%) rename images/{tutorial-ios-a-complete-media-player-screenshot-0.png => tutorials/ios-a-complete-media-player-screenshot-0.png} (100%) rename images/{tutorial-ios-a-complete-media-player-screenshot-1.png => tutorials/ios-a-complete-media-player-screenshot-1.png} (100%) rename images/{tutorial-ios-a-running-pipeline-screenshot.png => tutorials/ios-a-running-pipeline-screenshot.png} (100%) rename images/{tutorial-ios-link-against-gstreamer-screenshot.png => tutorials/ios-link-against-gstreamer-screenshot.png} (100%) rename images/{tutorial-ios-video-screenshot.png => tutorials/ios-video-screenshot.png} (100%) rename {attachments => images}/windows.png (100%) rename deploying-your-application.md => markdown/deploying/index.md (96%) rename deploying-mac-osx.md => markdown/deploying/mac-osx.md (99%) rename deploying-multiplatform-using-cerbero.md => markdown/deploying/multiplatform-using-cerbero.md (97%) rename deploying-windows.md => markdown/deploying/windows.md (97%) rename basic-media-player.md => markdown/for-later/basic-media-player.md (100%) rename qt-gstreamer-vs-c-gstreamer.md => markdown/for-later/qt-gstreamer-vs-c-gstreamer.md (100%) rename using-appsink-appsrc-in-qt.md => markdown/for-later/using-appsink-appsrc-in-qt.md (100%) rename index.md => markdown/index.md (98%) rename building-from-source-using-cerbero.md => markdown/installing/building-from-source-using-cerbero.md (99%) rename installing-for-android-development.md => markdown/installing/for-android-development.md (99%) rename installing-for-ios-development.md => markdown/installing/for-ios-development.md (96%) rename installing.md => markdown/installing/index.md (68%) rename installing-on-linux.md => markdown/installing/on-linux.md (97%) rename installing-on-mac-osx.md => markdown/installing/on-mac-osx.md (97%) rename installing-on-windows.md => markdown/installing/on-windows.md (97%) rename legal-information.md => markdown/legal-information.md (98%) rename manual-autoplugging.md => markdown/manual/advanced/autoplugging.md (94%) rename manual-buffering.md => markdown/manual/advanced/buffering.md (99%) rename manual-clocks.md => markdown/manual/advanced/clocks.md (99%) rename manual-dataaccess.md => markdown/manual/advanced/dataaccess.md (99%) rename manual-dparams.md => markdown/manual/advanced/dparams.md (99%) rename manual-advanced.md => markdown/manual/advanced/index.md (99%) rename manual-interfaces.md => markdown/manual/advanced/interfaces.md (97%) rename manual-metadata.md => markdown/manual/advanced/metadata.md (97%) rename manual-queryevents.md => markdown/manual/advanced/queryevents.md (99%) rename manual-threads.md => markdown/manual/advanced/threads.md (99%) rename manual-checklist-element.md => markdown/manual/appendix/checklist-element.md (99%) rename manual-compiling.md => markdown/manual/appendix/compiling.md (99%) rename manual-appendices.md => markdown/manual/appendix/index.md (99%) rename manual-integration.md => markdown/manual/appendix/integration.md (99%) rename manual-licensing.md => markdown/manual/appendix/licensing.md (99%) rename manual-porting-1.0.md => markdown/manual/appendix/porting-1.0.md (99%) rename manual-porting.md => markdown/manual/appendix/porting.md (95%) rename manual-programs.md => markdown/manual/appendix/programs.md (97%) rename manual-quotes.md => markdown/manual/appendix/quotes.md (88%) rename manual-bins.md => markdown/manual/building/bins.md (98%) rename manual-bus.md => markdown/manual/building/bus.md (98%) rename manual-data.md => markdown/manual/building/data.md (99%) rename manual-elements.md => markdown/manual/building/elements.md (98%) rename manual-helloworld.md => markdown/manual/building/helloworld.md (95%) rename manual-building.md => markdown/manual/building/index.md (99%) rename manual-init.md => markdown/manual/building/init.md (99%) rename manual-pads.md => markdown/manual/building/pads.md (97%) rename manual-highlevel.md => markdown/manual/highlevel/index.md (99%) rename manual-playback-components.md => markdown/manual/highlevel/playback-components.md (97%) rename manual-index.md => markdown/manual/index.md (88%) rename manual-intro-basics.md => markdown/manual/introduction/basics.md (99%) rename manual-gstreamer.md => markdown/manual/introduction/gstreamer.md (99%) rename manual-introduction.md => markdown/manual/introduction/index.md (99%) rename manual-motivation.md => markdown/manual/introduction/motivation.md (99%) rename pwg-allocation.md => markdown/pwg/advanced/allocation.md (99%) rename pwg-building-types.md => markdown/pwg/advanced/building-types.md (99%) rename pwg-advanced-clock.md => markdown/pwg/advanced/clock.md (99%) rename pwg-dparams.md => markdown/pwg/advanced/dparams.md (99%) rename pwg-advanced-events.md => markdown/pwg/advanced/events.md (98%) rename pwg-advanced.md => markdown/pwg/advanced/index.md (99%) rename pwg-advanced-interfaces.md => markdown/pwg/advanced/interfaces.md (97%) rename pwg-negotiation.md => markdown/pwg/advanced/negotiation.md (99%) rename pwg-advanced-qos.md => markdown/pwg/advanced/qos.md (99%) rename pwg-advanced-request.md => markdown/pwg/advanced/request.md (99%) rename pwg-scheduling.md => markdown/pwg/advanced/scheduling.md (99%) rename pwg-advanced-tagging.md => markdown/pwg/advanced/tagging.md (99%) rename pwg-checklist-element.md => markdown/pwg/appendix/checklist-element.md (98%) rename pwg-appendix.md => markdown/pwg/appendix/index.md (99%) rename pwg-licensing-advisory.md => markdown/pwg/appendix/licensing-advisory.md (99%) rename pwg-porting-1_0.md => markdown/pwg/appendix/porting-1_0.md (99%) rename pwg-porting.md => markdown/pwg/appendix/porting.md (95%) rename pwg-building-args.md => markdown/pwg/building/args.md (98%) rename pwg-building-boiler.md => markdown/pwg/building/boiler.md (98%) rename pwg-building-chainfn.md => markdown/pwg/building/chainfn.md (98%) rename pwg-building-eventfn.md => markdown/pwg/building/eventfn.md (99%) rename pwg-building.md => markdown/pwg/building/index.md (93%) rename pwg-building-pads.md => markdown/pwg/building/pads.md (99%) rename pwg-building-queryfn.md => markdown/pwg/building/queryfn.md (99%) rename pwg-building-signals.md => markdown/pwg/building/signals.md (99%) rename pwg-statemanage-states.md => markdown/pwg/building/statemanage-states.md (98%) rename pwg-building-testapp.md => markdown/pwg/building/testapp.md (99%) rename pwg-index.md => markdown/pwg/index.md (100%) rename pwg-intro-basics.md => markdown/pwg/introduction/basics.md (98%) rename pwg-introduction.md => markdown/pwg/introduction/index.md (99%) rename pwg-intro-preface.md => markdown/pwg/introduction/preface.md (82%) rename pwg-other-base.md => markdown/pwg/other/base.md (99%) rename pwg-other.md => markdown/pwg/other/index.md (99%) rename pwg-other-manager.md => markdown/pwg/other/manager.md (99%) rename pwg-other-ntoone.md => markdown/pwg/other/ntoone.md (87%) rename pwg-other-oneton.md => markdown/pwg/other/oneton.md (86%) rename rtp.md => markdown/rtp.md (99%) rename splitup.md => markdown/splitup.md (97%) rename tool-ges-launch.md => markdown/tools/ges-launch.md (99%) rename tool-gst-inspect.md => markdown/tools/gst-inspect.md (100%) rename tool-gst-launch.md => markdown/tools/gst-launch.md (100%) rename gstreamer-command-line-tools.md => markdown/tools/index.md (100%) rename tutorial-android-a-complete-media-player.md => markdown/tutorials/android/a-complete-media-player.md (94%) rename tutorial-android-a-running-pipeline.md => markdown/tutorials/android/a-running-pipeline.md (99%) rename tutorials-android.md => markdown/tutorials/android/index.md (79%) rename tutorial-android-link-against-gstreamer.md => markdown/tutorials/android/link-against-gstreamer.md (98%) rename tutorial-android-media-player.md => markdown/tutorials/android/media-player.md (99%) rename tutorial-android-video.md => markdown/tutorials/android/video.md (99%) rename tutorial-basic-concepts.md => markdown/tutorials/basic/concepts.md (93%) rename tutorial-basic-debugging-tools.md => markdown/tutorials/basic/debugging-tools.md (100%) rename tutorial-basic-dynamic-pipelines.md => markdown/tutorials/basic/dynamic-pipelines.md (95%) rename tutorial-basic-gstreamer-tools.md => markdown/tutorials/basic/gstreamer-tools.md (96%) rename tutorial-basic-handy-elements.md => markdown/tutorials/basic/handy-elements.md (95%) rename tutorial-basic-hello-world.md => markdown/tutorials/basic/hello-world.md (91%) rename tutorials-basic.md => markdown/tutorials/basic/index.md (100%) rename tutorial-basic-media-formats-and-pad-capabilities.md => markdown/tutorials/basic/media-formats-and-pad-capabilities.md (97%) rename tutorial-basic-media-information-gathering.md => markdown/tutorials/basic/media-information-gathering.md (97%) rename tutorial-basic-multithreading-and-pad-availability.md => markdown/tutorials/basic/multithreading-and-pad-availability.md (96%) rename tutorial-basic-platform-specific-elements.md => markdown/tutorials/basic/platform-specific-elements.md (98%) rename tutorial-basic-playback-speed.md => markdown/tutorials/basic/playback-speed.md (96%) rename tutorial-basic-short-cutting-the-pipeline.md => markdown/tutorials/basic/short-cutting-the-pipeline.md (96%) rename tutorial-basic-streaming.md => markdown/tutorials/basic/streaming.md (95%) rename tutorial-basic-time-management.md => markdown/tutorials/basic/time-management.md (97%) rename tutorial-basic-toolkit-integration.md => markdown/tutorials/basic/toolkit-integration.md (98%) rename tutorials.md => markdown/tutorials/index.md (91%) rename tutorial-ios-a-basic-media-player.md => markdown/tutorials/ios/a-basic-media-player.md (98%) rename tutorial-ios-a-complete-media-player.md => markdown/tutorials/ios/a-complete-media-player.md (88%) rename tutorial-ios-a-running-pipeline.md => markdown/tutorials/ios/a-running-pipeline.md (98%) rename tutorials-ios.md => markdown/tutorials/ios/index.md (81%) rename tutorial-ios-link-against-gstreamer.md => markdown/tutorials/ios/link-against-gstreamer.md (97%) rename tutorial-ios-video.md => markdown/tutorials/ios/video.md (98%) rename tutorial-playback-audio-visualization.md => markdown/tutorials/playback/audio-visualization.md (95%) rename tutorial-playback-color-balance.md => markdown/tutorials/playback/color-balance.md (96%) rename tutorial-playback-custom-playbin-sinks.md => markdown/tutorials/playback/custom-playbin-sinks.md (95%) rename tutorial-playback-digital-audio-pass-through.md => markdown/tutorials/playback/digital-audio-pass-through.md (97%) rename tutorial-playback-hardware-accelerated-video-decoding.md => markdown/tutorials/playback/hardware-accelerated-video-decoding.md (100%) rename tutorials-playback.md => markdown/tutorials/playback/index.md (100%) rename tutorial-playback-playbin-usage.md => markdown/tutorials/playback/playbin-usage.md (98%) rename tutorial-playback-progressive-streaming.md => markdown/tutorials/playback/progressive-streaming.md (95%) rename tutorial-playback-short-cutting-the-pipeline.md => markdown/tutorials/playback/short-cutting-the-pipeline.md (95%) rename tutorial-playback-subtitle-management.md => markdown/tutorials/playback/subtitle-management.md (98%) rename tutorial-qt-tutorials.md => markdown/tutorials/qt-tutorials.md (80%) rename table-of-concepts.md => markdown/tutorials/table-of-concepts.md (62%) rename {extra_theme => theme/extra}/images/favicon.png (100%) rename {extra_theme => theme/extra}/images/gstreamer-logo.svg (100%) rename {extra_theme => theme/extra}/templates/extra_head.html (100%) rename {extra_theme => theme/extra}/templates/navbar.html (100%) rename hotdoc_bootstrap_theme => theme/hotdoc_bootstrap_theme (100%) rename {less => theme/less}/variables.less (100%) delete mode 100644 tutorials/android-tutorial-5/jni/Application.mk delete mode 100644 tutorials/xcode iOS/Tutorial 5/AppDelegate.m delete mode 100644 tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings delete mode 100644 tutorials/xcode iOS/Tutorial 5/fonts.conf diff --git a/.gitmodules b/.gitmodules index 7eb6e16..a31c07d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "hotdoc_bootstrap_theme"] - path = hotdoc_bootstrap_theme + path = theme/hotdoc_bootstrap_theme url = git@github.com:hotdoc/hotdoc_bootstrap_theme.git diff --git a/Makefile b/Makefile index d72be1b..04c0487 100644 --- a/Makefile +++ b/Makefile @@ -26,18 +26,18 @@ gst_docs_HOTDOC_FLAGS = \ --conf-file hotdoc.json \ $(NULL) -theme.stamp: less/variables.less - +make -C hotdoc_bootstrap_theme LESS_INCLUDE_PATH=$$PWD/less +theme/theme.stamp: theme/less/variables.less + +make -C theme/hotdoc_bootstrap_theme LESS_INCLUDE_PATH=$$PWD/theme/less @rm -rf hotdoc-private* - @touch theme.stamp + @touch theme/theme.stamp clean_theme: - rm -f theme.stamp - +make -C hotdoc_bootstrap_theme clean + rm -f theme/theme.stamp + +make -C theme/hotdoc_bootstrap_theme clean clean: clean_theme -gst_docs_HOTDOC_EXTRA_DEPS = theme.stamp +gst_docs_HOTDOC_EXTRA_DEPS = theme/theme.stamp .PHONY: all install clean diff --git a/TODO.md b/TODO.md index 909e747..8f6439e 100644 --- a/TODO.md +++ b/TODO.md @@ -5,10 +5,10 @@ gstreamer.com content to hotdoc Pages to review: - [installing] - - installing-on-windows.md + - installing/on-windows.md For-later pages: - - tutorial-qt-tutorials.md [tpm: this should all be rewritten from scratch with qmlglsink; QtGStreamer is outdated and unmaintained, we should not promote it] + - tutorials/qt-tutorials.md [tpm: this should all be rewritten from scratch with qmlglsink; QtGStreamer is outdated and unmaintained, we should not promote it] - basic-media-player.md - qt-gstreamer-vs-c-gstreamer.md - using-appsink-appsrc-in-qt.md diff --git a/attachments/filter-element-multi.png b/attachments/filter-element-multi.png deleted file mode 100644 index dfbbcb1e8110a662ea7759fa862d62ff7226d399..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4383 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 diff --git a/attachments/filter-element.png b/attachments/filter-element.png deleted file mode 100644 index 7e2ea32605a3f4021fdac9c44a0e8014cb3f764c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2718 zcma);cQ73K7RMKfAlfBC2%=stB1CVi1*@}&9(`@JT|^fVC3?AP5E~`j8$CqtVzpJ4 zM7ioN8+EZO(N=kTXWoBr-n;KNbAD$|`Qx0KGoSe;ni}ge&~efM000J%p0+vJ7n04L zhMN4_o@L_5?nZzn$byFaB52$a$T2NU&nAG}Klis$Xo?hukdyZUpI8Ti{X7DLo&DVb z!NI`~p}t-LuFf#`hkpK$!hID^0Dz7Qq^)5QQiNZQf@S^W?j;0I%lOQc_Y_u0NYq>k znI6tLnR3&-;crb;dLh4TIv=Fe1?OtvHg4&_UnmBHedXJ-_=e^iwxzTWs&}1Uujyaj z)DqV-Ft9t15xmTigHBg~iZ9JX9&K?zPvei(>aGh^FlQSfC!peu?V~LjqZt5YG;`s~ zS$5>DLWOD1Asml(0<7E``_|0O^(r;4+E$G#MuX{<@r(?5gvI$kc+HTOIl^EuK#8#n1rTe!oHR~!^{k{g6CcA6VEy*NT+*u)cc zeuOj0P}F-2z7|RURk-Z2173A1_R6!2%Bvt0l{caOK>KG;VJLjv_hri&)zXSavHerf z(*ppYCWzgnwn~thMl_t#1v{+Y;$-wVpa~t_J%=YDl&Nw^X+%`~JL{S8>^zV4lQ;8G zf80X=0qTgwp^3{Ev6=!6c;Hvm=(Em}jl_h+z5?HpIs5?Z&zmO^v%SPPTy;BSV#|jl z2bB6wq*4Rcq^%4aiVEjQx!#VKDZaW4zkmLTN;mIKZki+8qy(m_kr?VbK)U#Wu^Z7d zQaO+svQs)Uz-g#B0?9Mpa3U=2z8TSJpJGvB?vq3-I%UKkY7 zzjLbx>9q(f?H(C<47AmE_Wdg-Y+qCAGCz1LQ2b93fsy+|pX01@Ewasu5Pego8ShBD zhm7ZvA%;57`5Q<5A0aud&CTS_IbNkM0>2N=1%vYok)s`(YsAwKPrOwasS6O;)@fnM zyFMh@rDg9;&m@UReR7=gYmQWlw-UE_5g3KU^MbSUCi)cz0cFb6>{$hFrJeISxNd>6 zF{;)jHM#xM{Lkr2qpHaeih56DT7#(8X!$Be!aUVofG6it6iIwvwJRmx{^41%1j|l= zGJ!zSQo?1(rv!Ztc^=HLOA%infAC6B&WtC|*r8yZ4$3d1|w(z?Nr{QvZNd5*| zcR{(5lrO^Bne(yIEQO{zF07+^-kSFkjYI_gqlg3uM18wT-)Z-plzs^I9zltGdJ>+J zP^J1ZDF_nPG{ljo*1`mEz`T8K)kLJMZr7eJESj=xFpaADrFa5@4p!R36j`)6s7lqP2^3V2$Z6$;?Ba zo+>06(3Pr8p9VH5m#X&Pb^Tlcw$5h9OZCrAFHOAn(+gsbRr;qLgi9Mf2qOKpoPWCq z%2OlwL(}4R>4f)BBC*6LGR>4;{Hr#Pa;EnT5FZ0a802^gfbgCR#PBpqXY?pbbfh_h z1L)6Rg(_F5@DO&9*%JNq7W9~lLN7($w7}I_$59$Y+puoyH(!ZLl1FABoco!}%BrGh zAgj!&#}rqsyElU7h6x7XX;vEO)H)#x;f!^w%jw+|#q0B64JC>w0^a!~jF?z9H6Q>z@#9S&x{Q{PpQdila3B8nip^+GA0l8?OD zMKts7O3e^PDI8<3m6Dc|OxGqnhWf5*e`+Sn#X1T+~QGwp? z%Vl9we~w*PP2=cFBafpnH7`~o>c6!Az0pV2O?a@u-;D1z#C9^-#|gGU8M5C8xKdB( zq-TYCtb4wST*1`Oaa(y`VVI*%NpM3rwQtYEWV;IY-w~N1X!ke9&p4$6GqomT_)@!c zm26~Y^bvC=xM(mYMd0DUj{ApL8HQ^ZjhDa5_4%ix(y=&APQS>n$jBpN$WHfmNW?%9 zjQ)?P$z~@V;Q;+3`;*2P-paWdvTaze}h^}hn|~TNQ$+Yc%B`lCBtzU=LGc3-u=}o6YGY{qxzV0 zMtM+$wG!!#C!WYc50xn*)^~r5o|rLlI@lV@3EZGA>$ShRRzVV zyGkl84;$>h-4#q2-VI_x<9XWGf=G%7Ws~0yxW6aob|+LTSI(U3_q&*2OCnU;#$?)pBC^N40XtNpNaQV^HvHQ3uqo! z`{wT8466=<{|6rblaBwrcy3`pIkA7c4*Ed5T%lvR+?Hj^L~^u$VZD#9FHx)){kMW~ z4l`przbSv0@{pL@WyWJ*r~_%Yg@O6bbArb!$l|89AZ)gqSnG|^)>dd=u8zbx{9DQ3 z92(Kkf{J%d9U<7WmOp*&E8fbN9Z!+HoSqA1$GQ|%K2xF?P4@0Q|GK=fXs+WzMRP;b zJ8Tnt%HEx6NYaCe`|llPmMU-N5N z4XmzJa_jin``jpHMJZ$i0t5&M2xJ*)@y`$tPR|5bVeI?`!o$OZ$;#fw#njmG3zLJh zMb@bR0R#jYgp9a|nrHU$nwKxu&CC78!q{<&0+$CIS`x&EY>}^o@3Bw?lrPHXDY(t%%}mY>oyz@+U9^!la!G;6inSED;eET@OOAIuSzb--D*?7^oj1>>a*#s>ea_*lNI_ zN()a##InmL+ZD}S42oUV*J>58&Q*81h4!ICTs{^j?KI{!`osUXN~boyO~`=~!du6^ zvpq-_4&fM&y!*o_Au~NPv_H{rca!s70&k3u=B*I-15j^8$DcUPy>4HR(m9RKWsd&$ zCMERvA1VL0bS`Rv5Z1O@X4F^k7l1h>Dv(Y%0tTpT9Do1ROJN z-D}Sdp^VBmkXiLqT6qP*!XTU+^fIGWU;Pbvg!0J(OCW)phIDr{*N>j8T@CqSU{>y!mki|TzIx#Y+z(P;4BjXRb-h-+ z4TQw>LQVg?NMbcBqI}2VaG`M;;5}8>RRj{?cHqpjqbo7gVAGJ}c)~!ExW8d1b#f%S zIO+}<>&CI|VNt-qv>g+4FcbJr!~c6|f%KkP{U+D`|2Cg;Qxq0?O#3cdhCG2M1tI@G zgsa{Ut@k!>=`ApZWUEEDe*m3NcY}K)0$%t$z@CcF4+}zzSi-yk&nZe}4wsNDWi)9L z0S|oLT~{VJFS|!PCZO6sjO!zhcG!cD&CANl_g4vj>aWi{&Zlb}B83eNmZa4?2?MvL ztquI%uJ&&cIxYrvy>@a(y>9NfoyH#|KDm~!OBv`bGx}lt=WbhS?s^jI3zI_h28K?c z;|5QsS3U^eAQm6GLwsJI_8B{UpH0hbcrFP04l|^L?n_!UV!oz|j`-ti3a-=2ScklH zqwTsh;W*(5S-I$%mO3jeJnD3X4dZ!vQ}y`W*OZ+{0rjQBk{aF z(u%H*bCro5X!OVStiH;mT^^&cOf7dg%!=Dl0n83pdj8#Nr|mD#_uCy^WdhHgywAsF zVY8f%TDl#1P5n8L$;rX9LmSi2&`Di^gBfykH!UUOXJ%5)#YbpIFWr)-E^ z0`toq-?*90oK=|Q7S8hXmnPGVUs~NJc(UW?Qz{Uh*|%mU%!{eq7uVOgb3v_}yuKaY zxG8QV(FpZFzfACa*0*Cv$5kR8xvqoq+Ad`Lc3f4|QIB2%lFYlN7(hB11db0&$IS<5 zRq15WI_OW#XGSv{vgS&9Km>}wBJX9go4yw_q`T#`Goe3FY3dw~uiSZ2!t1POu$JXmqKN-pH${l8cR}Vzgn05#79W1)Q}p~x z!=kQPOmjv^qmw(k;59hMRZvDfyZ%LUTcO~;CyGxVeGW|AX(VlKyQyhycNcG<} z;yx51Q}De;XnB)^sf<}m4Hl?3H#h0UOEYW#bD?kKXFj&XZ0rp~BO`sA zj@PcZ{|c#nr@twhfZ*J_b8S89*Dvwu>FKuJ#j>(83Q9^yWkbV+$-Sd#A*li@oN!d) z3HAV=)CAmsu@KakAnk?;i-GHmA4Nrp85y)U`2QkT?0iwf=HsLHdiEU*avbv7d{E;o z#~%Z)8x^S7%uE8D4t~;vg_%vRm&aR+TM69cZ{I?#GS$@8FHU{VHm*E~%yxE=HVP2U zJ?MHM;NC-d`jHgpvFBLLOl%gV8SJ2>s1|vuhno(A-Ue26u)E7wH_yc+-Z%K9rhC%k!BQC$@9_G)Hs zo|K)vTIBveIi9o;8A0rz3>7xo?m3bAD*GE}xhHtqN>KJ@^aN%Llv|^Gr;~N1qLvU* zS9`n}<*j5?SC^5O|5y^hG}n}3cc-FW|8#wFeX&w_#22SThk5yRGbnYJt?K!;7#{1$Q z6S->2qTkh7nWCcLa40~_yOKLE3PqRyW}7;`K(RoG5S!(kS7B)l+V8^t zXx-V8%iwb(7#&U9|B9P`|ZK~eNIfj{LHTttAPUT z`w5TJ;sO)l0N;D#R3_a%PEEsz!R-%%g8K85|2(&($P|GEX@-KFk^a%_c;q#)=B&l9 zi4y;}!F)alM-6-Cn5UK1WRf)7N?9FyM$OU#w}G?4sqr|pfTq;i2h@tix2(=xaD!h~ zMl0~RpQqK}&Kcl+j83JLIo6MB7`<{r^}mNj7Q%&pv|UjZOXmMQqmSOH77Q90>h+VB zuf1{AjMr8ONz2)76934CAxZ=V{rIJgW@tPz6(`$hFtwKjiKFVvf>=G&ALB{a(#}e; zh(RG5!l}!jMA_+<4z21ON5=0?&P?$n89aF&(P-7&k)( z3K~3LN#D%Ybsa8a3}3S=YPwQ~lc}~{`D7FnQf}Bo(YDZl^5A*v0QKJN#QtMjwp!G7 zAsvEg`0aKYxGhozdP#6CM^U%dmLFB9JH1m~L2wP*iNKN1)_1dD>Um?7U8Xj#b$P=S zkwxb;i!lKOf$p2wWYaiGFiOJ_CtjVTnneE(N=%b?2;o!y$l+GOQA?*n`lCjrXchgI z+&w(DB_Uwi_hSBi#wkBtYPJeu%&%rumFhh&q*h(G$B{_%KAD(&WJ){QZz2(ebAq|I zy)x*!=n1&E7eylZ+Pi4{GAu85d|)4CP`-p|CMQFA)S~G)F35cO)XuzncqMh?+7f@b zP7U4zpZUd)m$U9x`i7$(hm5;lM>&P^e6#9XAAy<2KHJN4sM$?!YWD(KzQhb~6aN|# z)xaQpL1U??+zv5*>SgoMfH6=A%FHkEsI!$N2$1ctQ7IjxlW1enKEr2NTvPhG0~_6m z1ypd!k;EU_6PYi1T6ntQhK#o96$1{_4;$4w;~`V|l<$+I9YFI4Mk8}nBZ zX=++p_>vi~*;lv^zYa#W5iee()_adoohH*Jb_e7J-FS%9BdhPt?BIocwgmle)52m& z6U7X=XLCW&@zdu$c9T%qddet{nzKH+hVSY(i34k<%$rJ; zWOLSOG1x^&ThV0}8)ur^datnbDhGb*ks`w*9<^!G;ZNyRo=r8{{d)JKytI6N8JALr z8e@t)^rP{+UI?LX)SAf<;SFj$gsltj($Zxqa}6pb!3U1LNxnS8mqXl2olb+{UWoWqXSu5=w4&xO8b7mZWo^ernEvY>Oc7^kWZv=MyMz!!ex41U zeO`#H@%f(+Vybo8jA)}|r5D?!7ppHO$Sb2^(fd6FC@5qn7` z52mU086rTl1)MU1IZp>2b&q@`C{a zJzK*!w5{0Y!piV#Gitx-WW_@#Zrhc~v%IJM$Q9qVu5ZHK^_98_y6Ss>s1q2!FU>SG znE5rA#YW^Bt`_?7Xovr?aQZ$Uw?cS)P~B)FrOgNdg1zBA81%pHr}S+zR(ihZ3^4dK z+_i0}_aN>6G6rkAuD*0|f;!7}l{|=p1}7QcRcEX{xoI--CqqS*D)vZ*BF&D9cr$Xtnn)fu?tmT(h8i&9ld6^*> zc)d6EeX%jz)AjJpdVP7?cK%7>^C6UHJB%F0eP#GfUrS|XEQym+YR!B*{1#w-M_4-eNt`Q5?2s3Q8DubUy8~h6-sw$MaP^rjW#S zxx(%&rx$-`=L(_OX7tI$q>QV65_={KkBW#+T1*FE*9dhPX;?)~jZ3z)_x7~)R2pN% zIVc+3u1IS=EXb~c!B&|Rlt20MdX=$l=lAP$59tb8QkNq^4If}FSWwoa1ZjE>#?WXL z8orkjAXIUZF^YBRM31iMUbGi|T{UkCd3V-z$8`0la~QX}J=bCNRRJ)M5@9HyvK2f+ zY#2NbTQc=-BNWZ%AQgV9!t{@AA?ZE|B^Aro1L{O9iC*vDXl3&m1rV`|qMlUYR=Y+L9K{>(r+(U04IuWk*st|rDhW;S?u~8q3Jb)7HuqhF z+R;QKOZWDwsD`cf+F~ZGubvB;8I4_yg_*MT;Cc$M`O~}2=m8`H26bqIa6#cii4pL%&tW0dKv zh?{`~K*`J7q$=O$I-(Y4X?u4%4?W?OXMZc=u85a81%a1kgb`E@WsV=D4JF8ewpo%b zc^2UN*eXhOo@1PeJdRMH$N0nQ(7~9Mu=pIZkY&<7JiTdLEETgonp3zOVQ-`I&jYU7W2dQ9 zZ1kxS=f@J^MomrC-_#55PR~AoycLs{>o?oK@`rh8Bzkgmv9l(=(Tv)~B5rHTYRdol zF$1;LS_54|>~RY<{9$e;rga-p)$3||ypn!hN>cVCxXXAMJ!TE8tuwY<<@57s0RIOi zwd*Sgi~1KUYGSbEfGD@CtDvY>!uKO|SA8JVSPW?P*sFdc&a)fQpQxrrt|H_z@c{6@y%1J#6I4)$_a2QyIgr{)RIw)mG8AAh>b~~r2fAwL7 z8&1O2zT2J6#R6MJdoRBGH3!_;s~gku7w$}szPw)uc6;8R^4O}WpGp$CSGn&y zW@P}^M&Pa+%oLLXwb91tUFSQ5RrebTVEtE}5nyZfSnH{1;^*rN=wpV8T_7;9xEjr) zzut&@lvQ7SC!}gIV9j;V7xm?!)o z^rqb!gue~LUQd?gLu%-_s9Y2_>Y)tYfg&p)^u4jDsdrtoujcWf0Ku4F>{R4kZU_qr znFI*y8;+PVGXn6FUf0|1RjcnGxYhM}V@=YUW$d@ta1bA&rtMxtK&DaycMmddLeVhc z#wqx%2J}H?^4Wtjq3a%gLC-PuJ#I-PlLbqG*bkGK*^H`~*|O5_=@$$z(NQLu7j7&p zDT^bxRdS~iF_rw>0@5n8mJpDZ<4nNBE&H42H9mKkJeM(=4e0YB}&fDWMLbXr;hw#Jl!-b!@-wSgGPXHsh^NV>$ z)xkE5)13nQRzk~h`7c~Jmp$Cc&0sAmGXQZ0Ki&i^eg5pWcsL0l;uo11{yqyuV|d(n zfy0GY@r!S7eytfsG=0JWe&jd`yY=|wo*ND^i@HnRCii_SHjwvMO4S1xquC`TJP+gS zq~}c))Z4Y%o;zVmt(P4ts~%5b5yYl*f1LkT&P#@Rq}|?v6wJv!B>pj5YwEFh+2e=~ zHO8ywM6dTR^pNR-Zg>m6XI>u@=X*{rG*g`>7K5HIb#b9sY_`yRgU|qde0hF(heYso zg7oa?W#pNzYt3fJVu%*C0t|i+^C7sYH%ZcyPv}yKJhuMws9`zEruZX?iI=m;z_r{ zAb!Ns4?=C&6%cCPYQfLh<#g{CZu2XFLQ?OwZjfBjm~BQp>JQEVvEfBW&*9`ObMe`v zU>L@=hgD%ptVb7oA23g3`@lDbU;>#ET`nmM>toxxQ2#~l{*17O-Q#p_)%hyzM;FjX zw?)xUO?Y7W+O`+aQL$cm9vK?R2RgL*_{Hw6!GCgt?S9@`3?R+qgfb)Nb9@mEb21 z&t;v@!@Q=j7YhrTzgnDpLcX2WI5ZggykL9vqSp=U%zVHWpHhzBXc|B;wI8j?@(WgF!P3TZy!P6-kvCA}fJzP;F?&eINLKe)-QNhBR`(^I3Rm)Ga)EQ%u`$BJ#CzuOvhI5;0JzcwDU-b@Ol=w|#qRF>~KlPcL-Z{8Nf0X}}v;Ga%>A8xI zMC&Qs*oc=RB%g*3Ck8tC_AW~N8g$FsmnEfAU}&$upn?TeK@O>D!ls}QC-8Eus>Oiw zdUonFG%+FM?F0B>{P4G_haV+8US~5WwqVuq>jv2V8iU($dC3_y4Lhd2%KR$Lb77$4 zT#Rz^0mP>3uFhtz6#yZ7J2&>s=)3jpvO3cK_!)b97|5|diZUEk;@ zi2H%;2MzF!TqgoO-$D@1Rg;LmsdM}yg$+jkTkdMtjcF+6VFApBu7_rS02e@=5;+N` zW((0ipB0YZKj(Xr)q5{5Z3_OMS%51805xO2U3(nYPjhQM)8|&$tIjIEde*J*dThcT z6YSnE?cbET>}g@%oJvb|d}4kD8J@P^Mhcf~?HpddALYtQndGjvc{0md`eAbS?KZbW z;ToU#u;!Y+9}5JAYReDo*Cp(S@nmm_7=B7UQ) zUzdhpI*k?dcy;(h2qe3q$!^}KeLH%D$&R`tQn0&_Mnzc3TSN9S60Rx=f%9C!66QvO z!frNq9l*+wW6l4?oR0I>jh|f1<2Q;t<}VYtHJ!GLwig?ZAkO^Ss>ZpvC-EmW{cjNh z{QRIb4Oub)>d*HTjkIdLAE?5Uj9Q#`D^)r!HmQK(+Oc;>R87Lzg@GlLw<{26sssGL z;DbBes5T>eXWq0G-zs{w4w-t4o+$n{<#Gwwb(BdiKFj zj=ALV5QU6_=PEy31=#b!!Q+@*6^OHP7>>cf!@{nkzK$xqiu$6S9q=!CAuPzQbC zxJ($-H(wvl!tm=ai|7c?xK)e2_lZ!_N=^kwFypxZ*E|zX-x|1o7W{OUJ`NxQGz4bP z$8F>j8&rz9K#|3iAqbnW;BpPHpyX)y7o#|5^<>)82cI+q(? zuhAg8Hx?4z@p)5-#8Dr%Ef;^rfp(>Sd#0De_;w$n#nlYy8r4!b}&kSI$~^Jxk4aK0J{4Tl>~(GnUdl-#1_3bAK!enb-MJM9F5X#>D-6E`bE1 z5bPfYfTVX>H|O9B^tFwPv^3{4%(JA7Eefou3<17`pACFniyXi_gpWh_SK+SO^u2Yx zu>Jz4J>f^J~iL-LH1No43~>R2UJpK<6y+9lmV zB@*30kbOQtskayi<$9zw!SHkIv85XE^f~0d1j4>H!?ll#(p0(}?QT={>>DrWyW(WI zlNj9+2Y?D_vt4e1UHtZ7-osU5HhWE~3hmmbmG32&h_JyMaPv}2cmmQRnut(?CX zX8>&<{OxTEWND>aa%wi3;n}XGJSN>yrcAA_jGJ5aItN~~vijKvcFsD`Yjko+_0;Gw z|LZ_lGUCILpQeXyJG7<%91#euj6J2iyi)IH_Q(j7@9t>JRE|zVQEQ%Ng7L8GK@(g_O^(#3v%I}|(((2z718}x> z_*~gS#LA+l%g(gH@|tP!6*Rw@8*ISvfZ^oIllu&Og(yr$h`@5b(+2~TRbk2EKdy>L zb-3Ii=Lb#n`+pRYC{fsZynhT&q&+!g_&)}vU`0CcAKw|e&xK+1e+Hi7{(nE!f@Oxo z(z^Wcz#i^{B6(`=X&|rwr&{S>Jx8c6Z>nc^0FNREt~BfNS_7cIgDL-g$NN>FJACB0C-_G{OB_UQy(^!AxX!K8lb5H?8?3WxA$UPyr{J-BcC?H!7mfB=<)7UtFAr#)-v~M&0yI2#aNCDz|HIx@KP)Nb|*i*?tP zdcO+5pbnqS-?_6@={97vEyH{apPJFP(xf4RG+I3G-9a8Z*jy)SSEuLtJ-c&yVDB1J zU;jC{7a{}(8!bxQ)1y~lS=ikkzA-vC3gd`8gZ z(HD;crf^i!sB!bNYgWN7mMl4&bdA}kE~x+PkY|^sJa{x^ab}Ij97SqR>0_HoZ-H>2 zj);K)Q(^Q(->xj^Kw3ogB(%>yc+(OB9f@-j5qoCC>LZ^00LKkz`LjAbiY^`S3Ez}b z=QB*TYFP5V=}wTC@oq!RG4Z%Qozy;}%)3ey|A@Zsb7$v%vMMX-&F3)gLo5-L2nu)E zM&>r!hXMG3mX)~4J!*dbtmh8BReRK<1;2sfI6_BmZj+X!`|}WJJcNzcx&^K0_YV}5Zua+T z<)gqnNkYf*4(79Bd)j~AAkM71pccDeh#yc{jziSUaopUfMV1)8mKk2$dhRK}!NsYp ze^OlBoV5IiyvX403(34afNZgIUYA}RG#!Q%j%E>kvJ#!aVo#*ojMd;gPGH}DgY(fl z)QGHyJVAK4>*dLjkKsq#^wv`-IiJmZ)t8yns#RZ5Q)#9w1yS+OVTI41G59@fw~w7L zR|IocaDVOEjtAb#xYc(L{4Yi+R_^=~m{tv!3W3+9Ypb4`)l)Jx6`Xq#oSn5TDK{6! z85ecW`>?YcYdW-Xl`dq5mvQiuCVJ%gj`W=i?02KgVl$RdOR0lgjOx~76FNG286_DB zZdcKKv;gldW;IRCq@n{Ef^lU3f(KI3SQQ!~#^G+Fnv zW0oGRT4z*TB_io^dIGcSQE4;v3rM7y;|u(QHqrm4Mheno+>njmUSAl%^+{0b*rl10 z-N&MrE(2^lZ@$G!B$9cRB9@sqrFOJ5M!_HDOrzMfOiiJ(xa^I#2W~jHxj(CMq)u7n zC@3m2?fTrYdHyDIhTZut_3`PT8c|<1Ub=-j9lHzCi=7r5&8Fu{c ztd+HaZEfDs(E|es`r2pYoWnSI(Ok^@8OZI{c>Ik@zFGeGQO8y8cjXXb{#k$1P-h&5 zeh@#u&G`j1t~fhxv6VZ(e11^GEozs$-xJQ;JTiPhz@6X|#_32iB0vwv#!)uZlnVxl zh%Zc$^PMs4gvz>VZ~<)KxOvR_G1oB{zk54!)>^!vd&AO+S#e2igBf?Y@po;G%uK@V zL2zqD=3IZ(jT+P=MMKT90?#Vnm9Dw$JM|l4g&jxhB*4%`;iisg>b`#`95ACtC^jxA z?+lPt`OwyPbaQ#v{T8;;_51|`6BGWupKseUrYq=sem=Z}N}Wy>5+NU!{=!m22~yr< zLOC7KpjK)SYGh$o%tgc*`IF0%EmGdD2&UP?|~eKWW8cAhPVI7AQeuePYAgLTYgC z|160cSD=(9v`FkOq~C?K#!^~kL&iGXUzDbYK=Y%R0vJJwNn;XA2vwf5+%Rs^uG6-= zUfiM_^>9UU2#mNQ*@oSVusG%^BX-Kue7!bxns5PaP=ad2~ab_!k# zmijj_m91Q7^qn7}0UOH|^yxr?efFBGDbCZ>IeUsRo^P8i>r6=w6xH#%z952GVYKF z;Z_(3?-yHIkbqw9%cs;BVjsdSKRMajsbf22nrwG^`+ze97PH82f0Z>V9`dfiXTDk) zLN#1EM_Sm^74j(h&IN$ax}5txC2?<04w!N-n(ddQt*wDXNgFCEGBP3u>9~lQ&UHdW zghJiqc5^*?8d81Kx@LcjLZ2T99n;?znMnSyh1&&OLjYjGO-C9H*5ejc>@u|0jT$2? zQ^-*I318Fq$r3tIc}zR*)e=l!$@+lmqk25XuYCkd79sI=A=K z*#1^!in`jv?$ueDqmhtOhCi&A&*gzHF%n160R-64Gr!xvoJ8+C(wpUXV(w267Ms*r zc063*ba}tojCGt?ys17~+oUo(?NdY(mE^_YN!;mDV>-==7)idl}46Yu`}yNK`Ak;m86)c69L z#S`~pMc#;m8FTRn*`<@Ig0uU8La|aJ6xdBiyoxzdKQX@!<|q_;Wcz?;r_aGBwXtC! z^IlxIylm7GLTMOawEdUWsPW9uq;q}E={|cc(xekB9e3D+4PE5E)LMsBe-g?RCqr94 z=M0C6&wi$9u!5R`-nUsi=r!}Ner^Mt_GdVBJ!YkE9-6K<c>-*hGNTT3!c zOtGaF9*rs{d3Z8uD3vEp4FZ*4E={yyPN%6#=-VN`G(=#+!C1Pt%=7=CC_zJsxOnVP z(@@`Zr2-gd64dbOLMsAIJt6L{b!fDj5Fuj&$!sPAY-+AeIO58Y*hgaQ4N^ISl!? zg?nka`kQD7sEucMXj}TKc;R{EkTxn(H(+x6H7)G<_Gf=A@p4*?z99S++zF9P5~wc{ za`;+Fi42Q%QDw9E$22I{nz`${qBysVlMcS&S4Civv*PslGVb#!T*@m%0+pTlFZxJB zj`df8S)EOtHkq@9Wj3Y#2l8ZiNLyFUUEB!^}%_FFaXQ4*b?1wbjmHHINy=3^Hp>4 zRV)#HQpZNxK0ogzjom<%y!RZp*RW+ssD6(eDyC0};WD>F6n^VcSJn}Ql$Nveo}My= zWP&7nU@@qya#>qS$K=|gk96AVHbO?Jp4CsB>aM%(r-H62OtJImm@i;8^`3HWuu{jJ z1V@B*OUL&>;}T>Um`{VyYZN&!Ao($o1t2hv_@dvn0X9q*rAQ5oj2tw0?e|ChFaxrn zDP(xCF~L4MF)&`VWLLUwxq*(<2!o{5UaZr`whn!8mt7xG{0 zSg;_c&rc% z@Jq80y|f5&T+OO0^6j{6*?SRwz~Ny2ALks#T9M{1nxUaylURyMlUH3c%De z9Ke96B_#3;2V7V%aF}CURMwd-KJ@)NNMWJ8gkQgYdFmEh4M4>i{Z1G+mzptw49~|@ zxmmRRjlh+KoUkJ1-aVhv*7?d({od!V`BFDHV<){?|n z3c|w6&pZ}dRK{yN9u8P7?RI39s%uzeQzS2#p8KRH-^A&g#zo$3syhL$fe?Cs_z;5kEoYI69T@$mwr?}8ubGgtFHXiMZ&+-u$rv-^?|;hV zw|*?8iXYiM@Tn0xz59(%TC+4BfMeIk!3XEdiCnTKs_4$0=~=dE6mrH42zvE!*2I+C8z?B_X`ri9>F8T5j|VO#EgfqK=*Ew>iVs3L&i^S5j7n zZ($coYQ<3si%a*49*%l+f)UMPT}Gd=pJKh8yTle%uQ&LWYCSKu1?54J*Gn zki+(sdDM|jO-$b5D3GJUeND~80e3GEQV13`HTP|!ZaXh8UoYUsZZzhl6Xalu{8w$1 zAc0vYZq~WSdz)Xz85paLfmo@jIA;7w^4+HUJc;Gc{k5sNGhE!Xi=wN`hXDy_z>h;e z?av}|0MjkU6HW9;?0i+`sOfwRA)CBY+Fd{hK;%|)zjwI0oOZU)&K*=wb~gHq0thdG zz6Z!5CWqQygB<~y3|h@6wHu-;WQ??snguz8%*3NjxLAp~TRZsy{?77)(jH6Nt@%kU znwsb1F^G863v-*zjABj8Pd~WRxY6U&_4ulRSr`Gv2 zSydNy85x5 zJ9W^fuZ`DZ_fDC9#%!N4wh{!p(4ye&Lf{R_eEX;%dC>nexG7Un>SVQ98{Ih2b*~@cjt53A+0Y3z0Y>W zGQQFiW#l>`Q!4Yl9LTb=3$^~+0z%+tCLsrQc=%x;-?@^9mTSY`caHI$5kVmBr_wqk z^s~pfCmYSw>Z%iTR&m1C)GUqy5u$mixsA5R^z66?eWhz@g}?aZ`caJGt%Ec9YqsT} zeS_oFH&Oc>_W1mV45`KTE5HoJ3{o)z%>&Z!<~2!l#i%-(eVO68;^?VvsVfP6+p3y% zA3e*5hQf(=&kAcbfd9W~7R@`H_iF)CYMHt%aQ^;1Yrz5K;|+avbu62Ny6*IYG%cg9xFuk)Sb&l_Qr3A>EBSO~zN z?dvi&DYH+i2db|x^QeopP9$!~ zJ{R7E=g=Lc(Ll%To4Ljri_ebsEp^H2W2orVT_p_yqOf;1a+cvdFDZ&L9srZ!$(=#<8db=mvh-dz_y>k)p%B2gY`P^lQ9S z*Hnn*yYZwH&|GAd)0AdL_gjmo7K+3al(!0!$cvRUR|geLnK~{O;>S4t`d(QdRbwc` zw=SH(EbeS#0|UZ^OPq}fmkRm^X9ni%x~;xle*}hyObUMQ+>-t*pu#krEMLg6|m& zup~CG#t|3w1QK++?iGB45Dqh25{)K5sj~NSuuesZKZlYV^r4e(Mka7*vh{w=tH0DY zyQAGdNZ4$2TUmt{T!Tgjn#)bcNJpNrA2KtGtzMY86PaO?XXI$tru#5+bLvPW0-^Xb z7WJkJB(k!1%33UVS>uw<&TQif3U=0-1-mQeqi?L^mKwiV;ynE%SG@*#cv!P2B;y)9paePc8a_-fu#Ay$A`>dB(?=KN zmva#{yFT~o2)sgFyx3~sT2+5MB&1_SLIh$bL|zS~n39M{VXuDh7L$ld!PP^A8}s+C zNgQ9*G$9qGn0)S1u1@)x*}iOz>-lba`0T5qZS7d`4s#Uj?>t)xVbg=B(fE}&|>4+FGdQXfM>#y#RH zSkJEz26?D8gHWGjWf63_9L)QE?Q^u4hMOh+u_i`Q*I1Lc2PS$%ZgA$}gzDL|sV|cG z{Qq@c#!T6trA>n4YF@Y8`Vv8dVI^%Co`=+$P52~^#f$YPGq9lU_Lwb2#?rrDTV0IO$v5+u13OVsq2iAI@C4~QUxJ(v0 z{=T7+-T9tRNR??`Qs0(+b0oXiWb;9S+`{E4&G3gIIA8D@9?t19BfTmEc7}qJGLF}! zdh4VGOh!qW5%lnr2NPpaRbwJ(gl^>S)Z+1*496_@XYiu5zX4Nu{?{!2z|2DeSN*}? zh1xOF;?zX(ze*B;4(?B}`Jv5GK}ND;s8Gg1rC!rV5~J%$dFz?(dOB`sUMsuYiqicq z+Svay3vk2YW!9a1i|-b}e#YGfB(>x}oxA+4cW(_I3!6?vdr*Vjh*H6rayVKzTIPde zcw!h0pfRh`e3;B)nUzMF04p(Mu33&K)d=2!MW^HR43XykF~@1v=U1Ks+odFJKAGIf zt9{ zQ0>M|nwyT9PCqNPPSj^J5S@OWh=<)!k1awCo9>k4r5Tqku({ulr;q;$m${_iu*Snx zdggyZeHp69cKDvCehnj7F4=GGX4Eu`iJviaF2c=bI-=(4Em&T@9^U$J{XRro4;^a$@O!LE4)9L&REsd764;?fLHuVVES-h#^eDeOqGBZQhL98D7^%Uc4dR3jJ0d z-ejsc9$m2Uty3hdlBP>aU7d9w`Nt1;>UYWL9Y(`a zuwRrYq3;H3hj3k04x*+9R^73`<&%(YtC2#*7P|WZdT9pTAU*u z7kLlScL~=mG&B|DALtfqK+<_pT<|Po8vIXea>Ml1R!;7UB0T6-k{=jZlNzhhX=DeV zF&Y<%h=!QR+iOR-L(0jrQPdM<xhIImwp--Q zM%R5wyf386tvjzEJFaGnh)?CN^kfxC24>+=S>9$e_tyo(78jXH={##qo90cMmdi?q zw$3-@gF{UBGknoO=1K!6x9)0ovx~t_3~`bP26-FEbR5(qTbJ46a7=I~+2!S}Yt`ZY zc$rkdw!9inC8zSzXxTSJrj6uDp* z5AF`ZB?NbO_uy{9gS$f@xD#@NySuwy+~qCbU$2UyD6Z`8oY_7zJw3B>-z?z)lN`8e zyYe~MumgJ-?UHT8-~L2uFYfMiybdJ#iv38W##qG zyCzqI12tsS}d<64aVclLh55sPIUX0Xbh@)u0 z+>Gd9BC>faM9-`VvIR+hKx}>*P(U=$Z(YGN^d!aBxPie1ZqYLOily`RDb{UApEp+Q z5EmI0ELT2o%u1}4YLqz8UYf;Bqg~4VGO>Hv>RlamQ$w;;jRlWJBXsVg2TDwc{u4cBopv|be*oQ`9XSA5Fl^1FbuM*#_ zkmq&TBLEDF{yKfJMwI_TS6#J@TElGm&?i1((2)(m^`%FO;z7EHKQ%>n(BZcCRX;zq z$%I=~I#1|rdBxmcH3vp>&@ZC3XJbKB-Q(`>NX*UQ&D~3XY;u3~9=c*;6z!+`uo(BX z=#QrQU&bM(vlsXf&e!=RQ6j`j1v3uI#P#u)E9x?XL*tis#Wd7)k*$bh#cfHl=bWya ziVAgTi^9mnRS2}%cEbLMi55;4RBW|t@dyvr#jF{MY)^SV=~{L`k+fv}qUezXb>Q@u zD9a{F)J_h#&94O%(8?rA7&)PT>XF*Q?68X5FVJ8e$TRx}M<`gKQt4Y~tHiRiuMmzu zMH49Pkh5?GW=ABJcJ)Mi^RD~cN-*eY?mnUV{3%Fy{d1$< z{sq*YAB`|dvI^))ysSPgPa{I&3G<};3-HALJkP_K zZ}oNVR$FSCH8wk~(HWB!eCaX%oqfv}8yGOWE2ff#Oh+JnR?wy^{UN$gtuU_hoVSe% zL})A1Wmg$>WHZT=`8B#@{lrgD#_i~Uw!x-=||6cp-HM( zFujH%$8!%-LDmBM9m1n(EGahORE7(6#5b>dSY zf#(|)?%oEshz0J}4On%E@mvW=y4^l-kKy?$HdW8lf3roAljA!J#TNOg;xFZ&)@PV^ z@vD6L@Zajl>WqmFD*;qkArz8BM)DERnY^rCwl>J-8jVa-T9(+xH>_nhyiQ5^;ri6Y zeP`$1k&;rr#2fhW*W9m?C!S^7(@HSIul^eS_4p;1hwq0l7xwQ9UF&D`xOsZWzD->R z6#IC4CWCvkJ* z9Rd<`*6g8TKwfLng*mdsg)U!ZLnAd`n=@$6eul6q`(I*1ciTL#^Cj!7nL|ohnGySY z+96annSWr-lV)TQ6bRnAKX+-07YW8O`H?ej(6X6jH%;nV5p~OWCd8%R!Kr@^(ch@e z35zdna6t6r$sCH0?ECr``P*rnOV?@B^~`ZJ05*h@_PMy>089&bwp>Le=+2L+1u9Wb zI%fPsB7}Ug^kY!@;+J2H z=a+~VB|>2?o^)8QnS368FTR#Vk--N!Vw89jDs|UqfeENbzbHg(6o*?(2v zku^x$kr?_mneq!)tw`H-rqJl?Nq9yC_S?7qc=N6QEgLoSTY%)=`$6&hYN}-8pjh_| z^NL$9tyqvw+(|YwxA3o(;V?bk9UM(eY@7iNTvXGOJX44&E*h|3eIW5+C~e)p^Y4)> z>=t;|pw$*q&C}whwZ5C__#JGAg%l9*NdZ@oCq$RdZ@9`;SuuI|_3DM-)x)jE{{1b- zwtLT>uT3YTg-fPXbj&f!dnlzo#*`Zh9G-8>3Pl!a7+86`iIbf_dGp74z2ZaTOm3Rw zyI#Cdi#6N;58jR&mg1ECTwc+5-dAeFldL0UJuma!-roSAwQLY>kkKc?F#r#L$6ENB5HyyEWAI(ud<`ZRw!%P z?7cW}{T80qX&$7QYVjRP$X8l_v4&d3q$sa$zPt((r~DUkes7mFc82OsqTS69-v8Pd zQQ)kWBzwiTRT~*Z1~0a3d9~@me1I-pvqKvb=*>*Bnsgzq3b9bf9WUO>IQz!7&`f=n$~8l&@exrm?!g;TvY4!7=LezIXo(&Bz>J%GIr$i(zV}Z)KlU2 zZUrO1_REW)YJu0G59`NI9A6d}S^4A&SGKI@P6uuU*E3Z{-f(Pp8y_n1SNL;yF`u?B z{`igi4L^r2AEXeC2G7SAd&nVCVN?Gh)YW}?il-}QbvkVj)%}6fKm4ZC+d;~I7D4y- zP^XS7JKW$IGFX2%3_o~~p?oh)c#NiIfuB8k`E>JFx8GpX%fm?aOm0~%8Hv{g+;{C< zMaf3|^Af_f%hK@y`m&vhXxO{~4AkxoCN&FtFRaWZZw79m2ZZzoY+b(#ks~Je*Gq75 ze@g4)@A$!i%8jUUT-FW)axF)F~dsgd_kYq-pnZ=03&(c zuA0RhDe7M~Q8l4mR?msb& zXVDXln|oZ2_z1gftL3Vx+ZTK>WhH$%wSINp$3oWyZfAI!nZ0!kKUHIyQ-Z<3Dt2lV z{zjJPU|zH57Hbv3J3 zv0wWl0{QlGJd1R2*jc|M$d)K=@R)FYGBthlQ%BXv_@Uk7Nn7o!E#F9Lr`L$jt@fk) zT?tyu!TPA?tMIxl5a)${StI3ON66e?Ew` zn8RMGyN>?wb%#AA4~5-%yL8hX&GVPa=0r5ik0KJ55aa&m(GG;duWj*5do|$$}9~B?6P&o+h zpI)Z#Pv88+wVP>QZ!T&^I%`Rjq>CWWd+stP%04;>IF;9czkaI?+!qFXc@O2TG3Hwp zN|(>>ocW!RM~lojvtaRKgQoOb=UA}`&1j}zKB|AG1%2P2xJ4~BG-y#v9pWvnnKe+a zc=QYCC=rWp=@ zyTy5Tp$QtUkH1rfdwO?dvnFC%`SXISWC}H+5+Lb^&|u=;g!({QHNX} zO%qx>0q$qt?aCA1aSzp*Sop9Siy1d_>d2Om57}`y3cFqhc!7I(^m8JCYP%E!kYcDt zFTcHX{-p03no%JEG@QfIQw`$4I_8lrh80vOc)CKx8ISQ$Jl+J5&%d5QA@>e zcvg9H!V2_DY!pRJtFceRkR6_DbhV(`@kM8VkYl)LPwoFFDoZ4w!G^U|vtnK9$k-y;* z3r1FmqhTHzc$trrtT{&W$Jk`lvQrcwfk(CC(^Uifd(YK@b;GeOKJ#JOapdPIO6l@^ zqGOT#^!~BOuCm6lLb==tM&Ay))i*nozp;=CL!se#83Nqtb_WgCNpEU;5ktT?Q_Xl5 z*`Bj`G-^op;mtHSBui<;WtJUSj%I60BOA+zuC21zqG_B_l2I8o;&-dsSdHy^LlqWlT!&W8Cu5lr(fonCY{+b z;WuB39IWN*&Ger@#iPthaj5%~nKYLJ3YcDIuQkv6$H?;d2~xhU@G!-nv6AP|NKZTA z7jspD%Gactc^qhTfRK#o=`zFC;VP$N`_`$--f7df)t06>#ckBRP9X-luxV_F$tCP_ zeUqaQJi;8N$tlIul_L`os83O?k$4G4nxvod!*fs zQoz1z9pL*b>*Frp_uW0G(}94+zauLC`@#voMO$xJLV~8#-2M;!(%qoI&T(tP*W@HU z5i8kVEeDI&f>R*qPWfiLCVTbjxGZ6Ruwep51VH$8dM~?U{NK+&*&_GYjnVPB+9zdn zl6VjG^4RvyLh(k^$)lGUF4rUXHr<~`)s&xOCODid>5ZhIYW(WL3NE#sqbdLoz5&wc z`zhteqJKXUGW<(Fp9&Pe72$n7 zuDy+F$&%^j;5@F&axo~Ks|j~}%>%)~zcoh>F1o`llPzSWfc||Y>7W&O5|n3(7z zU*ekt{QI^(!`%<-e2Iid_-E}gK|>YR?{I^nhHp4=IaOHye$79hHsD%TNdO=6x=7IK z>bQ0aR%`KeRU&!b_b7{!AK$UG&*Dwq1x6hRrn1S5+r%3TO*=5{wh52Wa4rOlp6x6? zl}s{m#QU-*zYGv z+Dtu6cc-b^)fLdPqv`_5%P)didkZcc07dvv=&T-HNCIL={r$(d9v2v*@AviveP1p| zDSJb6eM6@WfAi9ovjR{>L4Lh6jhtDHGE{MNfPsEOsI~VEfC$>UnXOxTn^9n~3^Ile z%c?%BSu{;kk+&@3XAf5#)h=WK=?_Vo153k6rCB>*(Oj?B{6k%#*4*yO=_-r0r*u^R zg`x0qU2$ML!x`4HMH#9*ii~CFI&@vlf~mZ{xL*FEbvw2if{#3!`Y_H-_^|P$Q1x*B znpDEYt7k7qFaJ+6G^^HD(oN9K++n={BDiTcsIqW(1ZI&B!H<`-Vi}P@Y669h~N_2U`#C+9DrXf`vvjlF(Rdc5!o4+-2 zR90B6))Y9x&!2RtBfOXZCkSzo^R0vz#apZP?Kxf^ zJG~7q((M*ots7mWh)T5ZdiD<{e zv%Wj!r?h2|jzQIa%&)!;ex=>STcjbF}?CMPZ2iO4*Oy4&|K-zdBbBA)w z|6PXt&DU^A_9+wL9fVrRJ^=NF5XBw;=%%aqLh4bUt)@s_mc7RJy>scu|Be%wIK=mQ zeq;>f(J+7Va-2Hu&yfX}t#6(dmdF`H)$(owQk zz!yPxqd|rN@6DyHlhC$h?SV}>nera8w(FWl(hhBLgd&hE$(xE9+!C<&OB;sy6L&54 zhu>;#IDX`P!(Ju|cs~rMI5Zw`#^3YkG46C%vWpHxh?u$SC@&6=bek+R&`FAR2N@pk zhsJc$N5@W%Fzvyqi{ke$qnHzs|2qX?%ykLi^E8tj%s+t-UlW8z@ev+RGr)6|At@rz zv^T^>7!vouA~U$Bp<(11Im+RE3M8-|Mftv}3Cxxfvd;PSQEOhk38wxJE#T14hug7>31R zdd05q4XP-^`*3}IlJL*2S@#TF@j%%R?Yu8pell9wW9!1!WP`O_Ux9!+#bzSINF9wC zOP*k0W#pibj5>M}NdLt&b!M7^>n9Vw#!N;$Dr;f^6eN$jx^(BPtZZWniBpdR^f7Jq z??fH*5*vv>bhB*aJ2OM?t1YJU-!go^I=vf?lvSkAo&B^48J{^@$>nktn^r(u*IfxG z@+}W1pn?zXFtpLPQD}Xc9DU2Lv+rbMv^Tt#e^pnA9kQDK>fPq1>g13O6XSd`;FtUA zX78u3Gs_+EklMwcQKjE~M_cdd9u^mRvt#?hvy6Mz1pXs+X>CSUfwp=ziHQVHZ*TGI zublB;Sp=!JEYx&-0Xi)5dk*v0AiTVb&hKRdA*+XW`S6zT1aj6@5S|e6r4OfHXBQ#i zQEy>c^N|DPV|ynF!au!djdoJ+esM49 zOJ2!al*xf*bR(Q8^nlYjX@;s_<%Pj{=m_$svnZ0&ChVi@=Yo08b@Jad&9DKJf)w~a zu;g@q20nk}&~S5Cmn<E|6^ei)Eu4Z1oC&O&8M=!dW95k{RcY6F`MJ?xQ`WB}d)zGkT ztd1gJoMBV5T_bo-<7R#pY#7-O?V!*#G!c7ybWk{|t<$PTC6}tQ`cR|hxPwoH-AEMFEki|oz=YLOz6uEY z`tG7sKoynx8X2N%o5OF}CH*wy^ar>3{?& zUP$kzn1(4OC6OZT=BIojo}aTPO$sI6`hIpKC43A7*>Rc%PZ4mWEv*{CF|pzF3mICn zwW7g;Ti3DhDO#%i6r^XCs&l8e=d+IjU8_Ii*+hWX{v2BKl6|Y|jM#0DVzbncmoAo? z%^>c#d-8P_jb{czRHLgLfj%TTp@)w_js%xqDgZ{u+%Ueyogd!}ykp5(@pn(qi$~9X z#(j!L;XnY`k6`m0!&UDu%T+|0rUbzitrpOK;QDMV+3C_jDrBuggCo>)cB@R5vy z;bUS|p3KJq`Z`7mI{K(8@*3z2%xReutQ3X) zC>I_YW8d7(g`RFn{;tM>_qe!(<4E{JCTize#V3|l?76?-{IYicIlK3K4syOd8#g^O zOCuX(x0$ow+?0Nery=Q%ZfU^-3TemOw)^eiG?R*YcF$`|_DlMBXgm}ebab{IGoqa{ zpSO`~tL=17E3cq>?*G>UV2K6>+OD>RH?Kb=ui+w5=KFBUU_9W%c|D|{-mi)`lQ$dx z*mU*s^`lk{9ri2o{g#)C;8&Q@p|9nzKi_HAWtS<@9Zk)gI}^{6dbZVir^))(dW?W@ z*1{AZ_Vmu9F7pqcdu}XQF*PSXW_~SX^$~OEdi6qe@NEkVx5op6=@GIAUPmzYSXQLe zzmX+LyE>%!xjsS^o=nKq`TIp51?f@VWr|#$<0tQ&mF6Qrougcm)75cD{4mARl1juf zm6QVN(1XEM0gSB)*l=|_Qi-B{!39o9tS{(OxPpVJcg)hbb1BJ)q?Ao>wx*IUTSE^C zjDrU^eEyo-G387=`O@jBM$19^+tPhjzd3dKisOVIc--c+<#dq(S0_5x zhbi)po3>K1Bz^DW2dm%XuJGwYv6N0aRSb+!s?XP?d>>X6n@&b{mL1YC(b1z;H_cae z=w@bk2M6fHQ_T|9yp{ET_S)2pZ|B3=+xL2GjV$Wff23zpNS)P+&rQ+cF?Ixd+UE#{ zpmweQO^F}f1}eH7wVFiepZZIS5&o95rrW)zSF1I1NkB>#@`>($!KIs+(i&Uj>~j4B zz*yIPq;GX!BAddXkX*`hloIe9U@13Rjk8^QbH@Z&5DR}F^iQJIE>NXvZ)qhg5B!q+ zK(lg-jcmt}>_?C9N^@OqI~FImDG8Lyrpl(}hlQ>?9uEuizVU18h@&@@vF*7nOyjCw z_5N(a#3wZ#Axo{d!)uwGZ}S5vURqll(h|ZGXNu=dTT?+n&mPo%)*89eAqK>tk)T$y zla*X)NezG|$sdT~9!R64%yy02;cd%^E`p-S1Jm*2}H)0tK zAmKi6Bf!AeDl4n7xC{JHVZ+!Jx4OnDc~}Mv_X=CxEUInENMuh}Hh~DQle=iSC{dHe z=o1m_6A8t(;l9|qQo4US4|S1OF(v7+M*>LGy|hvM6Fzl$Ewk+IN-9@nAn$vbZe#Tp z;fB45x$VHS?Hmu^oCpZeQ8d;V~j4eCZTCVK&8)oaO-9W-PU72^&e& zJGnp6ht<3LCAr(0@}b<5^*}&VB`CPmrwh)FF2n?l&3uDLChs<-ju?6zf+XE_W7@0 z?C(&7s6>5#itYB8ojh$0Hu)k#_c%IGaFGI7Ay$}QJ6E6WJr?ll6<$^Q^Z*)7y&QJhKK z^efuD5efF_JAU!GJHIy>f4WkBkDWy=rAiT4kA^uG@7Is=+0xbd<_RS%12(k%3${=M$r|3N?Q8AD~3qxPAG$a#D z)wTYbux+<{e_&+hXY;eDI|Ajxqt0R$&7!C$AH=f#L+u(8cKAWoknsFW4lG3B zv~^i^{ii3@?7XJAr~*$N4j?3ymcu0n1;c+PP{vBvPD(k-@Md=&`ptE{X^F&Vxe&K{ zmd#D^nJE^T(4E!jFT6j=ulFnlzW)FVGOW5O1R1O+^@ixsv)l0dzIyq$j=ZZZzKCyp zLW?!Z_9RJm;i(l~K~ui4)OLtZ?6B_(=gNi?@y(LTvA4hmU){+-n_&#epW4OvIQy+g^e%E4U*V@0wiwc5mMt#olw$4Tu{-cM=+7$8_m zK+nrJ+-yrGT!Tg#5f?}PnJGQ85H=w}PtjdJl%?ed;Ri3-pdosWU|5u$VV1Q2@)sZ> zOh+L#@1Zj~35JOCyyKq#Gq#l=#=|JFCK~BFOu$iv_FUEK-^{ny zAC)y3puF#Ti}l@qxYe4u-Q>tWaV2k%3HJ0z0n_mr9*y43FUCKW|K4QRSMsJWZFlj# zV7hPG@3K&$D9(KPNt69(il#?Dcv-twHW(f(ric?jG#@o72C?O|TTb7Wv7Jqb^sg~i|JR^hDk znA*5NtgPy?goo?4AD+{a4fYV9&y@A;`x9ng9KM*fHTj?{!oR-Wtjnr3#nR}%L5VIe zUmMZ^llW`C-#KV;)4;WAeML~flUUdCr)a2bmdrEkpNEDaM2J-E(dxpCU!GNdToBph z)MksL_o%4G8(Z=<)x+Da`JRz-1vdO!XoK(j;&YvGOM}Af5BbHd3!aq^qH=X`C43*C zx=a8~&I*qS+Mw}(JVcZIDrj?rsE++|aGXVI7U&mt-QJ3Zdz>nyL?A-JHTnb@0u49O zY(dmrr9ECGOA(LA9EXF83xc{^|JQ%jwa?vb(0}9>4v&bO*ESa=HXDrFQ%qxD(br8uBK>QnZX0+B29LygR35bK2v_zhpWWd z`oV*y}9w=iW{HR?7k~Vt1g6)I3&*<4-B}=Dktw#y!>aO4sZFt>| zVukgGrWz0T&-JW);9Q2jwJ~RttdhUzVZS@a`QZd)-)|H~-;5s-o^q(wcHg$FO4Lml zdM}1En7~$EgfuL0SY~;&AE}Y9=Z{SBZWu39sYlBi9Elr_SGQm;5Bs#?-q+FG6`0T@3#oGKv^FE_!I&%gxi zk>@K=O28l&5r^O*BR@4KWojN0TYYqtQw4!BqzZF3@OkNeCJEDl}bOdZiVYAc0?D8>X8RcZUy^mWCn zF{um{U1_iG8yQA^@%`acme#NrZ1co3IOzEZ9AsV(+`<>xaER)Rs>PlgrMeI=)2a|`V>E)qOMs+wA7%Eq} z>+`Ma;(U?huWX9ueB-?~P@~CS>}zJYtp%hCF`|6Gvb-VBICxmKQd_PH)NN6?7mIJM zBM<=vND*MFWJKfIg=|}aZ=%*|WadbbX2#vL701N?!U+#Z2>-z`)cGza{`koukmKZ6 zaPKbu%8SShfu)r{ryjp(+plhMb<;Xwjcp*JqO2TCxrz9J5r>~nmW|Os#dYXuaGZgh zi7GuJf^0>R8z(wD>qO4s4P}wPy;-qTv{GZjS{?kV5gNltQ$gT37N_}+(;;f}caoc>yolg%hIGC21zGu_5Kt<{GqTa!P8dr%V8g$k}A-l7$`3b77 zfDCd{MT)+Xfj3!2Leh+?m#Q~eQys$?X>SdIJ8RnHy|4nkIpcZ;A)czDfgM|7C;d%D z1G$derAq=&@9*`=V72+|nrh!&E#LMla|dPeo@8}3Zp zT7JISpioSa|KwoIsqCZmZDfu|hGWQJ%GEK4{bTD=pn*(#nc&~{Lj>7A9xiEjrBRnN zDmr?zcmGYq-Cbx=>w$>RH2_FY&;QJ7>M3T+_5k6%tX?8zWJQHHa|U~klF&m!rbF9x z$kRfD6^&>hBs2`HvQc$mQ(w^Xp+dA+qOvJMwUqhmz5$!Xndu`cft;8aZUH&S@5=l= zP6?X0J9LI^dl2mmi;|Ti)+;J#rnE>Bxnld*n%(l}~H|&v$hEryyEJrJ@3IfPk zft$fIjx`T}1_}1=%~rTk8rr=zY$WziAjzA@$Wz0gp~>OjLo$)c4XMvz5U)`Ic$KS0 zFH4QcewI@O>$E%^sF*&^sy*$XRC^Y4WjVZNMY+9BvvkwchO9j|YI1V1$Ow3|fgj(y z%t(E&Kl6IQNQCt(Yg+JEV2g`=aCWB0Apc9POUaNn)y9y?*m>F_dVa_ettmh zE*>+LOr@k}IP&WWMS_Mo9vm1l|MN$GBwg?(izM^E(AeUangPt0#E^oDvZW@w9%W7f zQ%T7A2Pa&&-5k}q6Be3_vC%_LYIH0+;oPL;9G$0+>EyD3RbnfvzOX0V8FH+-- zZ$8@cqiE-sWh4C}FHDs|b4u07hn%NlanBWY_e{+2)zJRgiE^Dw6cs|EDvSQQPF?p< zc;M?ILf0xESCM<=B!YcATmFTK0B=kchTpJXvs zjX^EW*8aaTydlx^tEU4OOr6e4mE19HCpIoU%Y-XTZl`m>7cX7L9taHXr0Ic=t7gDZ z_2nFm-rFh)Kjznq(S%pl>S~K|(~loNI<{v)6Syv%DjFP1n)t`?CB?>o%yfA@_#Q$- zZCC5kl!RU&D`ypJNXoAdaz?VO)H+|7SJoalvrw9WyZ}O@aLbjKj+VJVX`Lgp_HsGb zqu$(SZV<7_q&Q{2Nki@(&&EQ>NDa#fIPJ2?i>(`I_f?|QE%uyzTD<1amSm|b3YaSQyf5vd{cUEo8uW_FrrA z^C6x{-hwxcCDcr)v4yh4{Ji?xWlFJu5#+;o;>gg@2SDE6sW1Mb0vQI{qHNT`xL|{O z*nBbr)cKS6vl^*poCKr10*_6_Sz9p&{{crTpIN}Bd;9O@Q)DK*SJ{L_GwjS&c?}IJ zzHF4vwE#wD*bv2E0NchQWbm)Ec|D}OFNkqa#u>4vmrWFo2!T&MR$kq;)&n0{XXT`DLQS-vKim0Os zU_?xX6Az!cekWPh$MESvM3#WK z5M?;Ful^jpnVFw8acTLjH6ruHy)82sa7oJrj`cqK$7L8i38lKL!J413w({MF;%9^FZgZQeU!_`Po0#3#qjbLu^){-1Th6Uc3wk_N zW7MTTDuxb_2pafOrs|x#-mYm-_D!88B@5HvMm>=5Cvu}{VnDhU(uEoeZ5G_rF2odJ zsORfFh}HDn4Ph_o#mO2E?Pl5sWif$#-lY;rM5N!PD8?T$S2y2_L5IA%3nvAQUwQoM zC=({ALb~YK0HHy3SGOXz;l{;=)xGFsUdhOAX?!kuos9ufm`DaHz2$d;oxU{1^QuEN zFlH%8QTB}Fr03-alAcrhD!_~xbQYo9_fW%^0tvAGXyw~uz;2}`$LZh5mQ`jP=C{zQ z4%@S~CwejQU>;A_=o%cRqNb&PFn-<~z8er2m|JD#oKH=dmNWHs`y@Cu-y$nC@YsuR zr_J?(r3&*6y3c@TCerJBfuZcX&#axDT^_t{ymNdnNgS4vdHVTMpcc&pUXP4{^7^fZ zMu;LgpmTd$^+(u-rFv+mFa5V27>{ea9qQF>+|=~eS{M>%wDdFQy;(;hq+u*ee`4?h z68J|0JwY{2_1EyU)aGFu7rJ{iblhWzJNo$qQ87P9r zv1C~zop*ZUgf)I6^N49bk}~@@jQm<0&Td-tn6pseBK6uGhZQ)=YMLGI9hqx7-ym7u zZpx{bf0#wG;4p5L5VCyY3;ZB&vg&1&Cd^rIUOb# zK;U!)w$A?14|Vsv-psh{7?B4-Tu*abY@v!32wM#(3S32izMPXFxjFEV(Z!N0*V*89 zW}1DGjl4|dNsSr|UPXoR1fk>S7^j*FdhbpWUcRnTX~(){yMel(ua&)MXd;G&Xh5-R z>#SnJ%1b&dvGq8|=39#+c2Wrn1v@!(_;ld%E-))|)0NMuHH$V%!rEE@HaN#Sx>)u& zxYt~=6o{NPPTb)tmL}*IYf-gQ4_Em^*WX^b05&oZ(tG__Y+qT+WG`|)4dVPSsQxEs zM|-Xfr7I55DCl{fyMFN;UWq4|N7$KI@T^yitBnqoT`h2R5Z=N0`NblVHPgW0f*)qB3Q$PEn8)c|iPR30 z6F3++BUb2$4Y7k6f^iNF4dCfX0x02_7N7^3L1%FY=N%$oGNOc3h_b$ltfw-MVkw+t z3LR5589O^Pko)VTWiQnqH6l-ur7x0X5zE zOtzZmeJJVu{M+35m|EInyBw4EgTD>y0jI#-A6Gy}y&uE)WyNoo_SOum-d&oj+kVt| zYa-dDD_0TMFraytoRSjD<2>ON)ehef@FJi%SjXr?vtkn-C}~$6nIi0P?(uo-=dAS= z&>FPZ#N?wq8|PKwrRY*OkW>sog23K!WgsCPuJTny*3^=cXBAi{BUuDCJ@UyTS4&R% ziV9H;4NihsmQm$GYhP{*P6Ff#`YBZYq*J($kUu$oZ;#b6HyB`s6=9fj)?OLrcUMjo z0KHBC8z4`VD(CBZTvQ9c-`tw?_iH*8F1GVd)BCmLhgA7fB_S@8oOBNtIhuzE>o1BZ1vo@BxZ5O3YB zu6t1=HiQRMJGZg|PEV9TQL@Un(H3{S^UbCG>;wlN2mX(LPFK{c)$i}W6qXYy5#C## zD($B3{w|_@1CqNHW?a9g+l}3{{on4}Uj-83R?uvbcDC>f5m@m$xDl{mBopGH36TTC zWWtX+bnQ_I8h5+Fu}a?o^=^!j=bOZO-N^GtuG67IEXclbLR1cSB(=_1K%jqh zpn!>Rx!!0|$#&4elmjSS$3I);ET7s53Qc-BZr!X_EhmgtyM#4<>$ClRHQnZV*6EG3 z`Q4UskfogWG+~SDbPxs&vQNuW0PZAiEA<{sSwThy-l5~w zLV)vhfN4{qIFUg66TgkkPRp7~%mI3!RKh}v+UVA4FCe=MD+%MMuz=na)t0ldI~goD zx_M>y*KA%LV5q&u-!V8Y}TP8(Y8QR{UIZ-i2%|BhN7N5E*Q;gEeg zwhg|ONxXB@0cDeEB~DnGR=I0NcYcE{4Po<;5CFs&fMkgJCcfwJw${~$ZM6W3wyL3) zsXl75lRTZDJSRvFF`de-+Rc-=?~3#}sMmgfJ5)!j?Uk$tQv21jA8Y;Cha>8}6#G%m z27j)Z!NY*}WA)yE-Ug_37a$!&N1o*XuxfeS3XI{Yp!&DzdeP&NxzNFl+T0J?SVLHG zI)r!C2G8#T?Mb!^DZ^AIKCJ#dTdmapGI`?QmoOS~-mCc{|+Ne4)Kh6TVA7^v*u-FUOkh zX%?uMF&_vyqB{S-7682;YCg7*jsFTzFy5P8838hKAe3;qODW7O%G*r?01NkRe9f<4 zQ)M@n^lgRTMaP?_^FyF=@ke-73C8FGL%sIlwlnRyCimRj<6yVmFk>*x9XjHago?6A zTTp(OvMO2UO6CgR?p?nEbL)=)V=>mOyW`&BRt^jEu@&Pz{(YaZhlGMU?Z-PA` z>eb%k++Rk^XY7nPn3!QVhD-lm15Zb-7?2fNzRaIcQhiEnuX!?QPR)%tBC^l%J=U@B z@T9bgR0+KCxtl*fqN!}%f4ul6e`!Rgx~qYr{|KhPJ*)Y|QcAd=y|!O#vP`(zadD`9 ziHK^LNY#fjxS1$hI>A2daZz!~_-MpGd!yJ^+UpFGq>zc?zeJmAkE;0A;mm*Bga!4A z)yQ8%65Y#4no54NUc>ciSZb?4?B3N%=mrJXBIaOl*8;Vm+IBlC1J-<0tLHG-MWV6~ zVJrSlQy*YVc;w=KJMBModR~vec%4MOu5j_<2B>syd2S6s$`dCHQKa2$|5Z~%_${L= z$d%Mzb29#>zZT!la6-4QxwB1Ctl&?pE$o1)6%~4_%G5CCD>{R*9D4=CX7Ib2ByTY_n&6$2 zY3~Fg(!tZWbdPUKV+!&9Lj~B&c!IRiblXqAxAr?%F7NjPPeXe(bT4b}7WGs?4UsRc zj~$;lc?1Jp#vd(V#yjo=7wLZM^5m0Na-VJwJqi6gy@6Do-`J~o5;9e?LQc#2j21pU z`quHRp-g;4umXIM$D*3{XaffvdzBJF&Dcvqnvgy=ZN2>$wsHT4pw@L;^XFQU82m(+ znQ^uI(}KU%C#wd-`|Epf)o;(sOjv32nCRA$vz)0_OM#t}Fagu2yF+k7ru|)V%t9_? zLXz8S`?#>DU{{~k69aI)of0o@47k56Fumhy*E{FChgRN5Rj9)JE99O@&+a8V^(B*Tz>CyAQc0~D0U9R@dR*kZtB)=6K3WI%r z#{q3%!wdPmNGBO;ls>5UX?Fa)S4qMnGH-~Ylg zy)LipAd3Dy=E@Kv!4(IElA!UwV4Eoe@Z(4w>5+;S1ZYjMjT7 z8C}z9L0k{Y?u1DT8NH+$hh57;J##NBtvZnedzV6w37YAiM`(hcN?q1Q9cmkEJ4U;( zgdNt$$CvM}UJKKv`P&IMa;+XW)6$@ao@<@BkDIZs4o7TclrB-N+43ydao1kC2%Az_ zd00~Rg>^;cnq}6qowN+Q*@9oV?{1~INf}oLka1%-GOnHt;cAEfcOjyqis};G=QLX=9&IGVEXb z*k#b2DNErJJXF1|I-`Vi+aT)u+Gi_Iul0sw2vIt zZ>NggaYlBHu++dn8l6m8`>VRK=H1T)T~iFy`AfOiFN41)`n=%wf;G>zusmD3M=+g} z{#LlSNw_;?nD!?lv}qAl`A!U3h}L|Do-31(^GY6tK%10(f8{IR;I`pqe-Tp#ktxj& z?ECX6eO6f|nZcC?xvB%Y^|rSUMiQf*91T3tvUhr~r-Vf2dIrTc=Z{WX?2z`7QQqJ| z`Cf|ZES1rEPT$lczQ;uG+E2wdMJ{8nflyMB>Rs4MU4?yR&hW^7Ll^2*F10^cPUt$E zpb>~Q%In42e9*qMvQ;2mTNpz>qbSr&5a21t`%}wp{Q6iC_Eqq`njWZ_J)3H{@U)|= zMv@<={mVn@>r~aDG z*DR0wb*p>6oANa^8v~}gTO@Z9ZKArBL`=|I#j4KD(=NbDi;sOB>WZuSr?X$8*f7pl zg>N)kAN7lzED_a?VB=R{mr?3h9>2XXL3iSaKyI;C7L&EUGPI6i7GBWIwTVij)u1`d+zwJ4A)d1 zC(M#qjqBwgyYRqbOM{{xs+^>iMHDAMX#jP-Pv`&*}UUFfBaZA-Q{p@9}Lu8zx>_tJ6u> z_8et5lKt{-h<$S54H)L+y)o>uWzDzjCpkfhQ+K&z3Dv{h*BuckugXggKimVT#wsE+T> z*JQy`Iun!rPy?-0UQ5BCd)|S}9sg>w#{RxzwEvkZoo8n)mo`R$Xh*Bu!~{ns03LoKJ@FLB6qW z@33Cfw9AjE!u8r4&KoNcR&}BEoJF&%M2aHo(}Vk$Qy3E^l{G2g7dp4H-7ylcCQCQA zncQc7^wz1d7R<{FXi*b?{ha(*@prg+zRh9(9n$=geDWBz4?6F0dPcUV@N}_ zz_q^J3pkG%jG5wwKIEEOf+c#dKQ(XkJ?@D+_3RFcE6&Li90x*~M{wFmbT`udQkz84(fY1^~lc8^U#<;W9%`pzms)SM6wnIBhf_!G7J0%4#r-7bXNyDTrP=9Re3 ztK=yq|GC)+EuA-cDe)oNekr~hF-%eGkY0#Jxso}zNb$jlfmF|~fz5#xo%QipJF~z2 z*Kzg3T(yRwK_-kovN5yOvJKoDq)G z^7e6@jE27TY!c!YjHef1P@FbnS%x6PqUZ<@pXVpQ%Cj)oOXEzQiU>S*Y zxI&`J56D-g2@+g(ce+O|?jIv9+)#TpS7La>^yiNPzr_20r>0+IkM`5JNf0}BPt9eZ zMvRRO{$r@W%!~fBH|Hw7>u96%Gj%+x0cqLjSKYX1`jlow@CK{R5^J8Am{u2n{IiM9 z(2x-{-r&h3`hGf$o(*v+PHh>uiaDFhF)8g4ezb>B5O~-ar4hK*lb=o;daMOhH?2oY zxsxyr1h(($={^O2>G!vE6^#hD5x&^+^1%hXJzWIekU3K4Iu&<#1H#_C-gtxiJ4D$0 z=FDio@i6gAJOMUjpyAAwz{QQyVpv5)t_H!yE77x2=9xZ0IjC~S_!-czc46BvChC!7 zhTr9+@;woYlc|_ESRLEIS-Qx#@eju71>_Im@(*X8w_jHRvvF5dXy>*cx@ z-9$Cdk7r5Uwm;kGpC-*=8~0~@TVQqJ6C3{1+7Wi6IpSl(+X%-w;90*;` zhUaJGOTu_QFV57}NwC9T_uX2#_{(*<<#2!V_&G{phO^!n zd~%!UmuI)j8@2DQwiLy@EYa9caf1Gn1Ar%e+TLQnu{Co4@1u9to~!46jrgcJPeEaD zc_0A(KeBReJzWl03mF~Gtt8~(`j>cF0gL=>-Pl^~ib@YS-CG|u7{iyD>h^{~CtZZG z-&~R;Bt6%Qe{%o#ewHY|gJH}YcI0?mZmFFAbW6)m_ndnSZ#H3KtlPS9);oh|h>?sQW_KXbKpBQe}=`HZY3oy>$g{p4HYFkNAiXI11`Zk8%4*;m!9uOC#!|% zY*{;n8u6Bkt~Kpi?EI`@!!@%wQF68gi1qe6l;{s{W|U+RuKVzlHCSVIZu^ zIj!)#Fy-en@{SB8!FJla>;(_8e3&oKS#x~j)12S=k)~rn_KC|cpxwoCxuDZ@Ubgk7 zy0QIGF?8#eQh*T${!mHh-{X9^ecr`4NuM)dgESgKArg^i+>cvKMKx05L*(Em_xAsa z0pCOU2ff>@1nrU5v$K0|PJ=#!Q;Vl2+kP%zbbl32L<(N}y4H3KN*JMMB{Uvxrlc^+ z18hREBIe1CM5KQJ{O-XX$ic#koJ%mS+O){7D#EdSU_Z>?e{{D1?dUVTKudb(5e_xD zrK0^bqXdscf`%bYhTlmMZ70Y&Z^Ha{(x{KP@KH2b3=ST*uJZ;ELM1Q4~F z-OY12a%Nj$Ub?#AcKB%^yXcHYYFcY53H@M3Wpq~lM$P`<@4*2TUij3x-+GXqic)iB zO{B@$-Mx`G;Sf&r{Olx@<|NYcSh<0NFCuqT|@OLm1RZ0 zRQJb#VvHf3xhzGzdFbR8j*TbhUdZED(`C;eWir|vYiMnv=D<|}WfTyetQuLx`h*C) zQt2MUeq_}dZ1gR%reT7xni;Lz?Rol=bWpYlEc+fUrV7kE+E>5Q_zPn>+nD?cVo3s| ziA5kAkxxd|CS2jRUw<;D?dltEO1WThlH?FeeoX2BtS({jjsXXLLyz3n-fnKQr+ z==WLI0_t?m6A$6kFfm357`I=TIK z!vx}I10|(5>qA(hAG>)70)r4w&bkUI^6bysJU$E-c5}PvMb1;_N1E6iOcmV5gW}_s zizGw2K@a9R&SK6*7kyi6v(UxB&HcZHg~tcRP%CFnrL(3`jt%DKNlj1^4q7cxFdlm{ zX{&85t)nemVzn4noGcUsJRYk12ZckN8oSp|!|D;= zG6=)>eBh=G9Bv*o7+5g{?u;Y<@i*ij)%>0v4ARQ@<3l^sT2kNV+gnmZ&-;Q6ZhZN- zXy=K3!KbS=ayYPZUMet{8zKT2;JA0ykL+li4$%Q#xP^;>m%x~)IYWy zPfZ%uWYA=apSy_bjwG==?0rX?2|;?e!Q%K(SVD}I#e03{`ZA00&XtD-gW6dZB%kKP z6B3M1_+-{^IW=g5l>{hH zQ+d9fAn=RydZe^Za4v5H7fi`kENI3w8{{k~%zm)CJ3may&iq(2wW*s)^=@)9T24M%R=p{8 zZtoid4ntyrw~r4hKE9Z)97}lksGy+W$6mFZW4{mg>O94m`I9(1%Ne^k>cwOFAJW;g zSn&zC@F<~-mU3!UPfR4_TcJL4mw&mMZZ)o4gE$NQgqR?JY0G|LYF)|0G#kL*bJFRc z!m%gUCaOQMLPOBJX-dRTo2(X{xfeMeB9(H>>@c9(vKGw=+`b|PilRG2Fc*^Gfrm&} zKUJvXQ31@2e8$|I%atZ&jZ!lyXjyZQ*!g0t!3#|P-kUj<)}g`;3-z!`9DZ9ll5pu& zU4tx?u^h|@Q^9c-E^~UiSdcgH?lKllMom^sT%7BbB(|iIlB0nJP;(rq!+x{ch!vWK zdA`HjaNle=WIl{Ct$f0AWI3L1NNIlwvNS`}jUU5vE)VI57;AA8vXN0xe$5{ev9O#w zHk0D#2@qPq_loI_7MLhEX(2t&81=~Fu89o(aR04L_m9gDJTDh=<^~OC1I2Cj-FfbC z`qX-GAV>P+L$A=HCxezfEyV%rI+(zM*&<^$))dZJ?vdiEgv~ksw$+5$q`f<*#`QSG z)TE}^BU_y;VBEI)is92D56>N4DsQUWH}Z+gu$&58Lfol>52UO<6ySXqk+js-j)e%PnElF`8B042C^l+uEfT_!wWOXWqD~ z7hssI92aLBUAunEFGQgA`n7d2Vx2p;Rdyf91nY&_n>#*}_B%W|^o2)|FBpWkZco_E zzV>PNcQ|?~_)%1d0LtaVvJai>vXkFA)nJdFU(U&#Nhq0 z$#NN6bDWL2bCBO7ho_OjIUH4eer}+jhH@Z?!?w|}l*zc1&+jYUw99B~XJ9+cz4_9; zX`bFxf=ez4G2SGkYHWcyyf99v@iI~sJ*V8_ZwFH5#MrRFV{ zftdHgAt@uZnB;GgJGL*hOA|(I5ezbsM!utYmw5@;vA{zH7-jAzZyk86 z{ek0stuzrya!64|ON0r_ajkGOcn7pWbe&FA-Mg~>oJ{j@3nv_k6+nUuxxHs6fJMan zK*tlXO5Bxk?J6f1B`wns_DZi)X;5JeHDb2jfRNh;iKk=44!^oPM3;%_BDP!67`>p&m~Mg-3PYHdk;g=QM*{jh6s(ae;VnDGa_; z>5yQ&UKF##_$`VJFKlF6lASJs+1ZF!-)mS_J= zt%^O}88oo!Iys_IZbU84kOA}#Aj+dFbE&H6GT(inY zg+xWMO{O3HhxdgeNJvE6ND^B#zl^g+prF3+_?f=X5gi>3Ca>}H3;2W7UvQy#7Id$|8$o-gEd3Z+B`lW$tny*2AhPewUa1J~C2fA!NBSI(4~XOI1BDW@m>#ISIy2 znB6`lz7RcKHaAH?s$Ue-b3!MJ44B#Z1g7|!$Np=`@H$;W*vk_)8v&>inxnYdpZG4+ zwW}VyoA;$|*IMf-UuwCtSO*fyBNFLxCj%!o-^cuB4y2z(1?dh4=iv)pnz=luDzX755VQyTe7Pmh8Jx_tJV^|yDNRmUWBJSi_; z-Imu|(yLV8i>s%4Cfip2vb?`(Q0EumA7Kgcg(0jfO3xdlMY43<7do-tZ-xEoJHETs z;z@;rv*77RHpnMr^ZUhz{_nDf+C9H*E3(fLX~`DUN|1a@%c+6*eX!+jEJwL^-I5n? z*2DrUq>nL6Z(3a;l+NkzuRmiiGm{b`pE~U*)p6l5+NGS~H}iwWgbEKwKHrNLQ&Iv& z0&g>=+YF-^u;2}MI!HUhlahM&qIqQ$6{T$D;LXF}il>EIhwvvRrq*RO4-+cScV?5z z#@s$7ha_8O{TlhqMSw&$>s@3rG09e~c`afmBabgMDlJcIn4FETYJMXneZS95Kqw@H zez4R?7~AhhB8nBl6hXpX$Fup zl~mPzkT4#C-FpgpS?w{O9M9n}8Xajd&UzoV4Y!9}hp>1=3fDvaZp5Ha2uY+bfY6i72#KA~B})^i?cU;?J{-vz7I~XJ(WJ z$lz`gJ%}hN1M2F2oSvS}Bs`%C_$E*FDlT2j;x5WffA0MjuzQe~G|@o7UM4C$&XQ+> z6R!6v?;S0t0Xt^}di&GzR#}=62P^Bv#Kg>~9Rtp0TFg6!imy-S0CzRnaR2_bLdM1( zWic%boYn0*va~&!B=jJ^dK!JswM1OMq-tO=K-X|@27_-hW<7B@k(z3}$t^gyKTRKX zjE<~)pku?3mzQ>Z$6NFxB-^N`EFf=>DkD?dat426+oIK!k=c6U%^E6V>cq&V^~ZSe zp0Wd}bmMnSmj|>Y#I%tG1vGj2`G&S^zr#~HZ$of7R*j{2mJ8@MmM}5GQ_womx8b$> zYPg8n3zF3eBSWY6g<>9FfU+xGQKmGb!OXAFuMG_-`r?zzhKmW#IrGOWXZa@O z`XF@PL!3wKz5+1Z9pU51hk`%8ss%wA^>N?DyU@iEog? zTDH%KL_rgI9j17Oc=6o8zAcI73g;yA#ky6i`rjmPm1Dw5<4;N$(1eU|Hif&j*-!}x zLbHvO1~BBFh*i^HCG%FXL!`A1=>Dz-RL5F%Evs)2Ukz&QCh*HuUbNIVA{-<4SAgDY z5@X2y$`UB!!haYWL=LR}PD3^zHH^JXVDO0IK7YhLE!Los)T3N(OtI1JwuXIeLsXQU zwAx|IvQ@nvN7OW4CXXwkF)To*_Q+x1XQ)2y%LTM z?|>_4Pa|+fMk#cb#_BeWricfOB(_1}EI_nE#$Z|#_#G@lP&G(`ixrL=H2CcEt!v*K z#|B_hX4;ltlbe6`q5pB^1!8h_Tk6n65?NLrj=jsPkdVhF=|Q*Dd&F$s%Blko{DnN^ zIG0!WYLg7{gP)QS@NFlPMgF-!`0F{J&bfwoxsilMubsNxV~VJCXK(q959zqn(Oq;- zaw#V(CC#1hZI)84b{SKd!5Rm=zZaAVMz^=`B~P-{pt;Y@Y(@+<+Cn$8r zbEQ|BUr=#=?`q-}qR8VnG<*{-jSP>&%AclGwc&qBP-5@94_k70Cz7$yu^SN@8c zc|U}oB$z3Zo;xOL8+YT4#PA$ZBjxJgw|i*)GQE2K6P4$|9$)phHq z4v$ove71w}>t05-hQO|&2gG;%IKVFV@6TV8WhLSlhwly0($FK8PAAiDr!ifS6^nj2 zX@zzs^NYm6Pz|RXV|fSYH9EscQmqpM?Yl1` z6j1C=r6VOotaG{s0%~I`3g6{Im~S1{8}(dnoGjE$3zIv)x6dBR2s_uRl#9L*gL5dtqU~JJxks7OF!6d-LLq3bL9? zlgUe}7*ncOnq8X@Cx3C6d1eE5kF^b7qaTI1KM`q0Vd!@1r5;Xp1QtGb)E5B+ZBu%=bdL-vFK`^%p4mmzRf! zA&#)EhzTTy#ior_sRA}oV6Sf5Cd$7aR3Gq|^Of~Ce!>eQ_CTez?rNF2zlBpg(3EgT zmTG7`hzrF<-)sI{WOiO=)9fYXPQzzJ+^oig<9L(LZ>zSQ0_PH$h=Po!Db7ob>($x< z2M3pHbW-IUe7RvcGwad9`%>yDC|nwX9bBWzksUje4BNLpH5 z=-W5r4<`&bAxa^_ZD2%ZSWr%`E+N^hpt19w)^@qF00n(yj(lTT85f9LBhZc&)Yv;v$g;bAh`%)DpCRbBNx=n`g9uXnyfRUQB3%0BDxRZ%*%!9JUcwr-DK>=lJKDKD7H z&^b%5LYs$N%MEdmzD><5r+ErXCdx8OXh!k@9^y|)|_N(^ay2}4Dp5C+tP>^%$6K|~oM9rBbCV!1IHPsZZYyskhq`9p=_^}+oMFk$mME4u9yg@dq= z#h%6sk>lKl{jt=SCSmV&4fCe7C#djyDOMqPORbM#lK;3z8{rb55Cuz4*M?H{eK<8> zCfuvyr?bw`ma_hQ7&8}}-PYPqRT%TN`->9za`T#Gk?~Oz@Oy_Bg5Dyhht*=AO~z*b zkQsbelMU#{UwC0VvLbuEdWVj7MAxwo$=K!KNkz({wBRD=Of(k_fXAC5{ON!4HG^13 zx!E1Rlav%p0=z^=AFo&RfQJ$I(3!{Vmv`8wU`C~_XvNAH{_%XkU+)&W9h;kCKUbiO zAZQyCt)lL+anr@gqSj+}RpwXI)$*gvP<3+@ta|mrkZ_)Tk6 z>Hd4zUnA~os3`HSkE8>MSB&wy@!meZtJd|`xdZzuow z_hMe{p8dORAHeeoBV!}`(2~3knr&Nhb5X9a1nqxuW9J1jGd%)GxPV87ekh27dh&2$XP+tn@-b9SS${b9N~16!S+rzpBJ!q z>g;b#S4U_IKUa9$?*wK~OON8jWP6g{N8T8D&+uE;s|gC)-v4~n9rQm(M{LEeJJM8rjX6&I&jT#En`V(S+rY{Dema_33*lPzT!~?!}aEE zg8s^7{ZYHN(K7ZVbUL#Wm-zq&b3%4T=2_2E%DeYibeGjM7V~9bVG672?{)CeEjDmry*z>^-r-iGoLatb-oUN?LIQp?2WMS4-);r zLW34bqXSn8jQn4Dd7lmtxzq{sr1<0~TSgMedV{C)S8VH~(MTEa4qI*d1Vuz5$GH>T z-R{cFADjpD!@G!WX#mpgu3cfbu}6`Fq4@ee&HQM{Ny%Yi_V@Ni!ej{E z+zwXaRf)01`v(RKPun&ug{InUJN}OiC4Hb#p#D6|eSH?~q4O{oeK3RlaxyJbSa?K8Z^QaLPd^N>{F?z(O=?LHk2?kvP@}=c`^7^Po zF$H$4!HFrIY#IdPI&eU&-a0l&WU}o_d=wf#seH6EgT?2NXiisn>DSWpopySEupd?= zLRH=uxU=u~A}k zl5fWKeQ{#n{@`6^rirs`vAKXO)R=Z6V%-!MOQC0slMG#T;#!7wwwg6IS$S>wQVQb7 z=g=^Sy0(JBa6l6D%YC$RQo34XeWjJ9CC$`;Ov-!v35CZ+33|1MN=Y-|km}9?7u?OO zs2waKBGA?7E#IhI0|63UPUI`tZ?h52*wtVJJ!?oiz1Y_X@BYmUhozRGCR@Ip_rxM$ zdOLrKDe0- z7xp6vB%o?AJUnF5xRU~#v6oC&S(xqFAMrRX(J!3oc^+Iq$LcJ{{2!#Wz3tItxaQPJ z9K3erG5yFE;Yyhs*z5!7c11RMG3^y27CaWhqrzL!7{+*A)2jF4WU?O~{-(FK(kFUo zxBjBf{Zv8-3Y!MWtjk<%r#9d5`!UB4{K?LG^;pZ;ppK+oj1)Exjtx~K(LS>WPY8*$7z1R? z82RYsvri{2+PifR$^Sz6pyexrSL;eMA7f&o3>%Awxspf zOvV#$WMm><0JoJAO%XA{xN&(zQiS+$3inKPwSQ+&^U6Z6tf-h6lDMG}3r@HzPq6S) zM@)kLUYUSE&~sWP-}}c82?h)1!^+j|ZEXOn<;YTbD;Gm4-;gs&j3+$e!_Oo>6)HFW zl9j~%A|oS{*3fDEk&0u_zni6cM<6^QrtRm82jyygbWu^tuMs%5p<8Fh3IEb7z*~d9 zzkRyOmq`9;#(%Q^tV3$7>XMXbV%mkZO!QfBN|g${XH22c&@or#UE>Btj#NgYMNI#L zF3UC}Q``TSr*Lu0QU4C#`09x0@|YgPMDfbIe2H`FlfX#aOKBO`wDNqb0USK?tqm(! z*%)|Fxwb8jcE8lF44>3Y+_a30Up!7uy4eQ6UFg%j4!N2FY~t869lq z8j}kntP$q;R;Rxp`VR4XbRBuXUvD=h*C(G(!M1`j%)9k-Pc_2`IO{^(0Z-lKkx5V7 zPnDPVF`p{0Kzod(tgPN7vo=c%`eLakOf7=UpSCz z=VqWN^hq#xa3CK^ZDMxvdhzIbm@B4`enYUa8LsqJ*2Fx{o@zRYw<6MHoRt+RVT9@M zuM=9;`MG#e-7Sp$!A#dt+si-)jEsFMEo5Y+LWKeaxE&6Axat1*yo zkDsa0QsdnpV8-elH00#do0?L<8Tbmr(#7(2(sf|)e>J2?PuKGH6Zs%2{N&0Ku_2Xg z{4Jd+aiE6`RUscbe{w2IHZ$R0dhkD-ql_1qKwa%6bLF8g>s{_ukw$wusSNy;o#*ZC zongoMY2BebMqmWy)`lfZfHg;0nP%%t-b63|KbH9~-zR_bPt2ejB_PZ~kT9|=Rs{O| zeU1co$Ddj&ng&*xBp*eEJ^FoSf6?@l3k7wi|L= z7w37?yzPnq!|~_;%!T~NNuJmH|MM5dS6_7XMN>PS_L74_Qx1nkJ4}nF8#4R)2gPFz z6%{c70Rh;llQ4sJUj!0z^7RYn`HLEzuHe;&t7W8yq2Aur`r{^(X`2dt09Bx!ZsEq( zmi4F*rrq^T=oT0ytABqD!FLXww`fjQv1qIm7#@v>LB#86a5@9D4jdH-)BHk&V@Q%D zpH{U&KqV8`>K z#d?S15gXg=z`%D4<_-pm|IpK0@`J;Kr@=s6>;27{a-}i47YxF?xl2elA#evH&gTG` z9vS(rds8i+pPueHGBT2;!^Xn$9s^^_*a-|8pFaeiWPC_XLUuaEJN@#{C6e;;a`Fg2 zrXz~>KP5{7-X7*?3g(zPI$k69Ljh)O%BC_>x3Hkfb9Yd_Tp=YUnS+`*IJIXmGM4n& zCe$(b_wV0q)gY_FR?Xtf&Ddx(Lx}5qL;wt~zAiBf2??1ots;hztt%RznVH$zUQ{Iv z>$d4&GW$Gsw+nInj<)HaTHU_dqFwsB5tDt%=KA}5NF^mlpmpib)!Yy0|S5Pa0(341=JH{IC+KNtWni~npx zcD3YktknwLLK>^eudc4Xa^Z!<^Hp7)ptQ6UTu@6$C+4e@*yekmXlljN0p{V~NlD^h zxc27eCXGf@5{S6O&?xhpo707dhnvn-yse%eOm!A1zVRm~=WNxF5N2rImLvX? z6;XP6dPip`GCF#vS@q&`?m<-TdMIbj%~oRV-BCSgB}L4`lfrr2fT}iKyBVYMviotm z`O$8MRl}+i9gtj9Y;4ixCO73KS0~N8g<2bI4qJ++hhvZ4p&>FVs=%?avG%3JMwct# zXdZ~waDRU7TO=fMPR>M9F_8F=mq2vk@pR<@ge}Qo*)6uBf`y2P2#ZnsH8eCdU-#oi zq}0n}ML9V%u*ax$vH63;rFwxAj}LdEl9F5b#ZB5LE3F_)u(`stgW_Z%4+Im!KY z_h7!7zQk;{Oz-?~J{E{EIPBe}MoydUA%wZ7o9$GCku<)Jj*j;zC~ZCA#INQNCBjdg z8y7sD9!N+?-lL)lfOzQB{WkA>LE`ZCIyik&GBV$up06^pvQGPj)xY{cgM=_}^HB&0 zBqb#ggD_}`xVe+F#A0FkXp~AmoFwm#=OCSJ50iiX9B(#XRq1r}7M1K|0W`UNyx9in z0}`gDG)O$x9}==FYlk;uH3+VUy#4%aI?)xsD=NZ%;p2NjNlEFKdVMHTFn6;kUCr**H0c#cgwSNcGN1>=A<7#z6k3Uu(D!A z;=N~(;)1-^)6+XYn2nq_uMg=A!aSQ&v5;0)?rpqU>Svu+Z3j5|;wkb79DKssnl^|( z5xQT0JZ`!J?H4Y8r14x_Tr@mf&VxdEHq)6Flj6p%@?oBS@3*KWKMGA3YQkgHodbZF za8Ue=?aiVrGLOJokHu2yht4 zW{baFICnc6WLI^+*?b1@gXQK_&~C~boZjh*7gE*DY*cJ4XuA*PVIpbMcvQPhaCtD> z4vneWa=trmWNP~Qo>F1GDh|#Nxf5r zDz(>ZL6kH!x~Chx!Pv~cYW4Qd&r|MtbDEa(XlG}~^>lycc|4NNelcSAh&89B620NV&PWtz2+lEwlsm)cFdD>x;ZR zI=I{-2e79TvQm&alVZq>PMEZ+>Oi!jdM{Y=4S3)e9{F8Sl(IX^&AdQ6tyWH}uY=|h z>>#4$8E;r%ljQ9S6hI_u+&teC~?R@@$laq7D;SB>g_93n_ab4wXppLB8 zyTX%`2YnH6XBwQC85tQt;~~=bKR@9iZVki>02u(2jP)n;u9ka z4Ez>-TaaH+u+fEU0e`R3;K&H|EbJT{2>_dQmC4xHV#K0wtKuN_F&ZOLt9&4x8g`{fOO$LqePO+Q7ym^%k>a;>p7#G=Q9Oj*G64b^Q)%j zQ-eA^z$op#iN7>IDkyRv0j2}B{2Y3xYr573vPnThvk^d^@`0Gx3*3sBfdO%aVs(UT z3rmmdRoG|A*%{3g6&Kg-3dRPoa5gGJ2pzhA;T+GX0~1LmLBz-i@!u6tRI@{mRkePL zjg8%KJ|@;vHjrr1G^_8FI^0bh#?_W9or%Sy`{wx)&sSR@Rea&PoY6`0cmz(lV-Iqm zL;_IBPp_JvxKEbue>}qhrkX9Xk&)4Y%W>nx^ZkMpx?%L@YXt=hlC3 zZ?EMMK=VKXYtT}oOJq{gg0b7(#eO%yf|r!G00$_!T`u7l{Hr_HAtyi#8EtpI3kPGh z0%4k|vC>&#CIoscQzWd*xKf)bJ`V6UaQvQEE`apJiIdei9EZ-Df);DP0B}@0)738y z6)2b2fU|m5k^X^!M5LrXXG5IDgSU;~K8h!@h2Wakc!Eq20+$2E+pFVY&|e9v1#q-n z(1vBIK>2)cG6=HXZ8L9H4UNAJK)BnK?W_%s9$5RW;2P9i&Y6T=H?iz5*0UpVpT7?X z2w1Qkmq>EEoE=Evt{*%F)J`I8l9ru47CVvloMX}7xJ z&zXiXIKhbc98lktl>C#E@u6@+d;to+Dgn||XSWaTUqkCmsSaQZ*-Dv zo_yi4Gq|RVE8%fiauxbyB``2Bb}pPZYhz3S9|5b>=FJ@OWIYWMySdO-%u8$Za9O!wVKqpY>4}Gl0dnwSmG0ch_XQ zSKu=MW}N^H&1&?t(Cm?VfA2bJ@M1DGgi(){oE#Pj3F+YQFnZdAK(>n!z!N_(LOHW} z!ouL*yji(BZZ39kRaM0UNudi(Znyw`fl)8N>jYX3x!yy%pP5=o2?LwOQgADX!dxAF zxhTyVH3Y=a+gQC&q5ook8h9q4z#`dyJdr%!)`8BOH`F&#_v*erwN()IHxTclhch~Q z<*K%-!^r8B2W*b&V)GK~2YoHLV!?*oqK6-DtyAeb_4@J6$}iy^92}s^%E~P5?4Usl zC}cuHq%;m>K(;>uzyx4I+5YHSC7Pbx88-lq&{$yU@pAhl{X8i%+Q#a2m?XnUD z!6lXI(1{7ThK7ccvN9sTegQL)WPOB0ehCql-99$vVPj_2>5U+*Jo<*^MGIwOvM>CK zJhPkgBq}C`P3ayGeMu*$+Oi>FHud%O$sNCa^G37H`)%dY9Z7P=-W*aFH4RP(3@j{c z46Ta7zMIq-WADH~fr5$ldavPNq?U@xyzq7cs|g0X`N9g=z?zzxv`J&gxu zNO%OWnf^MVYrE^=rWKa(WM`BZP*?J#i6}s+Jb~tTUUQjVKWH|- zb-LMK$s@A9ELZNOC@?TEFk;A3xn}^#QdBJsEv>wR%g-Olr3D2A#vxAkPHqIeJYwIz z?Q!!U5%P!wcFpN5X5H|5yiN*wI!aw5&*6UNMddS^t*Ge(j8%DEwgsSra;UZrtl`Z-15B^ltC?I4m_a z)jIkNLbRDPnj=LB0HN0H&c4uWn(M|1#Sal*hJe@g`Zw4em>`AzzP?Y+=eeg`Kz#g= z2&p{kb8^VLL-F$~c^cJ=IgFl&xwyGMyIj&BA|h5+jZScqKmm0`!p*H__cA#q#uw;5 zYoYqTbZT{iK-mF$@+E&VA~CTaXd7I&WiMEyC|io30A~OtEjkzmz{aT6_F7d<4IJYp zu)*?v>13)mI+r>^w3(Qhdj|*Qv(B)bp04~dLK1<0PaoRgI`TJK@%L0()4!BZLSTAHn#X3cCxJgY3%_ zIP7+Na-oF0Lt|NDj6k-*=JlDRq@<|USiW#^x%<(rF!({e0jmpP-z)y_Tk0x2GWKT3 z(-S|-Wb<)snWNgp(~v0fUFC`Ko`JD(TMg*0rgHvsQxrBjitb~I&w2UuY@~h4(BVAF z$WyfbtZ;edU(i740|kY@`@=0GplS;X3xM`*cLbnrY;IE0GNPiQMxUnue+8TQLJuH1 zzF?K#lZ{buam9|88b^0+;c?jth7M=v=1zeJqttkk3J5V4w=-ygqcefvano^T#IusO?grqtq zvpE*fzB zwrj7&1A2gqShU!RQHX0g#ygOhkF4?X~M5bNm#`nRXISGvv; z`t@rt6nS{RxLHzA@HM-|(gpz2yoqLDCu?hKpPZfolm8bmnSLiHBa9gC%>om<3pl;R zz>A;3gOxQJm@$)|?K}Mc5xR~JK^O!aL2K(WsuM;46=XmlfB^(Jd1f8%CqSK_jlUYJ z^*AmkCUg!Hou1ZucJmMJ?x0x=l^FL2_3JsOOkem01;HsRD|d8tl>xM{wze**tn36;FW`Yl zrJ7BqiwZQFQ}p^{w9L#TG&R%m7Pr8I15!vtOB({#zOuhBR&Rf}$7Q5ZqWK~;H1yd3 zJe;rA(bD1r5*^R!KnDfmmvZ>0r<&xN)}diC$l_2O@Yhf=Cq&Q%E94T$yJyrCX*YOnT51! zeouZ41~Q~vUpr=GW&$+nTwYG~_I|x-CnY5%nZnfzD9H`*(_91E`pl8C#4nDQHRNdy zx3_al#}^jxyjs8S-+gd(bBjhb0VD=Ml5&mZ$9%~E^+{v z!0VAMnH&hnoXysNbR~>?LsJ?Lkd8kfJOOTmEeAf(x+_2@A;3hd)!Awd#4!S&*s~7> zILKbScmcdwlsZ7f{lmh@xww)5h?eN~q5zKgXX4EEXdxb-)4oK15U1h?EqF0V4ObCm z++S*}&vT>)8aou9Ga@RgBaTsL2e>vA(5Iu0grKJfDJzhc_tU?IU zIXR{Jng4`3+w&b_P~&_-Wo~YM4`f5)=vTSfJR9&XW>8UJu2}*4JOIjn04zYpbfNpW)oB0d92s+Y~UobnlCIW=jlGo=}hE*^)#rMK43_8kc*dgvBHvPxrg8ux?_^^v z1Pm3hdGjPW4Zw^Rf%82=2_d0dpBTaTt7mO&={$FgtKrU{`mGm=V8X`9Itw>%JoF?~ zyqdx9&zEfPb)Hbm<`^9lTEFW?vXH?6)`lIq?mL0Q)86a6VX{E3V&UyRCIO)I#ox yvY7F~e}?m$Rz`ofI&+%=2s~Z=T-G@yGywpZF}8XD diff --git a/attachments/sink-element.png b/attachments/sink-element.png deleted file mode 100644 index 6a4eaa1a379d1ecf88e8551e29ab96c0ed18f6fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3369 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 diff --git a/attachments/src-element.png b/attachments/src-element.png deleted file mode 100644 index 27699e05b4c2d3432d0e879d1318cbc11107519c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3611 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 diff --git a/tutorials/android-tutorial-1/AndroidManifest.xml b/examples/tutorials/android-tutorial-1/AndroidManifest.xml similarity index 98% rename from tutorials/android-tutorial-1/AndroidManifest.xml rename to examples/tutorials/android-tutorial-1/AndroidManifest.xml index 2086bc5..cc6f8f4 100644 --- a/tutorials/android-tutorial-1/AndroidManifest.xml +++ b/examples/tutorials/android-tutorial-1/AndroidManifest.xml @@ -14,4 +14,4 @@ - + diff --git a/tutorials/android-tutorial-1/jni/Android.mk b/examples/tutorials/android-tutorial-1/jni/Android.mk similarity index 100% rename from tutorials/android-tutorial-1/jni/Android.mk rename to examples/tutorials/android-tutorial-1/jni/Android.mk diff --git a/tutorials/android-tutorial-4/jni/Application.mk b/examples/tutorials/android-tutorial-1/jni/Application.mk similarity index 100% rename from tutorials/android-tutorial-4/jni/Application.mk rename to examples/tutorials/android-tutorial-1/jni/Application.mk diff --git a/tutorials/android-tutorial-1/jni/tutorial-1.c b/examples/tutorials/android-tutorial-1/jni/tutorial-1.c similarity index 100% rename from tutorials/android-tutorial-1/jni/tutorial-1.c rename to examples/tutorials/android-tutorial-1/jni/tutorial-1.c diff --git a/tutorials/android-tutorial-1/res/drawable-hdpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-hdpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-hdpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-hdpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/drawable-ldpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-ldpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-ldpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-ldpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/drawable-mdpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-mdpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-mdpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-mdpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/drawable-xhdpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-xhdpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-xhdpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-xhdpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/drawable-xxhdpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-xxhdpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-xxhdpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-xxhdpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/drawable-xxxhdpi/gstreamer_logo_1.png b/examples/tutorials/android-tutorial-1/res/drawable-xxxhdpi/gstreamer_logo_1.png similarity index 100% rename from tutorials/android-tutorial-1/res/drawable-xxxhdpi/gstreamer_logo_1.png rename to examples/tutorials/android-tutorial-1/res/drawable-xxxhdpi/gstreamer_logo_1.png diff --git a/tutorials/android-tutorial-1/res/layout/main.xml b/examples/tutorials/android-tutorial-1/res/layout/main.xml similarity index 94% rename from tutorials/android-tutorial-1/res/layout/main.xml rename to examples/tutorials/android-tutorial-1/res/layout/main.xml index 5cf846b..a7dc6da 100644 --- a/tutorials/android-tutorial-1/res/layout/main.xml +++ b/examples/tutorials/android-tutorial-1/res/layout/main.xml @@ -1,14 +1,14 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/android-tutorial-1/res/values/strings.xml b/examples/tutorials/android-tutorial-1/res/values/strings.xml similarity index 100% rename from tutorials/android-tutorial-1/res/values/strings.xml rename to examples/tutorials/android-tutorial-1/res/values/strings.xml diff --git a/tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java b/examples/tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java similarity index 97% rename from tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java rename to examples/tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java index 74fd9f5..34c3618 100644 --- a/tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java +++ b/examples/tutorials/android-tutorial-1/src/org/freedesktop/gstreamer/tutorials/tutorial_1/Tutorial1.java @@ -20,7 +20,7 @@ public class Tutorial1 extends Activity { GStreamer.init(this); } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - finish(); + finish(); return; } diff --git a/tutorials/android-tutorial-2/AndroidManifest.xml b/examples/tutorials/android-tutorial-2/AndroidManifest.xml similarity index 98% rename from tutorials/android-tutorial-2/AndroidManifest.xml rename to examples/tutorials/android-tutorial-2/AndroidManifest.xml index 5f8dbcc..cddedbf 100644 --- a/tutorials/android-tutorial-2/AndroidManifest.xml +++ b/examples/tutorials/android-tutorial-2/AndroidManifest.xml @@ -14,4 +14,4 @@ - + diff --git a/tutorials/android-tutorial-2/jni/Android.mk b/examples/tutorials/android-tutorial-2/jni/Android.mk similarity index 100% rename from tutorials/android-tutorial-2/jni/Android.mk rename to examples/tutorials/android-tutorial-2/jni/Android.mk diff --git a/tutorials/android-tutorial-3/jni/Application.mk b/examples/tutorials/android-tutorial-2/jni/Application.mk similarity index 100% rename from tutorials/android-tutorial-3/jni/Application.mk rename to examples/tutorials/android-tutorial-2/jni/Application.mk diff --git a/tutorials/android-tutorial-2/jni/tutorial-2.c b/examples/tutorials/android-tutorial-2/jni/tutorial-2.c similarity index 100% rename from tutorials/android-tutorial-2/jni/tutorial-2.c rename to examples/tutorials/android-tutorial-2/jni/tutorial-2.c diff --git a/tutorials/android-tutorial-2/res/drawable-hdpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-hdpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-hdpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-hdpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/drawable-ldpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-ldpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-ldpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-ldpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/drawable-mdpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-mdpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-mdpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-mdpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/drawable-xhdpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-xhdpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-xhdpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-xhdpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/drawable-xxhdpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-xxhdpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-xxhdpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-xxhdpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/drawable-xxxhdpi/gstreamer_logo_2.png b/examples/tutorials/android-tutorial-2/res/drawable-xxxhdpi/gstreamer_logo_2.png similarity index 100% rename from tutorials/android-tutorial-2/res/drawable-xxxhdpi/gstreamer_logo_2.png rename to examples/tutorials/android-tutorial-2/res/drawable-xxxhdpi/gstreamer_logo_2.png diff --git a/tutorials/android-tutorial-2/res/layout/main.xml b/examples/tutorials/android-tutorial-2/res/layout/main.xml similarity index 96% rename from tutorials/android-tutorial-2/res/layout/main.xml rename to examples/tutorials/android-tutorial-2/res/layout/main.xml index 2399033..7129dfc 100644 --- a/tutorials/android-tutorial-2/res/layout/main.xml +++ b/examples/tutorials/android-tutorial-2/res/layout/main.xml @@ -1,38 +1,38 @@ - - - - - - - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/tutorials/android-tutorial-2/res/values/strings.xml b/examples/tutorials/android-tutorial-2/res/values/strings.xml similarity index 100% rename from tutorials/android-tutorial-2/res/values/strings.xml rename to examples/tutorials/android-tutorial-2/res/values/strings.xml diff --git a/tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java b/examples/tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java similarity index 99% rename from tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java rename to examples/tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java index c1f6068..5bc880b 100644 --- a/tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java +++ b/examples/tutorials/android-tutorial-2/src/org/freedesktop/gstreamer/tutorials/tutorial_2/Tutorial2.java @@ -32,7 +32,7 @@ public class Tutorial2 extends Activity { GStreamer.init(this); } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - finish(); + finish(); return; } diff --git a/tutorials/android-tutorial-3/AndroidManifest.xml b/examples/tutorials/android-tutorial-3/AndroidManifest.xml similarity index 98% rename from tutorials/android-tutorial-3/AndroidManifest.xml rename to examples/tutorials/android-tutorial-3/AndroidManifest.xml index 6817677..1ac1cba 100644 --- a/tutorials/android-tutorial-3/AndroidManifest.xml +++ b/examples/tutorials/android-tutorial-3/AndroidManifest.xml @@ -15,4 +15,4 @@ - + diff --git a/tutorials/android-tutorial-3/jni/Android.mk b/examples/tutorials/android-tutorial-3/jni/Android.mk similarity index 100% rename from tutorials/android-tutorial-3/jni/Android.mk rename to examples/tutorials/android-tutorial-3/jni/Android.mk diff --git a/tutorials/android-tutorial-2/jni/Application.mk b/examples/tutorials/android-tutorial-3/jni/Application.mk similarity index 100% rename from tutorials/android-tutorial-2/jni/Application.mk rename to examples/tutorials/android-tutorial-3/jni/Application.mk diff --git a/tutorials/android-tutorial-3/jni/tutorial-3.c b/examples/tutorials/android-tutorial-3/jni/tutorial-3.c similarity index 100% rename from tutorials/android-tutorial-3/jni/tutorial-3.c rename to examples/tutorials/android-tutorial-3/jni/tutorial-3.c diff --git a/tutorials/android-tutorial-3/res/drawable-hdpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-hdpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-hdpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-hdpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/drawable-ldpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-ldpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-ldpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-ldpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/drawable-mdpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-mdpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-mdpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-mdpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/drawable-xhdpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-xhdpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-xhdpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-xhdpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/drawable-xxhdpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-xxhdpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-xxhdpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-xxhdpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/drawable-xxxhdpi/gstreamer_logo_3.png b/examples/tutorials/android-tutorial-3/res/drawable-xxxhdpi/gstreamer_logo_3.png similarity index 100% rename from tutorials/android-tutorial-3/res/drawable-xxxhdpi/gstreamer_logo_3.png rename to examples/tutorials/android-tutorial-3/res/drawable-xxxhdpi/gstreamer_logo_3.png diff --git a/tutorials/android-tutorial-3/res/layout/main.xml b/examples/tutorials/android-tutorial-3/res/layout/main.xml similarity index 97% rename from tutorials/android-tutorial-3/res/layout/main.xml rename to examples/tutorials/android-tutorial-3/res/layout/main.xml index 9b1218d..f709226 100644 --- a/tutorials/android-tutorial-3/res/layout/main.xml +++ b/examples/tutorials/android-tutorial-3/res/layout/main.xml @@ -1,45 +1,45 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/tutorials/android-tutorial-3/res/values/strings.xml b/examples/tutorials/android-tutorial-3/res/values/strings.xml similarity index 100% rename from tutorials/android-tutorial-3/res/values/strings.xml rename to examples/tutorials/android-tutorial-3/res/values/strings.xml diff --git a/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/GStreamerSurfaceView.java b/examples/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/GStreamerSurfaceView.java similarity index 100% rename from tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/GStreamerSurfaceView.java rename to examples/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/GStreamerSurfaceView.java diff --git a/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java b/examples/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java similarity index 99% rename from tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java rename to examples/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java index 1be3bf7..cc61017 100644 --- a/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java +++ b/examples/tutorials/android-tutorial-3/src/org/freedesktop/gstreamer/tutorial_3/Tutorial3.java @@ -36,7 +36,7 @@ public class Tutorial3 extends Activity implements SurfaceHolder.Callback { GStreamer.init(this); } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - finish(); + finish(); return; } diff --git a/tutorials/android-tutorial-4/AndroidManifest.xml b/examples/tutorials/android-tutorial-4/AndroidManifest.xml similarity index 98% rename from tutorials/android-tutorial-4/AndroidManifest.xml rename to examples/tutorials/android-tutorial-4/AndroidManifest.xml index c03e7fc..9885cc1 100644 --- a/tutorials/android-tutorial-4/AndroidManifest.xml +++ b/examples/tutorials/android-tutorial-4/AndroidManifest.xml @@ -16,4 +16,4 @@ - + diff --git a/tutorials/android-tutorial-4/jni/Android.mk b/examples/tutorials/android-tutorial-4/jni/Android.mk similarity index 100% rename from tutorials/android-tutorial-4/jni/Android.mk rename to examples/tutorials/android-tutorial-4/jni/Android.mk diff --git a/tutorials/android-tutorial-1/jni/Application.mk b/examples/tutorials/android-tutorial-4/jni/Application.mk similarity index 100% rename from tutorials/android-tutorial-1/jni/Application.mk rename to examples/tutorials/android-tutorial-4/jni/Application.mk diff --git a/tutorials/android-tutorial-4/jni/tutorial-4.c b/examples/tutorials/android-tutorial-4/jni/tutorial-4.c similarity index 97% rename from tutorials/android-tutorial-4/jni/tutorial-4.c rename to examples/tutorials/android-tutorial-4/jni/tutorial-4.c index 192ae9a..e792161 100644 --- a/tutorials/android-tutorial-4/jni/tutorial-4.c +++ b/examples/tutorials/android-tutorial-4/jni/tutorial-4.c @@ -1,562 +1,562 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -GST_DEBUG_CATEGORY_STATIC (debug_category); -#define GST_CAT_DEFAULT debug_category - -/* - * These macros provide a way to store the native pointer to CustomData, which might be 32 or 64 bits, into - * a jlong, which is always 64 bits, without warnings. - */ -#if GLIB_SIZEOF_VOID_P == 8 -# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(*env)->GetLongField (env, thiz, fieldID) -# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)data) -#else -# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(jint)(*env)->GetLongField (env, thiz, fieldID) -# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)(jint)data) -#endif - -/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably - * confuse some demuxers. */ -#define SEEK_MIN_DELAY (500 * GST_MSECOND) - -/* Structure to contain all our information, so we can pass it to callbacks */ -typedef struct _CustomData { - jobject app; /* Application instance, used to call its methods. A global reference is kept. */ - GstElement *pipeline; /* The running pipeline */ - GMainContext *context; /* GLib context used to run the main loop */ - GMainLoop *main_loop; /* GLib main loop */ - gboolean initialized; /* To avoid informing the UI multiple times about the initialization */ - ANativeWindow *native_window; /* The Android native window where video will be rendered */ - GstState state; /* Current pipeline state */ - GstState target_state; /* Desired pipeline state, to be set once buffering is complete */ - gint64 duration; /* Cached clip duration */ - gint64 desired_position; /* Position to seek to, once the pipeline is running */ - GstClockTime last_seek_time; /* For seeking overflow prevention (throttling) */ - gboolean is_live; /* Live streams do not use buffering */ -} CustomData; - -/* playbin flags */ -typedef enum { - GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ -} GstPlayFlags; - -/* These global variables cache values which are not changing during execution */ -static pthread_t gst_app_thread; -static pthread_key_t current_jni_env; -static JavaVM *java_vm; -static jfieldID custom_data_field_id; -static jmethodID set_message_method_id; -static jmethodID set_current_position_method_id; -static jmethodID on_gstreamer_initialized_method_id; -static jmethodID on_media_size_changed_method_id; - -/* - * Private methods - */ - -/* Register this thread with the VM */ -static JNIEnv *attach_current_thread (void) { - JNIEnv *env; - JavaVMAttachArgs args; - - GST_DEBUG ("Attaching thread %p", g_thread_self ()); - args.version = JNI_VERSION_1_4; - args.name = NULL; - args.group = NULL; - - if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) { - GST_ERROR ("Failed to attach current thread"); - return NULL; - } - - return env; -} - -/* Unregister this thread from the VM */ -static void detach_current_thread (void *env) { - GST_DEBUG ("Detaching thread %p", g_thread_self ()); - (*java_vm)->DetachCurrentThread (java_vm); -} - -/* Retrieve the JNI environment for this thread */ -static JNIEnv *get_jni_env (void) { - JNIEnv *env; - - if ((env = pthread_getspecific (current_jni_env)) == NULL) { - env = attach_current_thread (); - pthread_setspecific (current_jni_env, env); - } - - return env; -} - -/* Change the content of the UI's TextView */ -static void set_ui_message (const gchar *message, CustomData *data) { - JNIEnv *env = get_jni_env (); - GST_DEBUG ("Setting message to: %s", message); - jstring jmessage = (*env)->NewStringUTF(env, message); - (*env)->CallVoidMethod (env, data->app, set_message_method_id, jmessage); - if ((*env)->ExceptionCheck (env)) { - GST_ERROR ("Failed to call Java method"); - (*env)->ExceptionClear (env); - } - (*env)->DeleteLocalRef (env, jmessage); -} - -/* Tell the application what is the current position and clip duration */ -static void set_current_ui_position (gint position, gint duration, CustomData *data) { - JNIEnv *env = get_jni_env (); - (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); - if ((*env)->ExceptionCheck (env)) { - GST_ERROR ("Failed to call Java method"); - (*env)->ExceptionClear (env); - } -} - -/* If we have pipeline and it is running, query the current position and clip duration and inform - * the application */ -static gboolean refresh_ui (CustomData *data) { - gint64 current = -1; - gint64 position; - - /* We do not want to update anything unless we have a working pipeline in the PAUSED or PLAYING state */ - if (!data || !data->pipeline || data->state < GST_STATE_PAUSED) - return TRUE; - - /* If we didn't know it yet, query the stream duration */ - if (!GST_CLOCK_TIME_IS_VALID (data->duration)) { - if (!gst_element_query_duration (data->pipeline, GST_FORMAT_TIME, &data->duration)) { - GST_WARNING ("Could not query current duration"); - } - } - - if (gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position)) { - /* Java expects these values in milliseconds, and GStreamer provides nanoseconds */ - set_current_ui_position (position / GST_MSECOND, data->duration / GST_MSECOND, data); - } - return TRUE; -} - -/* Forward declaration for the delayed seek callback */ -static gboolean delayed_seek_cb (CustomData *data); - -/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for - * some time in the future. */ -static void execute_seek (gint64 desired_position, CustomData *data) { - gint64 diff; - - if (desired_position == GST_CLOCK_TIME_NONE) - return; - - diff = gst_util_get_timestamp () - data->last_seek_time; - - if (GST_CLOCK_TIME_IS_VALID (data->last_seek_time) && diff < SEEK_MIN_DELAY) { - /* The previous seek was too close, delay this one */ - GSource *timeout_source; - - if (data->desired_position == GST_CLOCK_TIME_NONE) { - /* There was no previous seek scheduled. Setup a timer for some time in the future */ - timeout_source = g_timeout_source_new ((SEEK_MIN_DELAY - diff) / GST_MSECOND); - g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL); - g_source_attach (timeout_source, data->context); - g_source_unref (timeout_source); - } - /* Update the desired seek position. If multiple requests are received before it is time - * to perform a seek, only the last one is remembered. */ - data->desired_position = desired_position; - GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, - GST_TIME_ARGS (desired_position), GST_TIME_ARGS (SEEK_MIN_DELAY - diff)); - } else { - /* Perform the seek now */ - GST_DEBUG ("Seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (desired_position)); - data->last_seek_time = gst_util_get_timestamp (); - gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); - data->desired_position = GST_CLOCK_TIME_NONE; - } -} - -/* Delayed seek callback. This gets called by the timer setup in the above function. */ -static gboolean delayed_seek_cb (CustomData *data) { - GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (data->desired_position)); - execute_seek (data->desired_position, data); - return FALSE; -} - -/* Retrieve errors from the bus and show them on the UI */ -static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GError *err; - gchar *debug_info; - gchar *message_string; - - gst_message_parse_error (msg, &err, &debug_info); - message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); - g_clear_error (&err); - g_free (debug_info); - set_ui_message (message_string, data); - g_free (message_string); - data->target_state = GST_STATE_NULL; - gst_element_set_state (data->pipeline, GST_STATE_NULL); -} - -/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */ -static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - data->target_state = GST_STATE_PAUSED; - data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); - execute_seek (0, data); -} - -/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */ -static void duration_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - data->duration = GST_CLOCK_TIME_NONE; -} - -/* Called when buffering messages are received. We inform the UI about the current buffering level and - * keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */ -static void buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - gint percent; - - if (data->is_live) - return; - - gst_message_parse_buffering (msg, &percent); - if (percent < 100 && data->target_state >= GST_STATE_PAUSED) { - gchar * message_string = g_strdup_printf ("Buffering %d%%", percent); - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - set_ui_message (message_string, data); - g_free (message_string); - } else if (data->target_state >= GST_STATE_PLAYING) { - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); - } else if (data->target_state >= GST_STATE_PAUSED) { - set_ui_message ("Buffering complete", data); - } -} - -/* Called when the clock is lost */ -static void clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - if (data->target_state >= GST_STATE_PLAYING) { - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); - } -} - -/* Retrieve the video sink's Caps and tell the application about the media size */ -static void check_media_size (CustomData *data) { - JNIEnv *env = get_jni_env (); - GstElement *video_sink; - GstPad *video_sink_pad; - GstCaps *caps; - GstVideoInfo info; - - /* Retrieve the Caps at the entrance of the video sink */ - g_object_get (data->pipeline, "video-sink", &video_sink, NULL); - video_sink_pad = gst_element_get_static_pad (video_sink, "sink"); - caps = gst_pad_get_current_caps (video_sink_pad); - - if (gst_video_info_from_caps (&info, caps)) { - info.width = info.width * info.par_n / info.par_d; - GST_DEBUG ("Media size is %dx%d, notifying application", info.width, info.height); - - (*env)->CallVoidMethod (env, data->app, on_media_size_changed_method_id, (jint)info.width, (jint)info.height); - if ((*env)->ExceptionCheck (env)) { - GST_ERROR ("Failed to call Java method"); - (*env)->ExceptionClear (env); - } - } - - gst_caps_unref(caps); - gst_object_unref (video_sink_pad); - gst_object_unref(video_sink); -} - -/* Notify UI about pipeline state changes */ -static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - /* Only pay attention to messages coming from the pipeline, not its children */ - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { - data->state = new_state; - gchar *message = g_strdup_printf("State changed to %s", gst_element_state_get_name(new_state)); - set_ui_message(message, data); - g_free (message); - - /* The Ready to Paused state change is particularly interesting: */ - if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) { - /* By now the sink already knows the media size */ - check_media_size(data); - - /* If there was a scheduled seek, perform it now that we have moved to the Paused state */ - if (GST_CLOCK_TIME_IS_VALID (data->desired_position)) - execute_seek (data->desired_position, data); - } - } -} - -/* Check if all conditions are met to report GStreamer as initialized. - * These conditions will change depending on the application */ -static void check_initialization_complete (CustomData *data) { - JNIEnv *env = get_jni_env (); - if (!data->initialized && data->native_window && data->main_loop) { - GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%p", data->native_window, data->main_loop); - - /* The main loop is running and we received a native window, inform the sink about it */ - gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->pipeline), (guintptr)data->native_window); - - (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); - if ((*env)->ExceptionCheck (env)) { - GST_ERROR ("Failed to call Java method"); - (*env)->ExceptionClear (env); - } - data->initialized = TRUE; - } -} - -/* Main method for the native code. This is executed on its own thread. */ -static void *app_function (void *userdata) { - JavaVMAttachArgs args; - GstBus *bus; - CustomData *data = (CustomData *)userdata; - GSource *timeout_source; - GSource *bus_source; - GError *error = NULL; - guint flags; - - GST_DEBUG ("Creating pipeline in CustomData at %p", data); - - /* Create our own GLib Main Context and make it the default one */ - data->context = g_main_context_new (); - g_main_context_push_thread_default(data->context); - - /* Build pipeline */ - data->pipeline = gst_parse_launch("playbin", &error); - if (error) { - gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message); - g_clear_error (&error); - set_ui_message(message, data); - g_free (message); - return NULL; - } - - /* Disable subtitles */ - g_object_get (data->pipeline, "flags", &flags, NULL); - flags &= ~GST_PLAY_FLAG_TEXT; - g_object_set (data->pipeline, "flags", flags, NULL); - - /* Set the pipeline to READY, so it can already accept a window handle, if we have one */ - data->target_state = GST_STATE_READY; - gst_element_set_state(data->pipeline, GST_STATE_READY); - - /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ - bus = gst_element_get_bus (data->pipeline); - bus_source = gst_bus_create_watch (bus); - g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); - g_source_attach (bus_source, data->context); - g_source_unref (bus_source); - g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); - g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); - g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); - g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, data); - g_signal_connect (G_OBJECT (bus), "message::buffering", (GCallback)buffering_cb, data); - g_signal_connect (G_OBJECT (bus), "message::clock-lost", (GCallback)clock_lost_cb, data); - gst_object_unref (bus); - - /* Register a function that GLib will call 4 times per second */ - timeout_source = g_timeout_source_new (250); - g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL); - g_source_attach (timeout_source, data->context); - g_source_unref (timeout_source); - - /* Create a GLib Main Loop and set it to run */ - GST_DEBUG ("Entering main loop... (CustomData:%p)", data); - data->main_loop = g_main_loop_new (data->context, FALSE); - check_initialization_complete (data); - g_main_loop_run (data->main_loop); - GST_DEBUG ("Exited main loop"); - g_main_loop_unref (data->main_loop); - data->main_loop = NULL; - - /* Free resources */ - g_main_context_pop_thread_default(data->context); - g_main_context_unref (data->context); - data->target_state = GST_STATE_NULL; - gst_element_set_state (data->pipeline, GST_STATE_NULL); - gst_object_unref (data->pipeline); - - return NULL; -} - -/* - * Java Bindings - */ - -/* Instruct the native code to create its internal data structure, pipeline and thread */ -static void gst_native_init (JNIEnv* env, jobject thiz) { - CustomData *data = g_new0 (CustomData, 1); - data->desired_position = GST_CLOCK_TIME_NONE; - data->last_seek_time = GST_CLOCK_TIME_NONE; - SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); - GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-4", 0, "Android tutorial 4"); - gst_debug_set_threshold_for_name("tutorial-4", GST_LEVEL_DEBUG); - GST_DEBUG ("Created CustomData at %p", data); - data->app = (*env)->NewGlobalRef (env, thiz); - GST_DEBUG ("Created GlobalRef for app object at %p", data->app); - pthread_create (&gst_app_thread, NULL, &app_function, data); -} - -/* Quit the main loop, remove the native thread and free resources */ -static void gst_native_finalize (JNIEnv* env, jobject thiz) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - GST_DEBUG ("Quitting main loop..."); - g_main_loop_quit (data->main_loop); - GST_DEBUG ("Waiting for thread to finish..."); - pthread_join (gst_app_thread, NULL); - GST_DEBUG ("Deleting GlobalRef for app object at %p", data->app); - (*env)->DeleteGlobalRef (env, data->app); - GST_DEBUG ("Freeing CustomData at %p", data); - g_free (data); - SET_CUSTOM_DATA (env, thiz, custom_data_field_id, NULL); - GST_DEBUG ("Done finalizing"); -} - -/* Set playbin's URI */ -void gst_native_set_uri (JNIEnv* env, jobject thiz, jstring uri) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data || !data->pipeline) return; - const jbyte *char_uri = (*env)->GetStringUTFChars (env, uri, NULL); - GST_DEBUG ("Setting URI to %s", char_uri); - if (data->target_state >= GST_STATE_READY) - gst_element_set_state (data->pipeline, GST_STATE_READY); - g_object_set(data->pipeline, "uri", char_uri, NULL); - (*env)->ReleaseStringUTFChars (env, uri, char_uri); - data->duration = GST_CLOCK_TIME_NONE; - data->is_live = (gst_element_set_state (data->pipeline, data->target_state) == GST_STATE_CHANGE_NO_PREROLL); -} - -/* Set pipeline to PLAYING state */ -static void gst_native_play (JNIEnv* env, jobject thiz) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - GST_DEBUG ("Setting state to PLAYING"); - data->target_state = GST_STATE_PLAYING; - data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); -} - -/* Set pipeline to PAUSED state */ -static void gst_native_pause (JNIEnv* env, jobject thiz) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - GST_DEBUG ("Setting state to PAUSED"); - data->target_state = GST_STATE_PAUSED; - data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); -} - -/* Instruct the pipeline to seek to a different position */ -void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - gint64 desired_position = (gint64)(milliseconds * GST_MSECOND); - if (data->state >= GST_STATE_PAUSED) { - execute_seek(desired_position, data); - } else { - GST_DEBUG ("Scheduling seek to %" GST_TIME_FORMAT " for later", GST_TIME_ARGS (desired_position)); - data->desired_position = desired_position; - } -} - -/* Static class initializer: retrieve method and field IDs */ -static jboolean gst_native_class_init (JNIEnv* env, jclass klass) { - custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); - set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); - set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(II)V"); - on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V"); - on_media_size_changed_method_id = (*env)->GetMethodID (env, klass, "onMediaSizeChanged", "(II)V"); - - if (!custom_data_field_id || !set_message_method_id || !on_gstreamer_initialized_method_id || - !on_media_size_changed_method_id || !set_current_position_method_id) { - /* We emit this message through the Android log instead of the GStreamer log because the later - * has not been initialized yet. - */ - __android_log_print (ANDROID_LOG_ERROR, "tutorial-4", "The calling class does not implement all necessary interface methods"); - return JNI_FALSE; - } - return JNI_TRUE; -} - -static void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - ANativeWindow *new_native_window = ANativeWindow_fromSurface(env, surface); - GST_DEBUG ("Received surface %p (native window %p)", surface, new_native_window); - - if (data->native_window) { - ANativeWindow_release (data->native_window); - if (data->native_window == new_native_window) { - GST_DEBUG ("New native window is the same as the previous one %p", data->native_window); - if (data->pipeline) { - gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->pipeline)); - gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->pipeline)); - } - return; - } else { - GST_DEBUG ("Released previous native window %p", data->native_window); - data->initialized = FALSE; - } - } - data->native_window = new_native_window; - - check_initialization_complete (data); -} - -static void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { - CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); - if (!data) return; - GST_DEBUG ("Releasing Native Window %p", data->native_window); - - if (data->pipeline) { - gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->pipeline), (guintptr)NULL); - gst_element_set_state (data->pipeline, GST_STATE_READY); - } - - ANativeWindow_release (data->native_window); - data->native_window = NULL; - data->initialized = FALSE; -} - -/* List of implemented native methods */ -static JNINativeMethod native_methods[] = { - { "nativeInit", "()V", (void *) gst_native_init}, - { "nativeFinalize", "()V", (void *) gst_native_finalize}, - { "nativeSetUri", "(Ljava/lang/String;)V", (void *) gst_native_set_uri}, - { "nativePlay", "()V", (void *) gst_native_play}, - { "nativePause", "()V", (void *) gst_native_pause}, - { "nativeSetPosition", "(I)V", (void*) gst_native_set_position}, - { "nativeSurfaceInit", "(Ljava/lang/Object;)V", (void *) gst_native_surface_init}, - { "nativeSurfaceFinalize", "()V", (void *) gst_native_surface_finalize}, - { "nativeClassInit", "()Z", (void *) gst_native_class_init} -}; - -/* Library initializer */ -jint JNI_OnLoad(JavaVM *vm, void *reserved) { - JNIEnv *env = NULL; - - java_vm = vm; - - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { - __android_log_print (ANDROID_LOG_ERROR, "tutorial-4", "Could not retrieve JNIEnv"); - return 0; - } - jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_4/Tutorial4"); - (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); - - pthread_key_create (¤t_jni_env, detach_current_thread); - - return JNI_VERSION_1_4; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (debug_category); +#define GST_CAT_DEFAULT debug_category + +/* + * These macros provide a way to store the native pointer to CustomData, which might be 32 or 64 bits, into + * a jlong, which is always 64 bits, without warnings. + */ +#if GLIB_SIZEOF_VOID_P == 8 +# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(*env)->GetLongField (env, thiz, fieldID) +# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)data) +#else +# define GET_CUSTOM_DATA(env, thiz, fieldID) (CustomData *)(jint)(*env)->GetLongField (env, thiz, fieldID) +# define SET_CUSTOM_DATA(env, thiz, fieldID, data) (*env)->SetLongField (env, thiz, fieldID, (jlong)(jint)data) +#endif + +/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably + * confuse some demuxers. */ +#define SEEK_MIN_DELAY (500 * GST_MSECOND) + +/* Structure to contain all our information, so we can pass it to callbacks */ +typedef struct _CustomData { + jobject app; /* Application instance, used to call its methods. A global reference is kept. */ + GstElement *pipeline; /* The running pipeline */ + GMainContext *context; /* GLib context used to run the main loop */ + GMainLoop *main_loop; /* GLib main loop */ + gboolean initialized; /* To avoid informing the UI multiple times about the initialization */ + ANativeWindow *native_window; /* The Android native window where video will be rendered */ + GstState state; /* Current pipeline state */ + GstState target_state; /* Desired pipeline state, to be set once buffering is complete */ + gint64 duration; /* Cached clip duration */ + gint64 desired_position; /* Position to seek to, once the pipeline is running */ + GstClockTime last_seek_time; /* For seeking overflow prevention (throttling) */ + gboolean is_live; /* Live streams do not use buffering */ +} CustomData; + +/* playbin flags */ +typedef enum { + GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ +} GstPlayFlags; + +/* These global variables cache values which are not changing during execution */ +static pthread_t gst_app_thread; +static pthread_key_t current_jni_env; +static JavaVM *java_vm; +static jfieldID custom_data_field_id; +static jmethodID set_message_method_id; +static jmethodID set_current_position_method_id; +static jmethodID on_gstreamer_initialized_method_id; +static jmethodID on_media_size_changed_method_id; + +/* + * Private methods + */ + +/* Register this thread with the VM */ +static JNIEnv *attach_current_thread (void) { + JNIEnv *env; + JavaVMAttachArgs args; + + GST_DEBUG ("Attaching thread %p", g_thread_self ()); + args.version = JNI_VERSION_1_4; + args.name = NULL; + args.group = NULL; + + if ((*java_vm)->AttachCurrentThread (java_vm, &env, &args) < 0) { + GST_ERROR ("Failed to attach current thread"); + return NULL; + } + + return env; +} + +/* Unregister this thread from the VM */ +static void detach_current_thread (void *env) { + GST_DEBUG ("Detaching thread %p", g_thread_self ()); + (*java_vm)->DetachCurrentThread (java_vm); +} + +/* Retrieve the JNI environment for this thread */ +static JNIEnv *get_jni_env (void) { + JNIEnv *env; + + if ((env = pthread_getspecific (current_jni_env)) == NULL) { + env = attach_current_thread (); + pthread_setspecific (current_jni_env, env); + } + + return env; +} + +/* Change the content of the UI's TextView */ +static void set_ui_message (const gchar *message, CustomData *data) { + JNIEnv *env = get_jni_env (); + GST_DEBUG ("Setting message to: %s", message); + jstring jmessage = (*env)->NewStringUTF(env, message); + (*env)->CallVoidMethod (env, data->app, set_message_method_id, jmessage); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } + (*env)->DeleteLocalRef (env, jmessage); +} + +/* Tell the application what is the current position and clip duration */ +static void set_current_ui_position (gint position, gint duration, CustomData *data) { + JNIEnv *env = get_jni_env (); + (*env)->CallVoidMethod (env, data->app, set_current_position_method_id, position, duration); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } +} + +/* If we have pipeline and it is running, query the current position and clip duration and inform + * the application */ +static gboolean refresh_ui (CustomData *data) { + gint64 current = -1; + gint64 position; + + /* We do not want to update anything unless we have a working pipeline in the PAUSED or PLAYING state */ + if (!data || !data->pipeline || data->state < GST_STATE_PAUSED) + return TRUE; + + /* If we didn't know it yet, query the stream duration */ + if (!GST_CLOCK_TIME_IS_VALID (data->duration)) { + if (!gst_element_query_duration (data->pipeline, GST_FORMAT_TIME, &data->duration)) { + GST_WARNING ("Could not query current duration"); + } + } + + if (gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position)) { + /* Java expects these values in milliseconds, and GStreamer provides nanoseconds */ + set_current_ui_position (position / GST_MSECOND, data->duration / GST_MSECOND, data); + } + return TRUE; +} + +/* Forward declaration for the delayed seek callback */ +static gboolean delayed_seek_cb (CustomData *data); + +/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for + * some time in the future. */ +static void execute_seek (gint64 desired_position, CustomData *data) { + gint64 diff; + + if (desired_position == GST_CLOCK_TIME_NONE) + return; + + diff = gst_util_get_timestamp () - data->last_seek_time; + + if (GST_CLOCK_TIME_IS_VALID (data->last_seek_time) && diff < SEEK_MIN_DELAY) { + /* The previous seek was too close, delay this one */ + GSource *timeout_source; + + if (data->desired_position == GST_CLOCK_TIME_NONE) { + /* There was no previous seek scheduled. Setup a timer for some time in the future */ + timeout_source = g_timeout_source_new ((SEEK_MIN_DELAY - diff) / GST_MSECOND); + g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, data, NULL); + g_source_attach (timeout_source, data->context); + g_source_unref (timeout_source); + } + /* Update the desired seek position. If multiple requests are received before it is time + * to perform a seek, only the last one is remembered. */ + data->desired_position = desired_position; + GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, + GST_TIME_ARGS (desired_position), GST_TIME_ARGS (SEEK_MIN_DELAY - diff)); + } else { + /* Perform the seek now */ + GST_DEBUG ("Seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (desired_position)); + data->last_seek_time = gst_util_get_timestamp (); + gst_element_seek_simple (data->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, desired_position); + data->desired_position = GST_CLOCK_TIME_NONE; + } +} + +/* Delayed seek callback. This gets called by the timer setup in the above function. */ +static gboolean delayed_seek_cb (CustomData *data) { + GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (data->desired_position)); + execute_seek (data->desired_position, data); + return FALSE; +} + +/* Retrieve errors from the bus and show them on the UI */ +static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GError *err; + gchar *debug_info; + gchar *message_string; + + gst_message_parse_error (msg, &err, &debug_info); + message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); + g_clear_error (&err); + g_free (debug_info); + set_ui_message (message_string, data); + g_free (message_string); + data->target_state = GST_STATE_NULL; + gst_element_set_state (data->pipeline, GST_STATE_NULL); +} + +/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */ +static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + data->target_state = GST_STATE_PAUSED; + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); + execute_seek (0, data); +} + +/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */ +static void duration_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + data->duration = GST_CLOCK_TIME_NONE; +} + +/* Called when buffering messages are received. We inform the UI about the current buffering level and + * keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */ +static void buffering_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + gint percent; + + if (data->is_live) + return; + + gst_message_parse_buffering (msg, &percent); + if (percent < 100 && data->target_state >= GST_STATE_PAUSED) { + gchar * message_string = g_strdup_printf ("Buffering %d%%", percent); + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + set_ui_message (message_string, data); + g_free (message_string); + } else if (data->target_state >= GST_STATE_PLAYING) { + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + } else if (data->target_state >= GST_STATE_PAUSED) { + set_ui_message ("Buffering complete", data); + } +} + +/* Called when the clock is lost */ +static void clock_lost_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + if (data->target_state >= GST_STATE_PLAYING) { + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + } +} + +/* Retrieve the video sink's Caps and tell the application about the media size */ +static void check_media_size (CustomData *data) { + JNIEnv *env = get_jni_env (); + GstElement *video_sink; + GstPad *video_sink_pad; + GstCaps *caps; + GstVideoInfo info; + + /* Retrieve the Caps at the entrance of the video sink */ + g_object_get (data->pipeline, "video-sink", &video_sink, NULL); + video_sink_pad = gst_element_get_static_pad (video_sink, "sink"); + caps = gst_pad_get_current_caps (video_sink_pad); + + if (gst_video_info_from_caps (&info, caps)) { + info.width = info.width * info.par_n / info.par_d; + GST_DEBUG ("Media size is %dx%d, notifying application", info.width, info.height); + + (*env)->CallVoidMethod (env, data->app, on_media_size_changed_method_id, (jint)info.width, (jint)info.height); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } + } + + gst_caps_unref(caps); + gst_object_unref (video_sink_pad); + gst_object_unref(video_sink); +} + +/* Notify UI about pipeline state changes */ +static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + /* Only pay attention to messages coming from the pipeline, not its children */ + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->pipeline)) { + data->state = new_state; + gchar *message = g_strdup_printf("State changed to %s", gst_element_state_get_name(new_state)); + set_ui_message(message, data); + g_free (message); + + /* The Ready to Paused state change is particularly interesting: */ + if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) { + /* By now the sink already knows the media size */ + check_media_size(data); + + /* If there was a scheduled seek, perform it now that we have moved to the Paused state */ + if (GST_CLOCK_TIME_IS_VALID (data->desired_position)) + execute_seek (data->desired_position, data); + } + } +} + +/* Check if all conditions are met to report GStreamer as initialized. + * These conditions will change depending on the application */ +static void check_initialization_complete (CustomData *data) { + JNIEnv *env = get_jni_env (); + if (!data->initialized && data->native_window && data->main_loop) { + GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%p", data->native_window, data->main_loop); + + /* The main loop is running and we received a native window, inform the sink about it */ + gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->pipeline), (guintptr)data->native_window); + + (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); + if ((*env)->ExceptionCheck (env)) { + GST_ERROR ("Failed to call Java method"); + (*env)->ExceptionClear (env); + } + data->initialized = TRUE; + } +} + +/* Main method for the native code. This is executed on its own thread. */ +static void *app_function (void *userdata) { + JavaVMAttachArgs args; + GstBus *bus; + CustomData *data = (CustomData *)userdata; + GSource *timeout_source; + GSource *bus_source; + GError *error = NULL; + guint flags; + + GST_DEBUG ("Creating pipeline in CustomData at %p", data); + + /* Create our own GLib Main Context and make it the default one */ + data->context = g_main_context_new (); + g_main_context_push_thread_default(data->context); + + /* Build pipeline */ + data->pipeline = gst_parse_launch("playbin", &error); + if (error) { + gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message); + g_clear_error (&error); + set_ui_message(message, data); + g_free (message); + return NULL; + } + + /* Disable subtitles */ + g_object_get (data->pipeline, "flags", &flags, NULL); + flags &= ~GST_PLAY_FLAG_TEXT; + g_object_set (data->pipeline, "flags", flags, NULL); + + /* Set the pipeline to READY, so it can already accept a window handle, if we have one */ + data->target_state = GST_STATE_READY; + gst_element_set_state(data->pipeline, GST_STATE_READY); + + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ + bus = gst_element_get_bus (data->pipeline); + bus_source = gst_bus_create_watch (bus); + g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); + g_source_attach (bus_source, data->context); + g_source_unref (bus_source); + g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, data); + g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, data); + g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, data); + g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, data); + g_signal_connect (G_OBJECT (bus), "message::buffering", (GCallback)buffering_cb, data); + g_signal_connect (G_OBJECT (bus), "message::clock-lost", (GCallback)clock_lost_cb, data); + gst_object_unref (bus); + + /* Register a function that GLib will call 4 times per second */ + timeout_source = g_timeout_source_new (250); + g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL); + g_source_attach (timeout_source, data->context); + g_source_unref (timeout_source); + + /* Create a GLib Main Loop and set it to run */ + GST_DEBUG ("Entering main loop... (CustomData:%p)", data); + data->main_loop = g_main_loop_new (data->context, FALSE); + check_initialization_complete (data); + g_main_loop_run (data->main_loop); + GST_DEBUG ("Exited main loop"); + g_main_loop_unref (data->main_loop); + data->main_loop = NULL; + + /* Free resources */ + g_main_context_pop_thread_default(data->context); + g_main_context_unref (data->context); + data->target_state = GST_STATE_NULL; + gst_element_set_state (data->pipeline, GST_STATE_NULL); + gst_object_unref (data->pipeline); + + return NULL; +} + +/* + * Java Bindings + */ + +/* Instruct the native code to create its internal data structure, pipeline and thread */ +static void gst_native_init (JNIEnv* env, jobject thiz) { + CustomData *data = g_new0 (CustomData, 1); + data->desired_position = GST_CLOCK_TIME_NONE; + data->last_seek_time = GST_CLOCK_TIME_NONE; + SET_CUSTOM_DATA (env, thiz, custom_data_field_id, data); + GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-4", 0, "Android tutorial 4"); + gst_debug_set_threshold_for_name("tutorial-4", GST_LEVEL_DEBUG); + GST_DEBUG ("Created CustomData at %p", data); + data->app = (*env)->NewGlobalRef (env, thiz); + GST_DEBUG ("Created GlobalRef for app object at %p", data->app); + pthread_create (&gst_app_thread, NULL, &app_function, data); +} + +/* Quit the main loop, remove the native thread and free resources */ +static void gst_native_finalize (JNIEnv* env, jobject thiz) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + GST_DEBUG ("Quitting main loop..."); + g_main_loop_quit (data->main_loop); + GST_DEBUG ("Waiting for thread to finish..."); + pthread_join (gst_app_thread, NULL); + GST_DEBUG ("Deleting GlobalRef for app object at %p", data->app); + (*env)->DeleteGlobalRef (env, data->app); + GST_DEBUG ("Freeing CustomData at %p", data); + g_free (data); + SET_CUSTOM_DATA (env, thiz, custom_data_field_id, NULL); + GST_DEBUG ("Done finalizing"); +} + +/* Set playbin's URI */ +void gst_native_set_uri (JNIEnv* env, jobject thiz, jstring uri) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data || !data->pipeline) return; + const jbyte *char_uri = (*env)->GetStringUTFChars (env, uri, NULL); + GST_DEBUG ("Setting URI to %s", char_uri); + if (data->target_state >= GST_STATE_READY) + gst_element_set_state (data->pipeline, GST_STATE_READY); + g_object_set(data->pipeline, "uri", char_uri, NULL); + (*env)->ReleaseStringUTFChars (env, uri, char_uri); + data->duration = GST_CLOCK_TIME_NONE; + data->is_live = (gst_element_set_state (data->pipeline, data->target_state) == GST_STATE_CHANGE_NO_PREROLL); +} + +/* Set pipeline to PLAYING state */ +static void gst_native_play (JNIEnv* env, jobject thiz) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + GST_DEBUG ("Setting state to PLAYING"); + data->target_state = GST_STATE_PLAYING; + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); +} + +/* Set pipeline to PAUSED state */ +static void gst_native_pause (JNIEnv* env, jobject thiz) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + GST_DEBUG ("Setting state to PAUSED"); + data->target_state = GST_STATE_PAUSED; + data->is_live = (gst_element_set_state (data->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); +} + +/* Instruct the pipeline to seek to a different position */ +void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + gint64 desired_position = (gint64)(milliseconds * GST_MSECOND); + if (data->state >= GST_STATE_PAUSED) { + execute_seek(desired_position, data); + } else { + GST_DEBUG ("Scheduling seek to %" GST_TIME_FORMAT " for later", GST_TIME_ARGS (desired_position)); + data->desired_position = desired_position; + } +} + +/* Static class initializer: retrieve method and field IDs */ +static jboolean gst_native_class_init (JNIEnv* env, jclass klass) { + custom_data_field_id = (*env)->GetFieldID (env, klass, "native_custom_data", "J"); + set_message_method_id = (*env)->GetMethodID (env, klass, "setMessage", "(Ljava/lang/String;)V"); + set_current_position_method_id = (*env)->GetMethodID (env, klass, "setCurrentPosition", "(II)V"); + on_gstreamer_initialized_method_id = (*env)->GetMethodID (env, klass, "onGStreamerInitialized", "()V"); + on_media_size_changed_method_id = (*env)->GetMethodID (env, klass, "onMediaSizeChanged", "(II)V"); + + if (!custom_data_field_id || !set_message_method_id || !on_gstreamer_initialized_method_id || + !on_media_size_changed_method_id || !set_current_position_method_id) { + /* We emit this message through the Android log instead of the GStreamer log because the later + * has not been initialized yet. + */ + __android_log_print (ANDROID_LOG_ERROR, "tutorial-4", "The calling class does not implement all necessary interface methods"); + return JNI_FALSE; + } + return JNI_TRUE; +} + +static void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + ANativeWindow *new_native_window = ANativeWindow_fromSurface(env, surface); + GST_DEBUG ("Received surface %p (native window %p)", surface, new_native_window); + + if (data->native_window) { + ANativeWindow_release (data->native_window); + if (data->native_window == new_native_window) { + GST_DEBUG ("New native window is the same as the previous one %p", data->native_window); + if (data->pipeline) { + gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->pipeline)); + gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->pipeline)); + } + return; + } else { + GST_DEBUG ("Released previous native window %p", data->native_window); + data->initialized = FALSE; + } + } + data->native_window = new_native_window; + + check_initialization_complete (data); +} + +static void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { + CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); + if (!data) return; + GST_DEBUG ("Releasing Native Window %p", data->native_window); + + if (data->pipeline) { + gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->pipeline), (guintptr)NULL); + gst_element_set_state (data->pipeline, GST_STATE_READY); + } + + ANativeWindow_release (data->native_window); + data->native_window = NULL; + data->initialized = FALSE; +} + +/* List of implemented native methods */ +static JNINativeMethod native_methods[] = { + { "nativeInit", "()V", (void *) gst_native_init}, + { "nativeFinalize", "()V", (void *) gst_native_finalize}, + { "nativeSetUri", "(Ljava/lang/String;)V", (void *) gst_native_set_uri}, + { "nativePlay", "()V", (void *) gst_native_play}, + { "nativePause", "()V", (void *) gst_native_pause}, + { "nativeSetPosition", "(I)V", (void*) gst_native_set_position}, + { "nativeSurfaceInit", "(Ljava/lang/Object;)V", (void *) gst_native_surface_init}, + { "nativeSurfaceFinalize", "()V", (void *) gst_native_surface_finalize}, + { "nativeClassInit", "()Z", (void *) gst_native_class_init} +}; + +/* Library initializer */ +jint JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv *env = NULL; + + java_vm = vm; + + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { + __android_log_print (ANDROID_LOG_ERROR, "tutorial-4", "Could not retrieve JNIEnv"); + return 0; + } + jclass klass = (*env)->FindClass (env, "com/gst_sdk_tutorials/tutorial_4/Tutorial4"); + (*env)->RegisterNatives (env, klass, native_methods, G_N_ELEMENTS(native_methods)); + + pthread_key_create (¤t_jni_env, detach_current_thread); + + return JNI_VERSION_1_4; +} diff --git a/tutorials/android-tutorial-4/res/drawable-hdpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-hdpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-hdpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-hdpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/drawable-ldpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-ldpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-ldpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-ldpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/drawable-mdpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-mdpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-mdpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-mdpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/drawable-xhdpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-xhdpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-xhdpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-xhdpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/drawable-xxhdpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-xxhdpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-xxhdpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-xxhdpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/drawable-xxxhdpi/gstreamer_logo_4.png b/examples/tutorials/android-tutorial-4/res/drawable-xxxhdpi/gstreamer_logo_4.png similarity index 100% rename from tutorials/android-tutorial-4/res/drawable-xxxhdpi/gstreamer_logo_4.png rename to examples/tutorials/android-tutorial-4/res/drawable-xxxhdpi/gstreamer_logo_4.png diff --git a/tutorials/android-tutorial-4/res/layout/main.xml b/examples/tutorials/android-tutorial-4/res/layout/main.xml similarity index 96% rename from tutorials/android-tutorial-4/res/layout/main.xml rename to examples/tutorials/android-tutorial-4/res/layout/main.xml index e7329d2..a4215ef 100644 --- a/tutorials/android-tutorial-4/res/layout/main.xml +++ b/examples/tutorials/android-tutorial-4/res/layout/main.xml @@ -1,69 +1,69 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tutorials/android-tutorial-4/res/values/strings.xml b/examples/tutorials/android-tutorial-4/res/values/strings.xml similarity index 100% rename from tutorials/android-tutorial-4/res/values/strings.xml rename to examples/tutorials/android-tutorial-4/res/values/strings.xml diff --git a/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/GStreamerSurfaceView.java b/examples/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/GStreamerSurfaceView.java similarity index 100% rename from tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/GStreamerSurfaceView.java rename to examples/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/GStreamerSurfaceView.java diff --git a/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java b/examples/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java similarity index 99% rename from tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java rename to examples/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java index f3d5977..8516cb2 100644 --- a/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java +++ b/examples/tutorials/android-tutorial-4/src/com/gst_sdk_tutorials/tutorial_4/Tutorial4.java @@ -51,7 +51,7 @@ public class Tutorial4 extends Activity implements SurfaceHolder.Callback, OnSee GStreamer.init(this); } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - finish(); + finish(); return; } diff --git a/tutorials/android-tutorial-5/AndroidManifest.xml b/examples/tutorials/android-tutorial-5/AndroidManifest.xml similarity index 100% rename from tutorials/android-tutorial-5/AndroidManifest.xml rename to examples/tutorials/android-tutorial-5/AndroidManifest.xml diff --git a/tutorials/android-tutorial-5/jni/Android.mk b/examples/tutorials/android-tutorial-5/jni/Android.mk similarity index 100% rename from tutorials/android-tutorial-5/jni/Android.mk rename to examples/tutorials/android-tutorial-5/jni/Android.mk diff --git a/examples/tutorials/android-tutorial-5/jni/Application.mk b/examples/tutorials/android-tutorial-5/jni/Application.mk new file mode 100644 index 0000000..b8848e8 --- /dev/null +++ b/examples/tutorials/android-tutorial-5/jni/Application.mk @@ -0,0 +1 @@ +APP_ABI = armeabi armeabi-v7a arm64-v8a x86 x86_64 diff --git a/tutorials/android-tutorial-5/jni/tutorial-5.c b/examples/tutorials/android-tutorial-5/jni/tutorial-5.c similarity index 100% rename from tutorials/android-tutorial-5/jni/tutorial-5.c rename to examples/tutorials/android-tutorial-5/jni/tutorial-5.c diff --git a/tutorials/android-tutorial-5/res/drawable-ldpi/file.png b/examples/tutorials/android-tutorial-5/res/drawable-ldpi/file.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-ldpi/file.png rename to examples/tutorials/android-tutorial-5/res/drawable-ldpi/file.png diff --git a/tutorials/android-tutorial-5/res/drawable-ldpi/folder.png b/examples/tutorials/android-tutorial-5/res/drawable-ldpi/folder.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-ldpi/folder.png rename to examples/tutorials/android-tutorial-5/res/drawable-ldpi/folder.png diff --git a/tutorials/android-tutorial-5/res/drawable-ldpi/gstreamer_logo_5.png b/examples/tutorials/android-tutorial-5/res/drawable-ldpi/gstreamer_logo_5.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-ldpi/gstreamer_logo_5.png rename to examples/tutorials/android-tutorial-5/res/drawable-ldpi/gstreamer_logo_5.png diff --git a/tutorials/android-tutorial-5/res/drawable-mdpi/gstreamer_logo_5.png b/examples/tutorials/android-tutorial-5/res/drawable-mdpi/gstreamer_logo_5.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-mdpi/gstreamer_logo_5.png rename to examples/tutorials/android-tutorial-5/res/drawable-mdpi/gstreamer_logo_5.png diff --git a/tutorials/android-tutorial-5/res/drawable-xhdpi/gstreamer_logo_5.png b/examples/tutorials/android-tutorial-5/res/drawable-xhdpi/gstreamer_logo_5.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-xhdpi/gstreamer_logo_5.png rename to examples/tutorials/android-tutorial-5/res/drawable-xhdpi/gstreamer_logo_5.png diff --git a/tutorials/android-tutorial-5/res/drawable-xxhdpi/gstreamer_logo_5.png b/examples/tutorials/android-tutorial-5/res/drawable-xxhdpi/gstreamer_logo_5.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-xxhdpi/gstreamer_logo_5.png rename to examples/tutorials/android-tutorial-5/res/drawable-xxhdpi/gstreamer_logo_5.png diff --git a/tutorials/android-tutorial-5/res/drawable-xxxhdpi/gstreamer_logo_5.png b/examples/tutorials/android-tutorial-5/res/drawable-xxxhdpi/gstreamer_logo_5.png similarity index 100% rename from tutorials/android-tutorial-5/res/drawable-xxxhdpi/gstreamer_logo_5.png rename to examples/tutorials/android-tutorial-5/res/drawable-xxxhdpi/gstreamer_logo_5.png diff --git a/tutorials/android-tutorial-5/res/layout/file_dialog_main.xml b/examples/tutorials/android-tutorial-5/res/layout/file_dialog_main.xml similarity index 100% rename from tutorials/android-tutorial-5/res/layout/file_dialog_main.xml rename to examples/tutorials/android-tutorial-5/res/layout/file_dialog_main.xml diff --git a/tutorials/android-tutorial-5/res/layout/file_dialog_row.xml b/examples/tutorials/android-tutorial-5/res/layout/file_dialog_row.xml similarity index 100% rename from tutorials/android-tutorial-5/res/layout/file_dialog_row.xml rename to examples/tutorials/android-tutorial-5/res/layout/file_dialog_row.xml diff --git a/tutorials/android-tutorial-5/res/layout/main.xml b/examples/tutorials/android-tutorial-5/res/layout/main.xml similarity index 97% rename from tutorials/android-tutorial-5/res/layout/main.xml rename to examples/tutorials/android-tutorial-5/res/layout/main.xml index df795b2..70ee015 100755 --- a/tutorials/android-tutorial-5/res/layout/main.xml +++ b/examples/tutorials/android-tutorial-5/res/layout/main.xml @@ -1,77 +1,77 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tutorials/android-tutorial-5/res/values/strings.xml b/examples/tutorials/android-tutorial-5/res/values/strings.xml similarity index 100% rename from tutorials/android-tutorial-5/res/values/strings.xml rename to examples/tutorials/android-tutorial-5/res/values/strings.xml diff --git a/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/GStreamerSurfaceView.java b/examples/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/GStreamerSurfaceView.java similarity index 100% rename from tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/GStreamerSurfaceView.java rename to examples/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/GStreamerSurfaceView.java diff --git a/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java b/examples/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java similarity index 99% rename from tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java rename to examples/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java index c86ebd8..11c79f1 100644 --- a/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java +++ b/examples/tutorials/android-tutorial-5/src/com/gst_sdk_tutorials/tutorial_5/Tutorial5.java @@ -62,7 +62,7 @@ public class Tutorial5 extends Activity implements SurfaceHolder.Callback, OnSee GStreamer.init(this); } catch (Exception e) { Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show(); - finish(); + finish(); return; } diff --git a/tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java b/examples/tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java similarity index 99% rename from tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java rename to examples/tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java index e2ef765..e162522 100644 --- a/tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java +++ b/examples/tutorials/android-tutorial-5/src/com/lamerman/FileDialog.java @@ -2,10 +2,10 @@ // // Copyright (c) 2011, 2012, Alexander Ponomarev // All rights reserved. -// +// // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: -// +// // Redistributions of source code must retain the above copyright notice, this list // of conditions and the following disclaimer. Redistributions in binary form must // reproduce the above copyright notice, this list of conditions and the following @@ -49,9 +49,9 @@ import com.gst_sdk_tutorials.tutorial_5.R; /** * Activity para escolha de arquivos/diretorios. - * + * * @author android - * + * */ public class FileDialog extends ListActivity { diff --git a/tutorials/basic-tutorial-1.c b/examples/tutorials/basic-tutorial-1.c similarity index 94% rename from tutorials/basic-tutorial-1.c rename to examples/tutorials/basic-tutorial-1.c index 1656353..e91365b 100644 --- a/tutorials/basic-tutorial-1.c +++ b/examples/tutorials/basic-tutorial-1.c @@ -1,28 +1,28 @@ -#include - -int main(int argc, char *argv[]) { - GstElement *pipeline; - GstBus *bus; - GstMessage *msg; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Build the pipeline */ - pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - - /* Start playing */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - /* Wait until error or EOS */ - bus = gst_element_get_bus (pipeline); - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - - /* Free resources */ - if (msg != NULL) - gst_message_unref (msg); - gst_object_unref (bus); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - return 0; -} +#include + +int main(int argc, char *argv[]) { + GstElement *pipeline; + GstBus *bus; + GstMessage *msg; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Build the pipeline */ + pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); + + /* Start playing */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* Wait until error or EOS */ + bus = gst_element_get_bus (pipeline); + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); + + /* Free resources */ + if (msg != NULL) + gst_message_unref (msg); + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return 0; +} diff --git a/tutorials/basic-tutorial-12.c b/examples/tutorials/basic-tutorial-12.c similarity index 94% rename from tutorials/basic-tutorial-12.c rename to examples/tutorials/basic-tutorial-12.c index ab877e7..514da9b 100644 --- a/tutorials/basic-tutorial-12.c +++ b/examples/tutorials/basic-tutorial-12.c @@ -1,99 +1,99 @@ -#include -#include - -typedef struct _CustomData { - gboolean is_live; - GstElement *pipeline; - GMainLoop *loop; -} CustomData; - -static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) { - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: { - GError *err; - gchar *debug; - - gst_message_parse_error (msg, &err, &debug); - g_print ("Error: %s\n", err->message); - g_error_free (err); - g_free (debug); - - gst_element_set_state (data->pipeline, GST_STATE_READY); - g_main_loop_quit (data->loop); - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - gst_element_set_state (data->pipeline, GST_STATE_READY); - g_main_loop_quit (data->loop); - break; - case GST_MESSAGE_BUFFERING: { - gint percent = 0; - - /* If the stream is live, we do not care about buffering. */ - if (data->is_live) break; - - gst_message_parse_buffering (msg, &percent); - g_print ("Buffering (%3d%%)\r", percent); - /* Wait until buffering is complete before start/resume playing */ - if (percent < 100) - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - else - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); - break; - } - case GST_MESSAGE_CLOCK_LOST: - /* Get a new clock */ - gst_element_set_state (data->pipeline, GST_STATE_PAUSED); - gst_element_set_state (data->pipeline, GST_STATE_PLAYING); - break; - default: - /* Unhandled message */ - break; - } -} - -int main(int argc, char *argv[]) { - GstElement *pipeline; - GstBus *bus; - GstStateChangeReturn ret; - GMainLoop *main_loop; - CustomData data; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Initialize our data structure */ - memset (&data, 0, sizeof (data)); - - /* Build the pipeline */ - pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - bus = gst_element_get_bus (pipeline); - - /* Start playing */ - ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (pipeline); - return -1; - } else if (ret == GST_STATE_CHANGE_NO_PREROLL) { - data.is_live = TRUE; - } - - main_loop = g_main_loop_new (NULL, FALSE); - data.loop = main_loop; - data.pipeline = pipeline; - - gst_bus_add_signal_watch (bus); - g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data); - - g_main_loop_run (main_loop); - - /* Free resources */ - g_main_loop_unref (main_loop); - gst_object_unref (bus); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - return 0; -} +#include +#include + +typedef struct _CustomData { + gboolean is_live; + GstElement *pipeline; + GMainLoop *loop; +} CustomData; + +static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) { + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: { + GError *err; + gchar *debug; + + gst_message_parse_error (msg, &err, &debug); + g_print ("Error: %s\n", err->message); + g_error_free (err); + g_free (debug); + + gst_element_set_state (data->pipeline, GST_STATE_READY); + g_main_loop_quit (data->loop); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + gst_element_set_state (data->pipeline, GST_STATE_READY); + g_main_loop_quit (data->loop); + break; + case GST_MESSAGE_BUFFERING: { + gint percent = 0; + + /* If the stream is live, we do not care about buffering. */ + if (data->is_live) break; + + gst_message_parse_buffering (msg, &percent); + g_print ("Buffering (%3d%%)\r", percent); + /* Wait until buffering is complete before start/resume playing */ + if (percent < 100) + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + else + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + break; + } + case GST_MESSAGE_CLOCK_LOST: + /* Get a new clock */ + gst_element_set_state (data->pipeline, GST_STATE_PAUSED); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); + break; + default: + /* Unhandled message */ + break; + } +} + +int main(int argc, char *argv[]) { + GstElement *pipeline; + GstBus *bus; + GstStateChangeReturn ret; + GMainLoop *main_loop; + CustomData data; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Initialize our data structure */ + memset (&data, 0, sizeof (data)); + + /* Build the pipeline */ + pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); + bus = gst_element_get_bus (pipeline); + + /* Start playing */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (pipeline); + return -1; + } else if (ret == GST_STATE_CHANGE_NO_PREROLL) { + data.is_live = TRUE; + } + + main_loop = g_main_loop_new (NULL, FALSE); + data.loop = main_loop; + data.pipeline = pipeline; + + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data); + + g_main_loop_run (main_loop); + + /* Free resources */ + g_main_loop_unref (main_loop); + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return 0; +} diff --git a/tutorials/basic-tutorial-13.c b/examples/tutorials/basic-tutorial-13.c similarity index 98% rename from tutorials/basic-tutorial-13.c rename to examples/tutorials/basic-tutorial-13.c index 1447407..5c9c2ef 100644 --- a/tutorials/basic-tutorial-13.c +++ b/examples/tutorials/basic-tutorial-13.c @@ -1,27 +1,27 @@ #include #include #include - + typedef struct _CustomData { GstElement *pipeline; GstElement *video_sink; GMainLoop *loop; - + gboolean playing; /* Playing or Paused */ gdouble rate; /* Current playback rate (can be negative) */ } CustomData; - + /* Send seek event to change rate */ static void send_seek_event (CustomData *data) { gint64 position; GstEvent *seek_event; - + /* Obtain the current position, needed for the seek event */ if (!gst_element_query_position (data->pipeline, GST_FORMAT_TIME, &position)) { g_printerr ("Unable to retrieve current position.\n"); return; } - + /* Create the seek event */ if (data->rate > 0) { seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, @@ -30,26 +30,26 @@ static void send_seek_event (CustomData *data) { seek_event = gst_event_new_seek (data->rate, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, position); } - + if (data->video_sink == NULL) { /* If we have not done so, obtain the sink through which we will send the seek events */ g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL); } - + /* Send the event */ gst_element_send_event (data->video_sink, seek_event); - + g_print ("Current rate: %g\n", data->rate); } - + /* Process keyboard input */ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { gchar *str = NULL; - + if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) { return TRUE; } - + switch (g_ascii_tolower (str[0])) { case 'p': data->playing = !data->playing; @@ -73,7 +73,7 @@ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomDa /* If we have not done so, obtain the sink through which we will send the step events */ g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL); } - + gst_element_send_event (data->video_sink, gst_event_new_step (GST_FORMAT_BUFFERS, 1, data->rate, TRUE, FALSE)); g_print ("Stepping one frame\n"); @@ -84,23 +84,23 @@ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomDa default: break; } - + g_free (str); - + return TRUE; } - + int main(int argc, char *argv[]) { CustomData data; GstStateChangeReturn ret; GIOChannel *io_stdin; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Initialize our data structure */ memset (&data, 0, sizeof (data)); - + /* Print usage map */ g_print ( "USAGE: Choose one of the following options, then press enter:\n" @@ -109,10 +109,10 @@ int main(int argc, char *argv[]) { " 'D' to toggle playback direction\n" " 'N' to move to next frame (in the current direction, better in PAUSE)\n" " 'Q' to quit\n"); - + /* Build the pipeline */ data.pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - + /* Add a keyboard watch so we get notified of keystrokes */ #ifdef G_OS_WIN32 io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) { io_stdin = g_io_channel_unix_new (fileno (stdin)); #endif g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); - + /* Start playing */ ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { @@ -130,11 +130,11 @@ int main(int argc, char *argv[]) { } data.playing = TRUE; data.rate = 1.0; - + /* Create a GLib Main Loop and set it to run */ data.loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data.loop); - + /* Free resources */ g_main_loop_unref (data.loop); g_io_channel_unref (io_stdin); diff --git a/tutorials/basic-tutorial-15.c b/examples/tutorials/basic-tutorial-15.c similarity index 98% rename from tutorials/basic-tutorial-15.c rename to examples/tutorials/basic-tutorial-15.c index f9a18f0..fd000d7 100644 --- a/tutorials/basic-tutorial-15.c +++ b/examples/tutorials/basic-tutorial-15.c @@ -1,29 +1,29 @@ #include - + /* Setup the video texture once its size is known */ void size_change (ClutterActor *texture, gint width, gint height, gpointer user_data) { ClutterActor *stage; gfloat new_x, new_y, new_width, new_height; gfloat stage_width, stage_height; ClutterAnimation *animation = NULL; - + stage = clutter_actor_get_stage (texture); if (stage == NULL) return; - + clutter_actor_get_size (stage, &stage_width, &stage_height); - + /* Center video on window and calculate new size preserving aspect ratio */ new_height = (height * stage_width) / width; if (new_height <= stage_height) { new_width = stage_width; - + new_x = 0; new_y = (stage_height - new_height) / 2; } else { new_width = (width * stage_height) / height; new_height = stage_height; - + new_x = (stage_width - new_width) / 2; new_y = 0; } @@ -34,31 +34,31 @@ void size_change (ClutterActor *texture, gint width, gint height, gpointer user_ animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000, "rotation-angle-y", 360.0, NULL); clutter_animation_set_loop (animation, TRUE); } - + int main(int argc, char *argv[]) { GstElement *pipeline, *sink; ClutterTimeline *timeline; ClutterActor *stage, *texture; - + /* clutter-gst takes care of initializing Clutter and GStreamer */ if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) { g_error ("Failed to initialize clutter\n"); return -1; } - + stage = clutter_stage_get_default (); - + /* Make a timeline */ timeline = clutter_timeline_new (1000); g_object_set(timeline, "loop", TRUE, NULL); - + /* Create new texture and disable slicing so the video is properly mapped onto it */ texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL)); g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL); - + /* Build the GStreamer pipeline */ pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - + /* Instantiate the Clutter sink */ sink = gst_element_factory_make ("autocluttersink", NULL); if (sink == NULL) { @@ -69,25 +69,25 @@ int main(int argc, char *argv[]) { g_printerr ("Unable to find a Clutter sink.\n"); return -1; } - + /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/ g_object_set (sink, "texture", texture, NULL); - + /* Add the Clutter sink to the pipeline */ g_object_set (pipeline, "video-sink", sink, NULL); - + /* Start playing */ gst_element_set_state (pipeline, GST_STATE_PLAYING); - + /* start the timeline */ clutter_timeline_start (timeline); - + /* Add texture to the stage, and show it */ clutter_group_add (CLUTTER_GROUP (stage), texture); clutter_actor_show_all (stage); - + clutter_main(); - + /* Free resources */ gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); diff --git a/tutorials/basic-tutorial-2.c b/examples/tutorials/basic-tutorial-2.c similarity index 94% rename from tutorials/basic-tutorial-2.c rename to examples/tutorials/basic-tutorial-2.c index 984442b..e900416 100644 --- a/tutorials/basic-tutorial-2.c +++ b/examples/tutorials/basic-tutorial-2.c @@ -1,76 +1,76 @@ -#include - -int main(int argc, char *argv[]) { - GstElement *pipeline, *source, *sink; - GstBus *bus; - GstMessage *msg; - GstStateChangeReturn ret; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the elements */ - source = gst_element_factory_make ("videotestsrc", "source"); - sink = gst_element_factory_make ("autovideosink", "sink"); - - /* Create the empty pipeline */ - pipeline = gst_pipeline_new ("test-pipeline"); - - if (!pipeline || !source || !sink) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Build the pipeline */ - gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); - if (gst_element_link (source, sink) != TRUE) { - g_printerr ("Elements could not be linked.\n"); - gst_object_unref (pipeline); - return -1; - } - - /* Modify the source's properties */ - g_object_set (source, "pattern", 0, NULL); - - /* Start playing */ - ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (pipeline); - return -1; - } - - /* Wait until error or EOS */ - bus = gst_element_get_bus (pipeline); - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - - /* Parse message */ - if (msg != NULL) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - break; - default: - /* We should not reach here because we only asked for ERRORs and EOS */ - g_printerr ("Unexpected message received.\n"); - break; - } - gst_message_unref (msg); - } - - /* Free resources */ - gst_object_unref (bus); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - return 0; +#include + +int main(int argc, char *argv[]) { + GstElement *pipeline, *source, *sink; + GstBus *bus; + GstMessage *msg; + GstStateChangeReturn ret; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the elements */ + source = gst_element_factory_make ("videotestsrc", "source"); + sink = gst_element_factory_make ("autovideosink", "sink"); + + /* Create the empty pipeline */ + pipeline = gst_pipeline_new ("test-pipeline"); + + if (!pipeline || !source || !sink) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Build the pipeline */ + gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); + if (gst_element_link (source, sink) != TRUE) { + g_printerr ("Elements could not be linked.\n"); + gst_object_unref (pipeline); + return -1; + } + + /* Modify the source's properties */ + g_object_set (source, "pattern", 0, NULL); + + /* Start playing */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (pipeline); + return -1; + } + + /* Wait until error or EOS */ + bus = gst_element_get_bus (pipeline); + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); + + /* Parse message */ + if (msg != NULL) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + break; + default: + /* We should not reach here because we only asked for ERRORs and EOS */ + g_printerr ("Unexpected message received.\n"); + break; + } + gst_message_unref (msg); + } + + /* Free resources */ + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return 0; } \ No newline at end of file diff --git a/tutorials/basic-tutorial-3.c b/examples/tutorials/basic-tutorial-3.c similarity index 95% rename from tutorials/basic-tutorial-3.c rename to examples/tutorials/basic-tutorial-3.c index 8ec0dca3..a892224 100644 --- a/tutorials/basic-tutorial-3.c +++ b/examples/tutorials/basic-tutorial-3.c @@ -1,149 +1,149 @@ -#include - -/* Structure to contain all our information, so we can pass it to callbacks */ -typedef struct _CustomData { - GstElement *pipeline; - GstElement *source; - GstElement *convert; - GstElement *sink; -} CustomData; - -/* Handler for the pad-added signal */ -static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data); - -int main(int argc, char *argv[]) { - CustomData data; - GstBus *bus; - GstMessage *msg; - GstStateChangeReturn ret; - gboolean terminate = FALSE; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the elements */ - data.source = gst_element_factory_make ("uridecodebin", "source"); - data.convert = gst_element_factory_make ("audioconvert", "convert"); - data.sink = gst_element_factory_make ("autoaudiosink", "sink"); - - /* Create the empty pipeline */ - data.pipeline = gst_pipeline_new ("test-pipeline"); - - if (!data.pipeline || !data.source || !data.convert || !data.sink) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Build the pipeline. Note that we are NOT linking the source at this - * point. We will do it later. */ - gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert , data.sink, NULL); - if (!gst_element_link (data.convert, data.sink)) { - g_printerr ("Elements could not be linked.\n"); - gst_object_unref (data.pipeline); - return -1; - } - - /* Set the URI to play */ - g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - - /* Connect to the pad-added signal */ - g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data); - - /* Start playing */ - ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (data.pipeline); - return -1; - } - - /* Listen to the bus */ - bus = gst_element_get_bus (data.pipeline); - do { - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, - GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - - /* Parse message */ - if (msg != NULL) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - terminate = TRUE; - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - terminate = TRUE; - break; - case GST_MESSAGE_STATE_CHANGED: - /* We are only interested in state-changed messages from the pipeline */ - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - g_print ("Pipeline state changed from %s to %s:\n", - gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); - } - break; - default: - /* We should not reach here */ - g_printerr ("Unexpected message received.\n"); - break; - } - gst_message_unref (msg); - } - } while (!terminate); - - /* Free resources */ - gst_object_unref (bus); - gst_element_set_state (data.pipeline, GST_STATE_NULL); - gst_object_unref (data.pipeline); - return 0; -} - -/* This function will be called by the pad-added signal */ -static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) { - GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink"); - GstPadLinkReturn ret; - GstCaps *new_pad_caps = NULL; - GstStructure *new_pad_struct = NULL; - const gchar *new_pad_type = NULL; - - g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src)); - - /* If our converter is already linked, we have nothing to do here */ - if (gst_pad_is_linked (sink_pad)) { - g_print (" We are already linked. Ignoring.\n"); - goto exit; - } - - /* Check the new pad's type */ - new_pad_caps = gst_pad_query_caps (new_pad, NULL); - new_pad_struct = gst_caps_get_structure (new_pad_caps, 0); - new_pad_type = gst_structure_get_name (new_pad_struct); - if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) { - g_print (" It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type); - goto exit; - } - - /* Attempt the link */ - ret = gst_pad_link (new_pad, sink_pad); - if (GST_PAD_LINK_FAILED (ret)) { - g_print (" Type is '%s' but link failed.\n", new_pad_type); - } else { - g_print (" Link succeeded (type '%s').\n", new_pad_type); - } - -exit: - /* Unreference the new pad's caps, if we got them */ - if (new_pad_caps != NULL) - gst_caps_unref (new_pad_caps); - - /* Unreference the sink pad */ - gst_object_unref (sink_pad); -} +#include + +/* Structure to contain all our information, so we can pass it to callbacks */ +typedef struct _CustomData { + GstElement *pipeline; + GstElement *source; + GstElement *convert; + GstElement *sink; +} CustomData; + +/* Handler for the pad-added signal */ +static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data); + +int main(int argc, char *argv[]) { + CustomData data; + GstBus *bus; + GstMessage *msg; + GstStateChangeReturn ret; + gboolean terminate = FALSE; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the elements */ + data.source = gst_element_factory_make ("uridecodebin", "source"); + data.convert = gst_element_factory_make ("audioconvert", "convert"); + data.sink = gst_element_factory_make ("autoaudiosink", "sink"); + + /* Create the empty pipeline */ + data.pipeline = gst_pipeline_new ("test-pipeline"); + + if (!data.pipeline || !data.source || !data.convert || !data.sink) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Build the pipeline. Note that we are NOT linking the source at this + * point. We will do it later. */ + gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert , data.sink, NULL); + if (!gst_element_link (data.convert, data.sink)) { + g_printerr ("Elements could not be linked.\n"); + gst_object_unref (data.pipeline); + return -1; + } + + /* Set the URI to play */ + g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); + + /* Connect to the pad-added signal */ + g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data); + + /* Start playing */ + ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (data.pipeline); + return -1; + } + + /* Listen to the bus */ + bus = gst_element_get_bus (data.pipeline); + do { + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS); + + /* Parse message */ + if (msg != NULL) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + terminate = TRUE; + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + terminate = TRUE; + break; + case GST_MESSAGE_STATE_CHANGED: + /* We are only interested in state-changed messages from the pipeline */ + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + g_print ("Pipeline state changed from %s to %s:\n", + gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); + } + break; + default: + /* We should not reach here */ + g_printerr ("Unexpected message received.\n"); + break; + } + gst_message_unref (msg); + } + } while (!terminate); + + /* Free resources */ + gst_object_unref (bus); + gst_element_set_state (data.pipeline, GST_STATE_NULL); + gst_object_unref (data.pipeline); + return 0; +} + +/* This function will be called by the pad-added signal */ +static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) { + GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink"); + GstPadLinkReturn ret; + GstCaps *new_pad_caps = NULL; + GstStructure *new_pad_struct = NULL; + const gchar *new_pad_type = NULL; + + g_print ("Received new pad '%s' from '%s':\n", GST_PAD_NAME (new_pad), GST_ELEMENT_NAME (src)); + + /* If our converter is already linked, we have nothing to do here */ + if (gst_pad_is_linked (sink_pad)) { + g_print (" We are already linked. Ignoring.\n"); + goto exit; + } + + /* Check the new pad's type */ + new_pad_caps = gst_pad_query_caps (new_pad, NULL); + new_pad_struct = gst_caps_get_structure (new_pad_caps, 0); + new_pad_type = gst_structure_get_name (new_pad_struct); + if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) { + g_print (" It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type); + goto exit; + } + + /* Attempt the link */ + ret = gst_pad_link (new_pad, sink_pad); + if (GST_PAD_LINK_FAILED (ret)) { + g_print (" Type is '%s' but link failed.\n", new_pad_type); + } else { + g_print (" Link succeeded (type '%s').\n", new_pad_type); + } + +exit: + /* Unreference the new pad's caps, if we got them */ + if (new_pad_caps != NULL) + gst_caps_unref (new_pad_caps); + + /* Unreference the sink pad */ + gst_object_unref (sink_pad); +} diff --git a/tutorials/basic-tutorial-4.c b/examples/tutorials/basic-tutorial-4.c similarity index 95% rename from tutorials/basic-tutorial-4.c rename to examples/tutorials/basic-tutorial-4.c index 37f162e..f0ba4ca 100644 --- a/tutorials/basic-tutorial-4.c +++ b/examples/tutorials/basic-tutorial-4.c @@ -1,156 +1,156 @@ -#include - -/* Structure to contain all our information, so we can pass it around */ -typedef struct _CustomData { - GstElement *playbin; /* Our one and only element */ - gboolean playing; /* Are we in the PLAYING state? */ - gboolean terminate; /* Should we terminate execution? */ - gboolean seek_enabled; /* Is seeking enabled for this media? */ - gboolean seek_done; /* Have we performed the seek already? */ - gint64 duration; /* How long does this media last, in nanoseconds */ -} CustomData; - -/* Forward definition of the message processing function */ -static void handle_message (CustomData *data, GstMessage *msg); - -int main(int argc, char *argv[]) { - CustomData data; - GstBus *bus; - GstMessage *msg; - GstStateChangeReturn ret; - - data.playing = FALSE; - data.terminate = FALSE; - data.seek_enabled = FALSE; - data.seek_done = FALSE; - data.duration = GST_CLOCK_TIME_NONE; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the elements */ - data.playbin = gst_element_factory_make ("playbin", "playbin"); - - if (!data.playbin) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Set the URI to play */ - g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - - /* Start playing */ - ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (data.playbin); - return -1; - } - - /* Listen to the bus */ - bus = gst_element_get_bus (data.playbin); - do { - msg = gst_bus_timed_pop_filtered (bus, 100 * GST_MSECOND, - GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_DURATION); - - /* Parse message */ - if (msg != NULL) { - handle_message (&data, msg); - } else { - /* We got no message, this means the timeout expired */ - if (data.playing) { - gint64 current = -1; - - /* Query the current position of the stream */ - if (!gst_element_query_position (data.playbin, GST_FORMAT_TIME, ¤t)) { - g_printerr ("Could not query current position.\n"); - } - - /* If we didn't know it yet, query the stream duration */ - if (!GST_CLOCK_TIME_IS_VALID (data.duration)) { - if (!gst_element_query_duration (data.playbin, GST_FORMAT_TIME, &data.duration)) { - g_printerr ("Could not query current duration.\n"); - } - } - - /* Print current position and total duration */ - g_print ("Position %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r", - GST_TIME_ARGS (current), GST_TIME_ARGS (data.duration)); - - /* If seeking is enabled, we have not done it yet, and the time is right, seek */ - if (data.seek_enabled && !data.seek_done && current > 10 * GST_SECOND) { - g_print ("\nReached 10s, performing seek...\n"); - gst_element_seek_simple (data.playbin, GST_FORMAT_TIME, - GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 30 * GST_SECOND); - data.seek_done = TRUE; - } - } - } - } while (!data.terminate); - - /* Free resources */ - gst_object_unref (bus); - gst_element_set_state (data.playbin, GST_STATE_NULL); - gst_object_unref (data.playbin); - return 0; -} - -static void handle_message (CustomData *data, GstMessage *msg) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - data->terminate = TRUE; - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - data->terminate = TRUE; - break; - case GST_MESSAGE_DURATION: - /* The duration has changed, mark the current one as invalid */ - data->duration = GST_CLOCK_TIME_NONE; - break; - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { - g_print ("Pipeline state changed from %s to %s:\n", - gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); - - /* Remember whether we are in the PLAYING state or not */ - data->playing = (new_state == GST_STATE_PLAYING); - - if (data->playing) { - /* We just moved to PLAYING. Check if seeking is possible */ - GstQuery *query; - gint64 start, end; - query = gst_query_new_seeking (GST_FORMAT_TIME); - if (gst_element_query (data->playbin, query)) { - gst_query_parse_seeking (query, NULL, &data->seek_enabled, &start, &end); - if (data->seek_enabled) { - g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n", - GST_TIME_ARGS (start), GST_TIME_ARGS (end)); - } else { - g_print ("Seeking is DISABLED for this stream.\n"); - } - } - else { - g_printerr ("Seeking query failed."); - } - gst_query_unref (query); - } - } - } break; - default: - /* We should not reach here */ - g_printerr ("Unexpected message received.\n"); - break; - } - gst_message_unref (msg); -} +#include + +/* Structure to contain all our information, so we can pass it around */ +typedef struct _CustomData { + GstElement *playbin; /* Our one and only element */ + gboolean playing; /* Are we in the PLAYING state? */ + gboolean terminate; /* Should we terminate execution? */ + gboolean seek_enabled; /* Is seeking enabled for this media? */ + gboolean seek_done; /* Have we performed the seek already? */ + gint64 duration; /* How long does this media last, in nanoseconds */ +} CustomData; + +/* Forward definition of the message processing function */ +static void handle_message (CustomData *data, GstMessage *msg); + +int main(int argc, char *argv[]) { + CustomData data; + GstBus *bus; + GstMessage *msg; + GstStateChangeReturn ret; + + data.playing = FALSE; + data.terminate = FALSE; + data.seek_enabled = FALSE; + data.seek_done = FALSE; + data.duration = GST_CLOCK_TIME_NONE; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the elements */ + data.playbin = gst_element_factory_make ("playbin", "playbin"); + + if (!data.playbin) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Set the URI to play */ + g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); + + /* Start playing */ + ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (data.playbin); + return -1; + } + + /* Listen to the bus */ + bus = gst_element_get_bus (data.playbin); + do { + msg = gst_bus_timed_pop_filtered (bus, 100 * GST_MSECOND, + GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_DURATION); + + /* Parse message */ + if (msg != NULL) { + handle_message (&data, msg); + } else { + /* We got no message, this means the timeout expired */ + if (data.playing) { + gint64 current = -1; + + /* Query the current position of the stream */ + if (!gst_element_query_position (data.playbin, GST_FORMAT_TIME, ¤t)) { + g_printerr ("Could not query current position.\n"); + } + + /* If we didn't know it yet, query the stream duration */ + if (!GST_CLOCK_TIME_IS_VALID (data.duration)) { + if (!gst_element_query_duration (data.playbin, GST_FORMAT_TIME, &data.duration)) { + g_printerr ("Could not query current duration.\n"); + } + } + + /* Print current position and total duration */ + g_print ("Position %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r", + GST_TIME_ARGS (current), GST_TIME_ARGS (data.duration)); + + /* If seeking is enabled, we have not done it yet, and the time is right, seek */ + if (data.seek_enabled && !data.seek_done && current > 10 * GST_SECOND) { + g_print ("\nReached 10s, performing seek...\n"); + gst_element_seek_simple (data.playbin, GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, 30 * GST_SECOND); + data.seek_done = TRUE; + } + } + } + } while (!data.terminate); + + /* Free resources */ + gst_object_unref (bus); + gst_element_set_state (data.playbin, GST_STATE_NULL); + gst_object_unref (data.playbin); + return 0; +} + +static void handle_message (CustomData *data, GstMessage *msg) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + data->terminate = TRUE; + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + data->terminate = TRUE; + break; + case GST_MESSAGE_DURATION: + /* The duration has changed, mark the current one as invalid */ + data->duration = GST_CLOCK_TIME_NONE; + break; + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { + g_print ("Pipeline state changed from %s to %s:\n", + gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); + + /* Remember whether we are in the PLAYING state or not */ + data->playing = (new_state == GST_STATE_PLAYING); + + if (data->playing) { + /* We just moved to PLAYING. Check if seeking is possible */ + GstQuery *query; + gint64 start, end; + query = gst_query_new_seeking (GST_FORMAT_TIME); + if (gst_element_query (data->playbin, query)) { + gst_query_parse_seeking (query, NULL, &data->seek_enabled, &start, &end); + if (data->seek_enabled) { + g_print ("Seeking is ENABLED from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (start), GST_TIME_ARGS (end)); + } else { + g_print ("Seeking is DISABLED for this stream.\n"); + } + } + else { + g_printerr ("Seeking query failed."); + } + gst_query_unref (query); + } + } + } break; + default: + /* We should not reach here */ + g_printerr ("Unexpected message received.\n"); + break; + } + gst_message_unref (msg); +} diff --git a/tutorials/basic-tutorial-5.c b/examples/tutorials/basic-tutorial-5.c similarity index 98% rename from tutorials/basic-tutorial-5.c rename to examples/tutorials/basic-tutorial-5.c index c0af920..9ea646f 100644 --- a/tutorials/basic-tutorial-5.c +++ b/examples/tutorials/basic-tutorial-5.c @@ -1,9 +1,9 @@ #include - + #include #include #include - + #include #if defined (GDK_WINDOWING_X11) #include @@ -12,29 +12,29 @@ #elif defined (GDK_WINDOWING_QUARTZ) #include #endif - + /* Structure to contain all our information, so we can pass it around */ typedef struct _CustomData { GstElement *playbin; /* Our one and only pipeline */ - + GtkWidget *slider; /* Slider widget to keep track of current position */ GtkWidget *streams_list; /* Text widget to display info about the streams */ gulong slider_update_signal_id; /* Signal ID for the slider update signal */ - + GstState state; /* Current state of the pipeline */ gint64 duration; /* Duration of the clip, in nanoseconds */ } CustomData; - + /* This function is called when the GUI toolkit creates the physical window that will hold the video. * At this point we can retrieve its handler (which has a different meaning depending on the windowing system) * and pass it to GStreamer through the XOverlay interface. */ static void realize_cb (GtkWidget *widget, CustomData *data) { GdkWindow *window = gtk_widget_get_window (widget); guintptr window_handle; - + if (!gdk_window_ensure_native (window)) g_error ("Couldn't create native window needed for GstXOverlay!"); - + /* Retrieve window handler from GDK */ #if defined (GDK_WINDOWING_WIN32) window_handle = (guintptr)GDK_WINDOW_HWND (window); @@ -46,35 +46,35 @@ static void realize_cb (GtkWidget *widget, CustomData *data) { /* Pass it to playbin, which implements XOverlay and will forward it to the video sink */ gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->playbin), window_handle); } - + /* This function is called when the PLAY button is clicked */ static void play_cb (GtkButton *button, CustomData *data) { gst_element_set_state (data->playbin, GST_STATE_PLAYING); } - + /* This function is called when the PAUSE button is clicked */ static void pause_cb (GtkButton *button, CustomData *data) { gst_element_set_state (data->playbin, GST_STATE_PAUSED); } - + /* This function is called when the STOP button is clicked */ static void stop_cb (GtkButton *button, CustomData *data) { gst_element_set_state (data->playbin, GST_STATE_READY); } - + /* This function is called when the main window is closed */ static void delete_event_cb (GtkWidget *widget, GdkEvent *event, CustomData *data) { stop_cb (NULL, data); gtk_main_quit (); } - + /* This function is called everytime the video window needs to be redrawn (due to damage/exposure, * rescaling, etc). GStreamer takes care of this in the PAUSED and PLAYING states, otherwise, * we simply draw a black rectangle to avoid garbage showing up. */ static gboolean draw_cb (GtkWidget *widget, cairo_t *cr, CustomData *data) { if (data->state < GST_STATE_PAUSED) { GtkAllocation allocation; - + /* Cairo is a 2D graphics library which we use here to clean the video window. * It is used by GStreamer for other reasons, so it will always be available to us. */ gtk_widget_get_allocation (widget, &allocation); @@ -82,10 +82,10 @@ static gboolean draw_cb (GtkWidget *widget, cairo_t *cr, CustomData *data) { cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); cairo_fill (cr); } - + return FALSE; } - + /* This function is called when the slider changes its position. We perform a seek to the * new position here. */ static void slider_cb (GtkRange *range, CustomData *data) { @@ -93,7 +93,7 @@ static void slider_cb (GtkRange *range, CustomData *data) { gst_element_seek_simple (data->playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, (gint64)(value * GST_SECOND)); } - + /* This creates all the GTK+ widgets that compose our application, and registers the callbacks */ static void create_ui (CustomData *data) { GtkWidget *main_window; /* The uppermost window, containing all other windows */ @@ -102,58 +102,58 @@ static void create_ui (CustomData *data) { GtkWidget *main_hbox; /* HBox to hold the video_window and the stream info text widget */ GtkWidget *controls; /* HBox to hold the buttons and the slider */ GtkWidget *play_button, *pause_button, *stop_button; /* Buttons */ - + main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); g_signal_connect (G_OBJECT (main_window), "delete-event", G_CALLBACK (delete_event_cb), data); - + video_window = gtk_drawing_area_new (); gtk_widget_set_double_buffered (video_window, FALSE); g_signal_connect (video_window, "realize", G_CALLBACK (realize_cb), data); g_signal_connect (video_window, "draw", G_CALLBACK (draw_cb), data); - + play_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY); g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), data); - + pause_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PAUSE); g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), data); - + stop_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_STOP); g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), data); - + data->slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1); gtk_scale_set_draw_value (GTK_SCALE (data->slider), 0); data->slider_update_signal_id = g_signal_connect (G_OBJECT (data->slider), "value-changed", G_CALLBACK (slider_cb), data); - + data->streams_list = gtk_text_view_new (); gtk_text_view_set_editable (GTK_TEXT_VIEW (data->streams_list), FALSE); - + controls = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (controls), play_button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (controls), pause_button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (controls), stop_button, FALSE, FALSE, 2); gtk_box_pack_start (GTK_BOX (controls), data->slider, TRUE, TRUE, 2); - + main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_box_pack_start (GTK_BOX (main_hbox), video_window, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (main_hbox), data->streams_list, FALSE, FALSE, 2); - + main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_box_pack_start (GTK_BOX (main_box), main_hbox, TRUE, TRUE, 0); gtk_box_pack_start (GTK_BOX (main_box), controls, FALSE, FALSE, 0); gtk_container_add (GTK_CONTAINER (main_window), main_box); gtk_window_set_default_size (GTK_WINDOW (main_window), 640, 480); - + gtk_widget_show_all (main_window); } - + /* This function is called periodically to refresh the GUI */ static gboolean refresh_ui (CustomData *data) { gint64 current = -1; - + /* We do not want to update anything unless we are in the PAUSED or PLAYING states */ if (data->state < GST_STATE_PAUSED) return TRUE; - + /* If we didn't know it yet, query the stream duration */ if (!GST_CLOCK_TIME_IS_VALID (data->duration)) { if (!gst_element_query_duration (data->playbin, GST_FORMAT_TIME, &data->duration)) { @@ -163,7 +163,7 @@ static gboolean refresh_ui (CustomData *data) { gtk_range_set_range (GTK_RANGE (data->slider), 0, (gdouble)data->duration / GST_SECOND); } } - + if (gst_element_query_position (data->playbin, GST_FORMAT_TIME, ¤t)) { /* Block the "value-changed" signal, so the slider_cb function is not called * (which would trigger a seek the user has not requested) */ @@ -175,7 +175,7 @@ static gboolean refresh_ui (CustomData *data) { } return TRUE; } - + /* This function is called when new metadata is discovered in the stream */ static void tags_cb (GstElement *playbin, gint stream, CustomData *data) { /* We are possibly in a GStreamer working thread, so we notify the main @@ -184,30 +184,30 @@ static void tags_cb (GstElement *playbin, gint stream, CustomData *data) { gst_message_new_application (GST_OBJECT (playbin), gst_structure_new_empty ("tags-changed"))); } - + /* This function is called when an error message is posted on the bus */ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GError *err; gchar *debug_info; - + /* Print error details on the screen */ gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); - + /* Set the pipeline to READY (which stops playback) */ gst_element_set_state (data->playbin, GST_STATE_READY); } - + /* This function is called when an End-Of-Stream message is posted on the bus. * We just set the pipeline to READY (which stops playback) */ static void eos_cb (GstBus *bus, GstMessage *msg, CustomData *data) { g_print ("End-Of-Stream reached.\n"); gst_element_set_state (data->playbin, GST_STATE_READY); } - + /* This function is called when the pipeline changes states. We use it to * keep track of the current state. */ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { @@ -222,7 +222,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, CustomData *data) { } } } - + /* Extract metadata from all the streams and write it to the text widget in the GUI */ static void analyze_streams (CustomData *data) { gint i; @@ -231,16 +231,16 @@ static void analyze_streams (CustomData *data) { guint rate; gint n_video, n_audio, n_text; GtkTextBuffer *text; - + /* Clean current contents of the widget */ text = gtk_text_view_get_buffer (GTK_TEXT_VIEW (data->streams_list)); gtk_text_buffer_set_text (text, "", -1); - + /* Read some properties */ g_object_get (data->playbin, "n-video", &n_video, NULL); g_object_get (data->playbin, "n-audio", &n_audio, NULL); g_object_get (data->playbin, "n-text", &n_text, NULL); - + for (i = 0; i < n_video; i++) { tags = NULL; /* Retrieve the stream's video tags */ @@ -257,7 +257,7 @@ static void analyze_streams (CustomData *data) { gst_tag_list_free (tags); } } - + for (i = 0; i < n_audio; i++) { tags = NULL; /* Retrieve the stream's audio tags */ @@ -286,7 +286,7 @@ static void analyze_streams (CustomData *data) { gst_tag_list_free (tags); } } - + for (i = 0; i < n_text; i++) { tags = NULL; /* Retrieve the stream's subtitle tags */ @@ -305,7 +305,7 @@ static void analyze_streams (CustomData *data) { } } } - + /* This function is called when an "application" message is posted on the bus. * Here we retrieve the message posted by the tags_cb callback */ static void application_cb (GstBus *bus, GstMessage *msg, CustomData *data) { @@ -315,41 +315,41 @@ static void application_cb (GstBus *bus, GstMessage *msg, CustomData *data) { analyze_streams (data); } } - + int main(int argc, char *argv[]) { CustomData data; GstStateChangeReturn ret; GstBus *bus; - + /* Initialize GTK */ gtk_init (&argc, &argv); - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Initialize our data structure */ memset (&data, 0, sizeof (data)); data.duration = GST_CLOCK_TIME_NONE; - + /* Create the elements */ data.playbin = gst_element_factory_make ("playbin", "playbin"); - + if (!data.playbin) { g_printerr ("Not all elements could be created.\n"); return -1; } - + /* Set the URI to play */ g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - + /* Connect to interesting signals in playbin */ g_signal_connect (G_OBJECT (data.playbin), "video-tags-changed", (GCallback) tags_cb, &data); g_signal_connect (G_OBJECT (data.playbin), "audio-tags-changed", (GCallback) tags_cb, &data); g_signal_connect (G_OBJECT (data.playbin), "text-tags-changed", (GCallback) tags_cb, &data); - + /* Create the GUI */ create_ui (&data); - + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data.playbin); gst_bus_add_signal_watch (bus); @@ -358,7 +358,7 @@ int main(int argc, char *argv[]) { g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, &data); g_signal_connect (G_OBJECT (bus), "message::application", (GCallback)application_cb, &data); gst_object_unref (bus); - + /* Start playing */ ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { @@ -366,13 +366,13 @@ int main(int argc, char *argv[]) { gst_object_unref (data.playbin); return -1; } - + /* Register a function that GLib will call every second */ g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, &data); - + /* Start the GTK main loop. We will not regain control until gtk_main_quit is called. */ gtk_main (); - + /* Free resources */ gst_element_set_state (data.playbin, GST_STATE_NULL); gst_object_unref (data.playbin); diff --git a/tutorials/basic-tutorial-6.c b/examples/tutorials/basic-tutorial-6.c similarity index 95% rename from tutorials/basic-tutorial-6.c rename to examples/tutorials/basic-tutorial-6.c index 4714938..04584db 100644 --- a/tutorials/basic-tutorial-6.c +++ b/examples/tutorials/basic-tutorial-6.c @@ -1,207 +1,207 @@ -#include - -/* Functions below print the Capabilities in a human-friendly format */ -static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) { - gchar *str = gst_value_serialize (value); - - g_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str); - g_free (str); - return TRUE; -} - -static void print_caps (const GstCaps * caps, const gchar * pfx) { - guint i; - - g_return_if_fail (caps != NULL); - - if (gst_caps_is_any (caps)) { - g_print ("%sANY\n", pfx); - return; - } - if (gst_caps_is_empty (caps)) { - g_print ("%sEMPTY\n", pfx); - return; - } - - for (i = 0; i < gst_caps_get_size (caps); i++) { - GstStructure *structure = gst_caps_get_structure (caps, i); - - g_print ("%s%s\n", pfx, gst_structure_get_name (structure)); - gst_structure_foreach (structure, print_field, (gpointer) pfx); - } -} - -/* Prints information about a Pad Template, including its Capabilities */ -static void print_pad_templates_information (GstElementFactory * factory) { - const GList *pads; - GstStaticPadTemplate *padtemplate; - - g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory)); - if (!gst_element_factory_get_num_pad_templates (factory)) { - g_print (" none\n"); - return; - } - - pads = gst_element_factory_get_static_pad_templates (factory); - while (pads) { - padtemplate = pads->data; - pads = g_list_next (pads); - - if (padtemplate->direction == GST_PAD_SRC) - g_print (" SRC template: '%s'\n", padtemplate->name_template); - else if (padtemplate->direction == GST_PAD_SINK) - g_print (" SINK template: '%s'\n", padtemplate->name_template); - else - g_print (" UNKNOWN!!! template: '%s'\n", padtemplate->name_template); - - if (padtemplate->presence == GST_PAD_ALWAYS) - g_print (" Availability: Always\n"); - else if (padtemplate->presence == GST_PAD_SOMETIMES) - g_print (" Availability: Sometimes\n"); - else if (padtemplate->presence == GST_PAD_REQUEST) { - g_print (" Availability: On request\n"); - } else - g_print (" Availability: UNKNOWN!!!\n"); - - if (padtemplate->static_caps.string) { - GstCaps *caps; - - g_print (" Capabilities:\n"); - caps = gst_static_caps_get (&padtemplate->static_caps); - print_caps (caps, " "); - gst_caps_unref (caps); - } - - g_print ("\n"); - } -} - -/* Shows the CURRENT capabilities of the requested pad in the given element */ -static void print_pad_capabilities (GstElement *element, gchar *pad_name) { - GstPad *pad = NULL; - GstCaps *caps = NULL; - - /* Retrieve pad */ - pad = gst_element_get_static_pad (element, pad_name); - if (!pad) { - g_printerr ("Could not retrieve pad '%s'\n", pad_name); - return; - } - - /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */ - caps = gst_pad_get_current_caps (pad); - if (!caps) - caps = gst_pad_query_caps (pad, NULL); - - /* Print and free */ - g_print ("Caps for the %s pad:\n", pad_name); - print_caps (caps, " "); - gst_caps_unref (caps); - gst_object_unref (pad); -} - -int main(int argc, char *argv[]) { - GstElement *pipeline, *source, *sink; - GstElementFactory *source_factory, *sink_factory; - GstBus *bus; - GstMessage *msg; - GstStateChangeReturn ret; - gboolean terminate = FALSE; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the element factories */ - source_factory = gst_element_factory_find ("audiotestsrc"); - sink_factory = gst_element_factory_find ("autoaudiosink"); - if (!source_factory || !sink_factory) { - g_printerr ("Not all element factories could be created.\n"); - return -1; - } - - /* Print information about the pad templates of these factories */ - print_pad_templates_information (source_factory); - print_pad_templates_information (sink_factory); - - /* Ask the factories to instantiate actual elements */ - source = gst_element_factory_create (source_factory, "source"); - sink = gst_element_factory_create (sink_factory, "sink"); - - /* Create the empty pipeline */ - pipeline = gst_pipeline_new ("test-pipeline"); - - if (!pipeline || !source || !sink) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Build the pipeline */ - gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); - if (gst_element_link (source, sink) != TRUE) { - g_printerr ("Elements could not be linked.\n"); - gst_object_unref (pipeline); - return -1; - } - - /* Print initial negotiated caps (in NULL state) */ - g_print ("In NULL state:\n"); - print_pad_capabilities (sink, "sink"); - - /* Start playing */ - ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state (check the bus for error messages).\n"); - } - - /* Wait until error, EOS or State Change */ - bus = gst_element_get_bus (pipeline); - do { - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS | - GST_MESSAGE_STATE_CHANGED); - - /* Parse message */ - if (msg != NULL) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - terminate = TRUE; - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - terminate = TRUE; - break; - case GST_MESSAGE_STATE_CHANGED: - /* We are only interested in state-changed messages from the pipeline */ - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - g_print ("\nPipeline state changed from %s to %s:\n", - gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); - /* Print the current capabilities of the sink element */ - print_pad_capabilities (sink, "sink"); - } - break; - default: - /* We should not reach here because we only asked for ERRORs, EOS and STATE_CHANGED */ - g_printerr ("Unexpected message received.\n"); - break; - } - gst_message_unref (msg); - } - } while (!terminate); - - /* Free resources */ - gst_object_unref (bus); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - gst_object_unref (source_factory); - gst_object_unref (sink_factory); - return 0; -} +#include + +/* Functions below print the Capabilities in a human-friendly format */ +static gboolean print_field (GQuark field, const GValue * value, gpointer pfx) { + gchar *str = gst_value_serialize (value); + + g_print ("%s %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str); + g_free (str); + return TRUE; +} + +static void print_caps (const GstCaps * caps, const gchar * pfx) { + guint i; + + g_return_if_fail (caps != NULL); + + if (gst_caps_is_any (caps)) { + g_print ("%sANY\n", pfx); + return; + } + if (gst_caps_is_empty (caps)) { + g_print ("%sEMPTY\n", pfx); + return; + } + + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + + g_print ("%s%s\n", pfx, gst_structure_get_name (structure)); + gst_structure_foreach (structure, print_field, (gpointer) pfx); + } +} + +/* Prints information about a Pad Template, including its Capabilities */ +static void print_pad_templates_information (GstElementFactory * factory) { + const GList *pads; + GstStaticPadTemplate *padtemplate; + + g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory)); + if (!gst_element_factory_get_num_pad_templates (factory)) { + g_print (" none\n"); + return; + } + + pads = gst_element_factory_get_static_pad_templates (factory); + while (pads) { + padtemplate = pads->data; + pads = g_list_next (pads); + + if (padtemplate->direction == GST_PAD_SRC) + g_print (" SRC template: '%s'\n", padtemplate->name_template); + else if (padtemplate->direction == GST_PAD_SINK) + g_print (" SINK template: '%s'\n", padtemplate->name_template); + else + g_print (" UNKNOWN!!! template: '%s'\n", padtemplate->name_template); + + if (padtemplate->presence == GST_PAD_ALWAYS) + g_print (" Availability: Always\n"); + else if (padtemplate->presence == GST_PAD_SOMETIMES) + g_print (" Availability: Sometimes\n"); + else if (padtemplate->presence == GST_PAD_REQUEST) { + g_print (" Availability: On request\n"); + } else + g_print (" Availability: UNKNOWN!!!\n"); + + if (padtemplate->static_caps.string) { + GstCaps *caps; + + g_print (" Capabilities:\n"); + caps = gst_static_caps_get (&padtemplate->static_caps); + print_caps (caps, " "); + gst_caps_unref (caps); + } + + g_print ("\n"); + } +} + +/* Shows the CURRENT capabilities of the requested pad in the given element */ +static void print_pad_capabilities (GstElement *element, gchar *pad_name) { + GstPad *pad = NULL; + GstCaps *caps = NULL; + + /* Retrieve pad */ + pad = gst_element_get_static_pad (element, pad_name); + if (!pad) { + g_printerr ("Could not retrieve pad '%s'\n", pad_name); + return; + } + + /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */ + caps = gst_pad_get_current_caps (pad); + if (!caps) + caps = gst_pad_query_caps (pad, NULL); + + /* Print and free */ + g_print ("Caps for the %s pad:\n", pad_name); + print_caps (caps, " "); + gst_caps_unref (caps); + gst_object_unref (pad); +} + +int main(int argc, char *argv[]) { + GstElement *pipeline, *source, *sink; + GstElementFactory *source_factory, *sink_factory; + GstBus *bus; + GstMessage *msg; + GstStateChangeReturn ret; + gboolean terminate = FALSE; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the element factories */ + source_factory = gst_element_factory_find ("audiotestsrc"); + sink_factory = gst_element_factory_find ("autoaudiosink"); + if (!source_factory || !sink_factory) { + g_printerr ("Not all element factories could be created.\n"); + return -1; + } + + /* Print information about the pad templates of these factories */ + print_pad_templates_information (source_factory); + print_pad_templates_information (sink_factory); + + /* Ask the factories to instantiate actual elements */ + source = gst_element_factory_create (source_factory, "source"); + sink = gst_element_factory_create (sink_factory, "sink"); + + /* Create the empty pipeline */ + pipeline = gst_pipeline_new ("test-pipeline"); + + if (!pipeline || !source || !sink) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Build the pipeline */ + gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL); + if (gst_element_link (source, sink) != TRUE) { + g_printerr ("Elements could not be linked.\n"); + gst_object_unref (pipeline); + return -1; + } + + /* Print initial negotiated caps (in NULL state) */ + g_print ("In NULL state:\n"); + print_pad_capabilities (sink, "sink"); + + /* Start playing */ + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state (check the bus for error messages).\n"); + } + + /* Wait until error, EOS or State Change */ + bus = gst_element_get_bus (pipeline); + do { + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS | + GST_MESSAGE_STATE_CHANGED); + + /* Parse message */ + if (msg != NULL) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + terminate = TRUE; + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + terminate = TRUE; + break; + case GST_MESSAGE_STATE_CHANGED: + /* We are only interested in state-changed messages from the pipeline */ + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + g_print ("\nPipeline state changed from %s to %s:\n", + gst_element_state_get_name (old_state), gst_element_state_get_name (new_state)); + /* Print the current capabilities of the sink element */ + print_pad_capabilities (sink, "sink"); + } + break; + default: + /* We should not reach here because we only asked for ERRORs, EOS and STATE_CHANGED */ + g_printerr ("Unexpected message received.\n"); + break; + } + gst_message_unref (msg); + } + } while (!terminate); + + /* Free resources */ + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (source_factory); + gst_object_unref (sink_factory); + return 0; +} diff --git a/tutorials/basic-tutorial-7.c b/examples/tutorials/basic-tutorial-7.c similarity index 99% rename from tutorials/basic-tutorial-7.c rename to examples/tutorials/basic-tutorial-7.c index 73e34d9..6edb3c1 100644 --- a/tutorials/basic-tutorial-7.c +++ b/examples/tutorials/basic-tutorial-7.c @@ -1,5 +1,5 @@ #include - + int main(int argc, char *argv[]) { GstElement *pipeline, *audio_source, *tee, *audio_queue, *audio_convert, *audio_resample, *audio_sink; GstElement *video_queue, *visual, *video_convert, *video_sink; @@ -8,10 +8,10 @@ int main(int argc, char *argv[]) { GstPadTemplate *tee_src_pad_template; GstPad *tee_audio_pad, *tee_video_pad; GstPad *queue_audio_pad, *queue_video_pad; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Create the elements */ audio_source = gst_element_factory_make ("audiotestsrc", "audio_source"); tee = gst_element_factory_make ("tee", "tee"); @@ -23,20 +23,20 @@ int main(int argc, char *argv[]) { visual = gst_element_factory_make ("wavescope", "visual"); video_convert = gst_element_factory_make ("videoconvert", "video_convert"); video_sink = gst_element_factory_make ("autovideosink", "video_sink"); - + /* Create the empty pipeline */ pipeline = gst_pipeline_new ("test-pipeline"); - + if (!pipeline || !audio_source || !tee || !audio_queue || !audio_convert || !audio_resample || !audio_sink || !video_queue || !visual || !video_convert || !video_sink) { g_printerr ("Not all elements could be created.\n"); return -1; } - + /* Configure elements */ g_object_set (audio_source, "freq", 215.0f, NULL); g_object_set (visual, "shader", 0, "style", 1, NULL); - + /* Link all elements that can be automatically linked because they have "Always" pads */ gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink, video_queue, visual, video_convert, video_sink, NULL); @@ -47,7 +47,7 @@ int main(int argc, char *argv[]) { gst_object_unref (pipeline); return -1; } - + /* Manually link the Tee, which has "Request" pads */ tee_src_pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (tee), "src_%u"); tee_audio_pad = gst_element_request_pad (tee, tee_src_pad_template, NULL, NULL); @@ -64,26 +64,26 @@ int main(int argc, char *argv[]) { } gst_object_unref (queue_audio_pad); gst_object_unref (queue_video_pad); - + /* Start playing the pipeline */ gst_element_set_state (pipeline, GST_STATE_PLAYING); - + /* Wait until error or EOS */ bus = gst_element_get_bus (pipeline); msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - + /* Release the request pads from the Tee, and unref them */ gst_element_release_request_pad (tee, tee_audio_pad); gst_element_release_request_pad (tee, tee_video_pad); gst_object_unref (tee_audio_pad); gst_object_unref (tee_video_pad); - + /* Free resources */ if (msg != NULL) gst_message_unref (msg); gst_object_unref (bus); gst_element_set_state (pipeline, GST_STATE_NULL); - + gst_object_unref (pipeline); return 0; } diff --git a/tutorials/basic-tutorial-8.c b/examples/tutorials/basic-tutorial-8.c similarity index 98% rename from tutorials/basic-tutorial-8.c rename to examples/tutorials/basic-tutorial-8.c index 2ddeaa7..558ac2d 100644 --- a/tutorials/basic-tutorial-8.c +++ b/examples/tutorials/basic-tutorial-8.c @@ -1,24 +1,24 @@ #include #include #include - + #define CHUNK_SIZE 1024 /* Amount of bytes we are sending in each buffer */ #define SAMPLE_RATE 44100 /* Samples per second we are sending */ - + /* Structure to contain all our information, so we can pass it to callbacks */ typedef struct _CustomData { GstElement *pipeline, *app_source, *tee, *audio_queue, *audio_convert1, *audio_resample, *audio_sink; GstElement *video_queue, *audio_convert2, *visual, *video_convert, *video_sink; GstElement *app_queue, *app_sink; - + guint64 num_samples; /* Number of samples generated so far (for timestamp generation) */ gfloat a, b, c, d; /* For waveform generation */ - + guint sourceid; /* To control the GSource */ - + GMainLoop *main_loop; /* GLib's Main Loop */ } CustomData; - + /* This method is called by the idle GSource in the mainloop, to feed CHUNK_SIZE bytes into appsrc. * The idle handler is added to the mainloop when appsrc requests us to start sending data (need-data signal) * and is removed when appsrc has enough data (enough-data signal). @@ -31,14 +31,14 @@ static gboolean push_data (CustomData *data) { gint16 *raw; gint num_samples = CHUNK_SIZE / 2; /* Because each sample is 16 bits */ gfloat freq; - + /* Create a new empty buffer */ buffer = gst_buffer_new_and_alloc (CHUNK_SIZE); - + /* Set its timestamp and duration */ GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (data->num_samples, GST_SECOND, SAMPLE_RATE); GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (CHUNK_SIZE, GST_SECOND, SAMPLE_RATE); - + /* Generate some psychodelic waveforms */ gst_buffer_map (buffer, &map, GST_MAP_WRITE); raw = (gint16 *)map.data; @@ -52,21 +52,21 @@ static gboolean push_data (CustomData *data) { } gst_buffer_unmap (buffer, &map); data->num_samples += num_samples; - + /* Push the buffer into the appsrc */ g_signal_emit_by_name (data->app_source, "push-buffer", buffer, &ret); - + /* Free the buffer now that we are done with it */ gst_buffer_unref (buffer); - + if (ret != GST_FLOW_OK) { /* We got some error, stop sending data */ return FALSE; } - + return TRUE; } - + /* This signal callback triggers when appsrc needs data. Here, we add an idle handler * to the mainloop to start pushing data into the appsrc */ static void start_feed (GstElement *source, guint size, CustomData *data) { @@ -75,7 +75,7 @@ static void start_feed (GstElement *source, guint size, CustomData *data) { data->sourceid = g_idle_add ((GSourceFunc) push_data, data); } } - + /* This callback triggers when appsrc has enough data and we can stop sending. * We remove the idle handler from the mainloop */ static void stop_feed (GstElement *source, CustomData *data) { @@ -85,11 +85,11 @@ static void stop_feed (GstElement *source, CustomData *data) { data->sourceid = 0; } } - + /* The appsink has received a buffer */ static void new_sample (GstElement *sink, CustomData *data) { GstSample *sample; - + /* Retrieve the buffer */ g_signal_emit_by_name (sink, "pull-sample", &sample); if (sample) { @@ -98,22 +98,22 @@ static void new_sample (GstElement *sink, CustomData *data) { gst_sample_unref (sample); } } - + /* This function is called when an error message is posted on the bus */ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GError *err; gchar *debug_info; - + /* Print error details on the screen */ gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); - + g_main_loop_quit (data->main_loop); } - + int main(int argc, char *argv[]) { CustomData data; GstPadTemplate *tee_src_pad_template; @@ -122,15 +122,15 @@ int main(int argc, char *argv[]) { GstAudioInfo info; GstCaps *audio_caps; GstBus *bus; - + /* Initialize cumstom data structure */ memset (&data, 0, sizeof (data)); data.b = 1; /* For waveform generation */ data.d = 1; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Create the elements */ data.app_source = gst_element_factory_make ("appsrc", "audio_source"); data.tee = gst_element_factory_make ("tee", "tee"); @@ -145,34 +145,34 @@ int main(int argc, char *argv[]) { data.video_sink = gst_element_factory_make ("autovideosink", "video_sink"); data.app_queue = gst_element_factory_make ("queue", "app_queue"); data.app_sink = gst_element_factory_make ("appsink", "app_sink"); - + /* Create the empty pipeline */ data.pipeline = gst_pipeline_new ("test-pipeline"); - + if (!data.pipeline || !data.app_source || !data.tee || !data.audio_queue || !data.audio_convert1 || !data.audio_resample || !data.audio_sink || !data.video_queue || !data.audio_convert2 || !data.visual || !data.video_convert || !data.video_sink || !data.app_queue || !data.app_sink) { g_printerr ("Not all elements could be created.\n"); return -1; } - + /* Configure wavescope */ g_object_set (data.visual, "shader", 0, "style", 0, NULL); - + /* Configure appsrc */ gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, SAMPLE_RATE, 1, NULL); audio_caps = gst_audio_info_to_caps (&info); g_object_set (data.app_source, "caps", audio_caps, "format", GST_FORMAT_TIME, NULL); g_signal_connect (data.app_source, "need-data", G_CALLBACK (start_feed), &data); g_signal_connect (data.app_source, "enough-data", G_CALLBACK (stop_feed), &data); - + /* Configure appsink */ g_object_set (data.app_sink, "emit-signals", TRUE, "caps", audio_caps, NULL); g_signal_connect (data.app_sink, "new-sample", G_CALLBACK (new_sample), &data); gst_caps_unref (audio_caps); - + /* Link all elements that can be automatically linked because they have "Always" pads */ - gst_bin_add_many (GST_BIN (data.pipeline), data.app_source, data.tee, data.audio_queue, data.audio_convert1, data.audio_resample, + gst_bin_add_many (GST_BIN (data.pipeline), data.app_source, data.tee, data.audio_queue, data.audio_convert1, data.audio_resample, data.audio_sink, data.video_queue, data.audio_convert2, data.visual, data.video_convert, data.video_sink, data.app_queue, data.app_sink, NULL); if (gst_element_link_many (data.app_source, data.tee, NULL) != TRUE || @@ -183,7 +183,7 @@ int main(int argc, char *argv[]) { gst_object_unref (data.pipeline); return -1; } - + /* Manually link the Tee, which has "Request" pads */ tee_src_pad_template = gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (data.tee), "src_%u"); tee_audio_pad = gst_element_request_pad (data.tee, tee_src_pad_template, NULL, NULL); @@ -205,20 +205,20 @@ int main(int argc, char *argv[]) { gst_object_unref (queue_audio_pad); gst_object_unref (queue_video_pad); gst_object_unref (queue_app_pad); - + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data.pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, &data); gst_object_unref (bus); - + /* Start playing the pipeline */ gst_element_set_state (data.pipeline, GST_STATE_PLAYING); - + /* Create a GLib Main Loop and set it to run */ data.main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data.main_loop); - + /* Release the request pads from the Tee, and unref them */ gst_element_release_request_pad (data.tee, tee_audio_pad); gst_element_release_request_pad (data.tee, tee_video_pad); @@ -226,7 +226,7 @@ int main(int argc, char *argv[]) { gst_object_unref (tee_audio_pad); gst_object_unref (tee_video_pad); gst_object_unref (tee_app_pad); - + /* Free resources */ gst_element_set_state (data.pipeline, GST_STATE_NULL); gst_object_unref (data.pipeline); diff --git a/tutorials/basic-tutorial-9.c b/examples/tutorials/basic-tutorial-9.c similarity index 97% rename from tutorials/basic-tutorial-9.c rename to examples/tutorials/basic-tutorial-9.c index 3e185e8..00b6610 100644 --- a/tutorials/basic-tutorial-9.c +++ b/examples/tutorials/basic-tutorial-9.c @@ -1,40 +1,40 @@ #include #include #include - + /* Structure to contain all our information, so we can pass it around */ typedef struct _CustomData { GstDiscoverer *discoverer; GMainLoop *loop; } CustomData; - + /* Print a tag in a human-readable format (name: value) */ static void print_tag_foreach (const GstTagList *tags, const gchar *tag, gpointer user_data) { GValue val = { 0, }; gchar *str; gint depth = GPOINTER_TO_INT (user_data); - + gst_tag_list_copy_value (&val, tags, tag); - + if (G_VALUE_HOLDS_STRING (&val)) str = g_value_dup_string (&val); else str = gst_value_serialize (&val); - + g_print ("%*s%s: %s\n", 2 * depth, " ", gst_tag_get_nick (tag), str); g_free (str); - + g_value_unset (&val); } - + /* Print information regarding a stream */ static void print_stream_info (GstDiscovererStreamInfo *info, gint depth) { gchar *desc = NULL; GstCaps *caps; const GstTagList *tags; - + caps = gst_discoverer_stream_info_get_caps (info); - + if (caps) { if (gst_caps_is_fixed (caps)) desc = gst_pb_utils_get_codec_description (caps); @@ -42,37 +42,37 @@ static void print_stream_info (GstDiscovererStreamInfo *info, gint depth) { desc = gst_caps_to_string (caps); gst_caps_unref (caps); } - + g_print ("%*s%s: %s\n", 2 * depth, " ", gst_discoverer_stream_info_get_stream_type_nick (info), (desc ? desc : "")); - + if (desc) { g_free (desc); desc = NULL; } - + tags = gst_discoverer_stream_info_get_tags (info); if (tags) { g_print ("%*sTags:\n", 2 * (depth + 1), " "); gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (depth + 2)); } } - + /* Print information regarding a stream and its substreams, if any */ static void print_topology (GstDiscovererStreamInfo *info, gint depth) { GstDiscovererStreamInfo *next; - + if (!info) return; - + print_stream_info (info, depth); - + next = gst_discoverer_stream_info_get_next (info); if (next) { print_topology (next, depth + 1); gst_discoverer_stream_info_unref (next); } else if (GST_IS_DISCOVERER_CONTAINER_INFO (info)) { GList *tmp, *streams; - + streams = gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO (info)); for (tmp = streams; tmp; tmp = tmp->next) { GstDiscovererStreamInfo *tmpinf = (GstDiscovererStreamInfo *) tmp->data; @@ -81,7 +81,7 @@ static void print_topology (GstDiscovererStreamInfo *info, gint depth) { gst_discoverer_stream_info_list_free (streams); } } - + /* This function is called every time the discoverer has information regarding * one of the URIs we provided.*/ static void on_discovered_cb (GstDiscoverer *discoverer, GstDiscovererInfo *info, GError *err, CustomData *data) { @@ -89,7 +89,7 @@ static void on_discovered_cb (GstDiscoverer *discoverer, GstDiscovererInfo *info const gchar *uri; const GstTagList *tags; GstDiscovererStreamInfo *sinfo; - + uri = gst_discoverer_info_get_uri (info); result = gst_discoverer_info_get_result (info); switch (result) { @@ -108,10 +108,10 @@ static void on_discovered_cb (GstDiscoverer *discoverer, GstDiscovererInfo *info case GST_DISCOVERER_MISSING_PLUGINS:{ const GstStructure *s; gchar *str; - + s = gst_discoverer_info_get_misc (info); str = gst_structure_to_string (s); - + g_print ("Missing plugins: %s\n", str); g_free (str); break; @@ -120,65 +120,65 @@ static void on_discovered_cb (GstDiscoverer *discoverer, GstDiscovererInfo *info g_print ("Discovered '%s'\n", uri); break; } - + if (result != GST_DISCOVERER_OK) { g_printerr ("This URI cannot be played\n"); return; } - + /* If we got no error, show the retrieved information */ - + g_print ("\nDuration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (gst_discoverer_info_get_duration (info))); - + tags = gst_discoverer_info_get_tags (info); if (tags) { g_print ("Tags:\n"); gst_tag_list_foreach (tags, print_tag_foreach, GINT_TO_POINTER (1)); } - + g_print ("Seekable: %s\n", (gst_discoverer_info_get_seekable (info) ? "yes" : "no")); - + g_print ("\n"); - + sinfo = gst_discoverer_info_get_stream_info (info); if (!sinfo) return; - + g_print ("Stream information:\n"); - + print_topology (sinfo, 1); - + gst_discoverer_stream_info_unref (sinfo); - + g_print ("\n"); } - + /* This function is called when the discoverer has finished examining * all the URIs we provided.*/ static void on_finished_cb (GstDiscoverer *discoverer, CustomData *data) { g_print ("Finished discovering\n"); - + g_main_loop_quit (data->loop); } - + int main (int argc, char **argv) { CustomData data; GError *err = NULL; gchar *uri = "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm"; - + /* if a URI was provided, use it instead of the default one */ if (argc > 1) { uri = argv[1]; } - + /* Initialize cumstom data structure */ memset (&data, 0, sizeof (data)); - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + g_print ("Discovering '%s'\n", uri); - + /* Instantiate the Discoverer */ data.discoverer = gst_discoverer_new (5 * GST_SECOND, &err); if (!data.discoverer) { @@ -186,31 +186,31 @@ int main (int argc, char **argv) { g_clear_error (&err); return -1; } - + /* Connect to the interesting signals */ g_signal_connect (data.discoverer, "discovered", G_CALLBACK (on_discovered_cb), &data); g_signal_connect (data.discoverer, "finished", G_CALLBACK (on_finished_cb), &data); - + /* Start the discoverer process (nothing to do yet) */ gst_discoverer_start (data.discoverer); - + /* Add a request to process asynchronously the URI passed through the command line */ if (!gst_discoverer_discover_uri_async (data.discoverer, uri)) { g_print ("Failed to start discovering URI '%s'\n", uri); g_object_unref (data.discoverer); return -1; } - + /* Create a GLib Main Loop and set it to run, so we can wait for the signals */ data.loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data.loop); - + /* Stop the discoverer process */ gst_discoverer_stop (data.discoverer); - + /* Free resources */ g_object_unref (data.discoverer); g_main_loop_unref (data.loop); - + return 0; } \ No newline at end of file diff --git a/tutorials/icons/gstreamer-logo-1.svg b/examples/tutorials/icons/gstreamer-logo-1.svg similarity index 100% rename from tutorials/icons/gstreamer-logo-1.svg rename to examples/tutorials/icons/gstreamer-logo-1.svg diff --git a/tutorials/icons/gstreamer-logo-2.svg b/examples/tutorials/icons/gstreamer-logo-2.svg similarity index 100% rename from tutorials/icons/gstreamer-logo-2.svg rename to examples/tutorials/icons/gstreamer-logo-2.svg diff --git a/tutorials/icons/gstreamer-logo-3.svg b/examples/tutorials/icons/gstreamer-logo-3.svg similarity index 100% rename from tutorials/icons/gstreamer-logo-3.svg rename to examples/tutorials/icons/gstreamer-logo-3.svg diff --git a/tutorials/icons/gstreamer-logo-4.svg b/examples/tutorials/icons/gstreamer-logo-4.svg similarity index 100% rename from tutorials/icons/gstreamer-logo-4.svg rename to examples/tutorials/icons/gstreamer-logo-4.svg diff --git a/tutorials/icons/gstreamer-logo-5.svg b/examples/tutorials/icons/gstreamer-logo-5.svg similarity index 100% rename from tutorials/icons/gstreamer-logo-5.svg rename to examples/tutorials/icons/gstreamer-logo-5.svg diff --git a/tutorials/playback-tutorial-1.c b/examples/tutorials/playback-tutorial-1.c similarity index 96% rename from tutorials/playback-tutorial-1.c rename to examples/tutorials/playback-tutorial-1.c index b142fa7..f1987f3 100644 --- a/tutorials/playback-tutorial-1.c +++ b/examples/tutorials/playback-tutorial-1.c @@ -1,221 +1,221 @@ -#include -#include - -/* Structure to contain all our information, so we can pass it around */ -typedef struct _CustomData { - GstElement *playbin; /* Our one and only element */ - - gint n_video; /* Number of embedded video streams */ - gint n_audio; /* Number of embedded audio streams */ - gint n_text; /* Number of embedded subtitle streams */ - - gint current_video; /* Currently playing video stream */ - gint current_audio; /* Currently playing audio stream */ - gint current_text; /* Currently playing subtitle stream */ - - GMainLoop *main_loop; /* GLib's Main Loop */ -} CustomData; - -/* playbin flags */ -typedef enum { - GST_PLAY_FLAG_VIDEO = (1 << 0), /* We want video output */ - GST_PLAY_FLAG_AUDIO = (1 << 1), /* We want audio output */ - GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ -} GstPlayFlags; - -/* Forward definition for the message and keyboard processing functions */ -static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data); -static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data); - -int main(int argc, char *argv[]) { - CustomData data; - GstBus *bus; - GstStateChangeReturn ret; - gint flags; - GIOChannel *io_stdin; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the elements */ - data.playbin = gst_element_factory_make ("playbin", "playbin"); - - if (!data.playbin) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Set the URI to play */ - g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm", NULL); - - /* Set flags to show Audio and Video but ignore Subtitles */ - g_object_get (data.playbin, "flags", &flags, NULL); - flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO; - flags &= ~GST_PLAY_FLAG_TEXT; - g_object_set (data.playbin, "flags", flags, NULL); - - /* Set connection speed. This will affect some internal decisions of playbin */ - g_object_set (data.playbin, "connection-speed", 56, NULL); - - /* Add a bus watch, so we get notified when a message arrives */ - bus = gst_element_get_bus (data.playbin); - gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data); - - /* Add a keyboard watch so we get notified of keystrokes */ -#ifdef G_OS_WIN32 - io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); -#else - io_stdin = g_io_channel_unix_new (fileno (stdin)); -#endif - g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); - - /* Start playing */ - ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (data.playbin); - return -1; - } - - /* Create a GLib Main Loop and set it to run */ - data.main_loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (data.main_loop); - - /* Free resources */ - g_main_loop_unref (data.main_loop); - g_io_channel_unref (io_stdin); - gst_object_unref (bus); - gst_element_set_state (data.playbin, GST_STATE_NULL); - gst_object_unref (data.playbin); - return 0; -} - -/* Extract some metadata from the streams and print it on the screen */ -static void analyze_streams (CustomData *data) { - gint i; - GstTagList *tags; - gchar *str; - guint rate; - - /* Read some properties */ - g_object_get (data->playbin, "n-video", &data->n_video, NULL); - g_object_get (data->playbin, "n-audio", &data->n_audio, NULL); - g_object_get (data->playbin, "n-text", &data->n_text, NULL); - - g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n", - data->n_video, data->n_audio, data->n_text); - - g_print ("\n"); - for (i = 0; i < data->n_video; i++) { - tags = NULL; - /* Retrieve the stream's video tags */ - g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags); - if (tags) { - g_print ("video stream %d:\n", i); - gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str); - g_print (" codec: %s\n", str ? str : "unknown"); - g_free (str); - gst_tag_list_unref (tags); - } - } - - g_print ("\n"); - for (i = 0; i < data->n_audio; i++) { - tags = NULL; - /* Retrieve the stream's audio tags */ - g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags); - if (tags) { - g_print ("audio stream %d:\n", i); - if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) { - g_print (" codec: %s\n", str); - g_free (str); - } - if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { - g_print (" language: %s\n", str); - g_free (str); - } - if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) { - g_print (" bitrate: %d\n", rate); - } - gst_tag_list_unref (tags); - } - } - - g_print ("\n"); - for (i = 0; i < data->n_text; i++) { - tags = NULL; - /* Retrieve the stream's subtitle tags */ - g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags); - if (tags) { - g_print ("subtitle stream %d:\n", i); - if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { - g_print (" language: %s\n", str); - g_free (str); - } - gst_tag_list_unref (tags); - } - } - - g_object_get (data->playbin, "current-video", &data->current_video, NULL); - g_object_get (data->playbin, "current-audio", &data->current_audio, NULL); - g_object_get (data->playbin, "current-text", &data->current_text, NULL); - - g_print ("\n"); - g_print ("Currently playing video stream %d, audio stream %d and text stream %d\n", - data->current_video, data->current_audio, data->current_text); - g_print ("Type any number and hit ENTER to select a different audio stream\n"); -} - -/* Process messages from GStreamer */ -static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - g_main_loop_quit (data->main_loop); - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - g_main_loop_quit (data->main_loop); - break; - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { - if (new_state == GST_STATE_PLAYING) { - /* Once we are in the playing state, analyze the streams */ - analyze_streams (data); - } - } - } break; - default: - break; - } - - /* We want to keep receiving messages */ - return TRUE; -} - -/* Process keyboard input */ -static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { - gchar *str = NULL; - - if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) { - int index = g_ascii_strtoull (str, NULL, 0); - if (index < 0 || index >= data->n_audio) { - g_printerr ("Index out of bounds\n"); - } else { - /* If the input was a valid audio stream index, set the current audio stream */ - g_print ("Setting current audio stream to %d\n", index); - g_object_set (data->playbin, "current-audio", index, NULL); - } - } - g_free (str); - return TRUE; -} +#include +#include + +/* Structure to contain all our information, so we can pass it around */ +typedef struct _CustomData { + GstElement *playbin; /* Our one and only element */ + + gint n_video; /* Number of embedded video streams */ + gint n_audio; /* Number of embedded audio streams */ + gint n_text; /* Number of embedded subtitle streams */ + + gint current_video; /* Currently playing video stream */ + gint current_audio; /* Currently playing audio stream */ + gint current_text; /* Currently playing subtitle stream */ + + GMainLoop *main_loop; /* GLib's Main Loop */ +} CustomData; + +/* playbin flags */ +typedef enum { + GST_PLAY_FLAG_VIDEO = (1 << 0), /* We want video output */ + GST_PLAY_FLAG_AUDIO = (1 << 1), /* We want audio output */ + GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ +} GstPlayFlags; + +/* Forward definition for the message and keyboard processing functions */ +static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data); +static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data); + +int main(int argc, char *argv[]) { + CustomData data; + GstBus *bus; + GstStateChangeReturn ret; + gint flags; + GIOChannel *io_stdin; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the elements */ + data.playbin = gst_element_factory_make ("playbin", "playbin"); + + if (!data.playbin) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Set the URI to play */ + g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_cropped_multilingual.webm", NULL); + + /* Set flags to show Audio and Video but ignore Subtitles */ + g_object_get (data.playbin, "flags", &flags, NULL); + flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO; + flags &= ~GST_PLAY_FLAG_TEXT; + g_object_set (data.playbin, "flags", flags, NULL); + + /* Set connection speed. This will affect some internal decisions of playbin */ + g_object_set (data.playbin, "connection-speed", 56, NULL); + + /* Add a bus watch, so we get notified when a message arrives */ + bus = gst_element_get_bus (data.playbin); + gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data); + + /* Add a keyboard watch so we get notified of keystrokes */ +#ifdef G_OS_WIN32 + io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); +#else + io_stdin = g_io_channel_unix_new (fileno (stdin)); +#endif + g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); + + /* Start playing */ + ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (data.playbin); + return -1; + } + + /* Create a GLib Main Loop and set it to run */ + data.main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (data.main_loop); + + /* Free resources */ + g_main_loop_unref (data.main_loop); + g_io_channel_unref (io_stdin); + gst_object_unref (bus); + gst_element_set_state (data.playbin, GST_STATE_NULL); + gst_object_unref (data.playbin); + return 0; +} + +/* Extract some metadata from the streams and print it on the screen */ +static void analyze_streams (CustomData *data) { + gint i; + GstTagList *tags; + gchar *str; + guint rate; + + /* Read some properties */ + g_object_get (data->playbin, "n-video", &data->n_video, NULL); + g_object_get (data->playbin, "n-audio", &data->n_audio, NULL); + g_object_get (data->playbin, "n-text", &data->n_text, NULL); + + g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n", + data->n_video, data->n_audio, data->n_text); + + g_print ("\n"); + for (i = 0; i < data->n_video; i++) { + tags = NULL; + /* Retrieve the stream's video tags */ + g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags); + if (tags) { + g_print ("video stream %d:\n", i); + gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str); + g_print (" codec: %s\n", str ? str : "unknown"); + g_free (str); + gst_tag_list_unref (tags); + } + } + + g_print ("\n"); + for (i = 0; i < data->n_audio; i++) { + tags = NULL; + /* Retrieve the stream's audio tags */ + g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags); + if (tags) { + g_print ("audio stream %d:\n", i); + if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) { + g_print (" codec: %s\n", str); + g_free (str); + } + if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { + g_print (" language: %s\n", str); + g_free (str); + } + if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) { + g_print (" bitrate: %d\n", rate); + } + gst_tag_list_unref (tags); + } + } + + g_print ("\n"); + for (i = 0; i < data->n_text; i++) { + tags = NULL; + /* Retrieve the stream's subtitle tags */ + g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags); + if (tags) { + g_print ("subtitle stream %d:\n", i); + if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { + g_print (" language: %s\n", str); + g_free (str); + } + gst_tag_list_unref (tags); + } + } + + g_object_get (data->playbin, "current-video", &data->current_video, NULL); + g_object_get (data->playbin, "current-audio", &data->current_audio, NULL); + g_object_get (data->playbin, "current-text", &data->current_text, NULL); + + g_print ("\n"); + g_print ("Currently playing video stream %d, audio stream %d and text stream %d\n", + data->current_video, data->current_audio, data->current_text); + g_print ("Type any number and hit ENTER to select a different audio stream\n"); +} + +/* Process messages from GStreamer */ +static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + g_main_loop_quit (data->main_loop); + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + g_main_loop_quit (data->main_loop); + break; + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { + if (new_state == GST_STATE_PLAYING) { + /* Once we are in the playing state, analyze the streams */ + analyze_streams (data); + } + } + } break; + default: + break; + } + + /* We want to keep receiving messages */ + return TRUE; +} + +/* Process keyboard input */ +static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { + gchar *str = NULL; + + if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) { + int index = g_ascii_strtoull (str, NULL, 0); + if (index < 0 || index >= data->n_audio) { + g_printerr ("Index out of bounds\n"); + } else { + /* If the input was a valid audio stream index, set the current audio stream */ + g_print ("Setting current audio stream to %d\n", index); + g_object_set (data->playbin, "current-audio", index, NULL); + } + } + g_free (str); + return TRUE; +} diff --git a/tutorials/playback-tutorial-2.c b/examples/tutorials/playback-tutorial-2.c similarity index 96% rename from tutorials/playback-tutorial-2.c rename to examples/tutorials/playback-tutorial-2.c index 52d3f6f..f11eccc 100644 --- a/tutorials/playback-tutorial-2.c +++ b/examples/tutorials/playback-tutorial-2.c @@ -1,223 +1,223 @@ -#include -#include - -/* Structure to contain all our information, so we can pass it around */ -typedef struct _CustomData { - GstElement *playbin; /* Our one and only element */ - - gint n_video; /* Number of embedded video streams */ - gint n_audio; /* Number of embedded audio streams */ - gint n_text; /* Number of embedded subtitle streams */ - - gint current_video; /* Currently playing video stream */ - gint current_audio; /* Currently playing audio stream */ - gint current_text; /* Currently playing subtitle stream */ - - GMainLoop *main_loop; /* GLib's Main Loop */ -} CustomData; - -/* playbin flags */ -typedef enum { - GST_PLAY_FLAG_VIDEO = (1 << 0), /* We want video output */ - GST_PLAY_FLAG_AUDIO = (1 << 1), /* We want audio output */ - GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ -} GstPlayFlags; - -/* Forward definition for the message and keyboard processing functions */ -static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data); -static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data); - -int main(int argc, char *argv[]) { - CustomData data; - GstBus *bus; - GstStateChangeReturn ret; - gint flags; - GIOChannel *io_stdin; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Create the elements */ - data.playbin = gst_element_factory_make ("playbin", "playbin"); - - if (!data.playbin) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Set the URI to play */ - g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv", NULL); - - /* Set the subtitle URI to play and some font description */ - g_object_set (data.playbin, "suburi", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer_gr.srt", NULL); - g_object_set (data.playbin, "subtitle-font-desc", "Sans, 18", NULL); - - /* Set flags to show Audio, Video and Subtitles */ - g_object_get (data.playbin, "flags", &flags, NULL); - flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_TEXT; - g_object_set (data.playbin, "flags", flags, NULL); - - /* Add a bus watch, so we get notified when a message arrives */ - bus = gst_element_get_bus (data.playbin); - gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data); - - /* Add a keyboard watch so we get notified of keystrokes */ -#ifdef G_OS_WIN32 - io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); -#else - io_stdin = g_io_channel_unix_new (fileno (stdin)); -#endif - g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); - - /* Start playing */ - ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Unable to set the pipeline to the playing state.\n"); - gst_object_unref (data.playbin); - return -1; - } - - /* Create a GLib Main Loop and set it to run */ - data.main_loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (data.main_loop); - - /* Free resources */ - g_main_loop_unref (data.main_loop); - g_io_channel_unref (io_stdin); - gst_object_unref (bus); - gst_element_set_state (data.playbin, GST_STATE_NULL); - gst_object_unref (data.playbin); - return 0; -} - -/* Extract some metadata from the streams and print it on the screen */ -static void analyze_streams (CustomData *data) { - gint i; - GstTagList *tags; - gchar *str; - guint rate; - - /* Read some properties */ - g_object_get (data->playbin, "n-video", &data->n_video, NULL); - g_object_get (data->playbin, "n-audio", &data->n_audio, NULL); - g_object_get (data->playbin, "n-text", &data->n_text, NULL); - - g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n", - data->n_video, data->n_audio, data->n_text); - - g_print ("\n"); - for (i = 0; i < data->n_video; i++) { - tags = NULL; - /* Retrieve the stream's video tags */ - g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags); - if (tags) { - g_print ("video stream %d:\n", i); - gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str); - g_print (" codec: %s\n", str ? str : "unknown"); - g_free (str); - gst_tag_list_free (tags); - } - } - - g_print ("\n"); - for (i = 0; i < data->n_audio; i++) { - tags = NULL; - /* Retrieve the stream's audio tags */ - g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags); - if (tags) { - g_print ("audio stream %d:\n", i); - if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) { - g_print (" codec: %s\n", str); - g_free (str); - } - if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { - g_print (" language: %s\n", str); - g_free (str); - } - if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) { - g_print (" bitrate: %d\n", rate); - } - gst_tag_list_free (tags); - } - } - - g_print ("\n"); - for (i = 0; i < data->n_text; i++) { - tags = NULL; - /* Retrieve the stream's subtitle tags */ - g_print ("subtitle stream %d:\n", i); - g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags); - if (tags) { - if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { - g_print (" language: %s\n", str); - g_free (str); - } - gst_tag_list_free (tags); - } else { - g_print (" no tags found\n"); - } - } - - g_object_get (data->playbin, "current-video", &data->current_video, NULL); - g_object_get (data->playbin, "current-audio", &data->current_audio, NULL); - g_object_get (data->playbin, "current-text", &data->current_text, NULL); - - g_print ("\n"); - g_print ("Currently playing video stream %d, audio stream %d and subtitle stream %d\n", - data->current_video, data->current_audio, data->current_text); - g_print ("Type any number and hit ENTER to select a different subtitle stream\n"); -} - -/* Process messages from GStreamer */ -static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) { - GError *err; - gchar *debug_info; - - switch (GST_MESSAGE_TYPE (msg)) { - case GST_MESSAGE_ERROR: - gst_message_parse_error (msg, &err, &debug_info); - g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); - g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); - g_clear_error (&err); - g_free (debug_info); - g_main_loop_quit (data->main_loop); - break; - case GST_MESSAGE_EOS: - g_print ("End-Of-Stream reached.\n"); - g_main_loop_quit (data->main_loop); - break; - case GST_MESSAGE_STATE_CHANGED: { - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { - if (new_state == GST_STATE_PLAYING) { - /* Once we are in the playing state, analyze the streams */ - analyze_streams (data); - } - } - } break; - default: - break; - } - - /* We want to keep receiving messages */ - return TRUE; -} - -/* Process keyboard input */ -static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { - gchar *str = NULL; - - if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) { - int index = g_ascii_strtoull (str, NULL, 0); - if (index < 0 || index >= data->n_text) { - g_printerr ("Index out of bounds\n"); - } else { - /* If the input was a valid subtitle stream index, set the current subtitle stream */ - g_print ("Setting current subtitle stream to %d\n", index); - g_object_set (data->playbin, "current-text", index, NULL); - } - } - g_free (str); - return TRUE; -} +#include +#include + +/* Structure to contain all our information, so we can pass it around */ +typedef struct _CustomData { + GstElement *playbin; /* Our one and only element */ + + gint n_video; /* Number of embedded video streams */ + gint n_audio; /* Number of embedded audio streams */ + gint n_text; /* Number of embedded subtitle streams */ + + gint current_video; /* Currently playing video stream */ + gint current_audio; /* Currently playing audio stream */ + gint current_text; /* Currently playing subtitle stream */ + + GMainLoop *main_loop; /* GLib's Main Loop */ +} CustomData; + +/* playbin flags */ +typedef enum { + GST_PLAY_FLAG_VIDEO = (1 << 0), /* We want video output */ + GST_PLAY_FLAG_AUDIO = (1 << 1), /* We want audio output */ + GST_PLAY_FLAG_TEXT = (1 << 2) /* We want subtitle output */ +} GstPlayFlags; + +/* Forward definition for the message and keyboard processing functions */ +static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data); +static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data); + +int main(int argc, char *argv[]) { + CustomData data; + GstBus *bus; + GstStateChangeReturn ret; + gint flags; + GIOChannel *io_stdin; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Create the elements */ + data.playbin = gst_element_factory_make ("playbin", "playbin"); + + if (!data.playbin) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Set the URI to play */ + g_object_set (data.playbin, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.ogv", NULL); + + /* Set the subtitle URI to play and some font description */ + g_object_set (data.playbin, "suburi", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer_gr.srt", NULL); + g_object_set (data.playbin, "subtitle-font-desc", "Sans, 18", NULL); + + /* Set flags to show Audio, Video and Subtitles */ + g_object_get (data.playbin, "flags", &flags, NULL); + flags |= GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_TEXT; + g_object_set (data.playbin, "flags", flags, NULL); + + /* Add a bus watch, so we get notified when a message arrives */ + bus = gst_element_get_bus (data.playbin); + gst_bus_add_watch (bus, (GstBusFunc)handle_message, &data); + + /* Add a keyboard watch so we get notified of keystrokes */ +#ifdef G_OS_WIN32 + io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); +#else + io_stdin = g_io_channel_unix_new (fileno (stdin)); +#endif + g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); + + /* Start playing */ + ret = gst_element_set_state (data.playbin, GST_STATE_PLAYING); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Unable to set the pipeline to the playing state.\n"); + gst_object_unref (data.playbin); + return -1; + } + + /* Create a GLib Main Loop and set it to run */ + data.main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (data.main_loop); + + /* Free resources */ + g_main_loop_unref (data.main_loop); + g_io_channel_unref (io_stdin); + gst_object_unref (bus); + gst_element_set_state (data.playbin, GST_STATE_NULL); + gst_object_unref (data.playbin); + return 0; +} + +/* Extract some metadata from the streams and print it on the screen */ +static void analyze_streams (CustomData *data) { + gint i; + GstTagList *tags; + gchar *str; + guint rate; + + /* Read some properties */ + g_object_get (data->playbin, "n-video", &data->n_video, NULL); + g_object_get (data->playbin, "n-audio", &data->n_audio, NULL); + g_object_get (data->playbin, "n-text", &data->n_text, NULL); + + g_print ("%d video stream(s), %d audio stream(s), %d text stream(s)\n", + data->n_video, data->n_audio, data->n_text); + + g_print ("\n"); + for (i = 0; i < data->n_video; i++) { + tags = NULL; + /* Retrieve the stream's video tags */ + g_signal_emit_by_name (data->playbin, "get-video-tags", i, &tags); + if (tags) { + g_print ("video stream %d:\n", i); + gst_tag_list_get_string (tags, GST_TAG_VIDEO_CODEC, &str); + g_print (" codec: %s\n", str ? str : "unknown"); + g_free (str); + gst_tag_list_free (tags); + } + } + + g_print ("\n"); + for (i = 0; i < data->n_audio; i++) { + tags = NULL; + /* Retrieve the stream's audio tags */ + g_signal_emit_by_name (data->playbin, "get-audio-tags", i, &tags); + if (tags) { + g_print ("audio stream %d:\n", i); + if (gst_tag_list_get_string (tags, GST_TAG_AUDIO_CODEC, &str)) { + g_print (" codec: %s\n", str); + g_free (str); + } + if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { + g_print (" language: %s\n", str); + g_free (str); + } + if (gst_tag_list_get_uint (tags, GST_TAG_BITRATE, &rate)) { + g_print (" bitrate: %d\n", rate); + } + gst_tag_list_free (tags); + } + } + + g_print ("\n"); + for (i = 0; i < data->n_text; i++) { + tags = NULL; + /* Retrieve the stream's subtitle tags */ + g_print ("subtitle stream %d:\n", i); + g_signal_emit_by_name (data->playbin, "get-text-tags", i, &tags); + if (tags) { + if (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, &str)) { + g_print (" language: %s\n", str); + g_free (str); + } + gst_tag_list_free (tags); + } else { + g_print (" no tags found\n"); + } + } + + g_object_get (data->playbin, "current-video", &data->current_video, NULL); + g_object_get (data->playbin, "current-audio", &data->current_audio, NULL); + g_object_get (data->playbin, "current-text", &data->current_text, NULL); + + g_print ("\n"); + g_print ("Currently playing video stream %d, audio stream %d and subtitle stream %d\n", + data->current_video, data->current_audio, data->current_text); + g_print ("Type any number and hit ENTER to select a different subtitle stream\n"); +} + +/* Process messages from GStreamer */ +static gboolean handle_message (GstBus *bus, GstMessage *msg, CustomData *data) { + GError *err; + gchar *debug_info; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (msg, &err, &debug_info); + g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); + g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); + g_clear_error (&err); + g_free (debug_info); + g_main_loop_quit (data->main_loop); + break; + case GST_MESSAGE_EOS: + g_print ("End-Of-Stream reached.\n"); + g_main_loop_quit (data->main_loop); + break; + case GST_MESSAGE_STATE_CHANGED: { + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data->playbin)) { + if (new_state == GST_STATE_PLAYING) { + /* Once we are in the playing state, analyze the streams */ + analyze_streams (data); + } + } + } break; + default: + break; + } + + /* We want to keep receiving messages */ + return TRUE; +} + +/* Process keyboard input */ +static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { + gchar *str = NULL; + + if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) == G_IO_STATUS_NORMAL) { + int index = g_ascii_strtoull (str, NULL, 0); + if (index < 0 || index >= data->n_text) { + g_printerr ("Index out of bounds\n"); + } else { + /* If the input was a valid subtitle stream index, set the current subtitle stream */ + g_print ("Setting current subtitle stream to %d\n", index); + g_object_set (data->playbin, "current-text", index, NULL); + } + } + g_free (str); + return TRUE; +} diff --git a/tutorials/playback-tutorial-3.c b/examples/tutorials/playback-tutorial-3.c similarity index 98% rename from tutorials/playback-tutorial-3.c rename to examples/tutorials/playback-tutorial-3.c index 4f8b809..cea556f 100644 --- a/tutorials/playback-tutorial-3.c +++ b/examples/tutorials/playback-tutorial-3.c @@ -1,23 +1,23 @@ #include #include #include - + #define CHUNK_SIZE 1024 /* Amount of bytes we are sending in each buffer */ #define SAMPLE_RATE 44100 /* Samples per second we are sending */ - + /* Structure to contain all our information, so we can pass it to callbacks */ typedef struct _CustomData { GstElement *pipeline; GstElement *app_source; - + guint64 num_samples; /* Number of samples generated so far (for timestamp generation) */ gfloat a, b, c, d; /* For waveform generation */ - + guint sourceid; /* To control the GSource */ - + GMainLoop *main_loop; /* GLib's Main Loop */ } CustomData; - + /* This method is called by the idle GSource in the mainloop, to feed CHUNK_SIZE bytes into appsrc. * The ide handler is added to the mainloop when appsrc requests us to start sending data (need-data signal) * and is removed when appsrc has enough data (enough-data signal). @@ -30,14 +30,14 @@ static gboolean push_data (CustomData *data) { gint16 *raw; gint num_samples = CHUNK_SIZE / 2; /* Because each sample is 16 bits */ gfloat freq; - + /* Create a new empty buffer */ buffer = gst_buffer_new_and_alloc (CHUNK_SIZE); - + /* Set its timestamp and duration */ GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (data->num_samples, GST_SECOND, SAMPLE_RATE); GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale (CHUNK_SIZE, GST_SECOND, SAMPLE_RATE); - + /* Generate some psychodelic waveforms */ gst_buffer_map (buffer, &map, GST_MAP_WRITE); raw = (gint16 *)map.data; @@ -51,21 +51,21 @@ static gboolean push_data (CustomData *data) { } gst_buffer_unmap (buffer, &map); data->num_samples += num_samples; - + /* Push the buffer into the appsrc */ g_signal_emit_by_name (data->app_source, "push-buffer", buffer, &ret); - + /* Free the buffer now that we are done with it */ gst_buffer_unref (buffer); - + if (ret != GST_FLOW_OK) { /* We got some error, stop sending data */ return FALSE; } - + return TRUE; } - + /* This signal callback triggers when appsrc needs data. Here, we add an idle handler * to the mainloop to start pushing data into the appsrc */ static void start_feed (GstElement *source, guint size, CustomData *data) { @@ -74,7 +74,7 @@ static void start_feed (GstElement *source, guint size, CustomData *data) { data->sourceid = g_idle_add ((GSourceFunc) push_data, data); } } - + /* This callback triggers when appsrc has enough data and we can stop sending. * We remove the idle handler from the mainloop */ static void stop_feed (GstElement *source, CustomData *data) { @@ -84,31 +84,31 @@ static void stop_feed (GstElement *source, CustomData *data) { data->sourceid = 0; } } - + /* This function is called when an error message is posted on the bus */ static void error_cb (GstBus *bus, GstMessage *msg, CustomData *data) { GError *err; gchar *debug_info; - + /* Print error details on the screen */ gst_message_parse_error (msg, &err, &debug_info); g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message); g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none"); g_clear_error (&err); g_free (debug_info); - + g_main_loop_quit (data->main_loop); } - + /* This function is called when playbin has created the appsrc element, so we have * a chance to configure it. */ static void source_setup (GstElement *pipeline, GstElement *source, CustomData *data) { GstAudioInfo info; GstCaps *audio_caps; - + g_print ("Source has been created. Configuring.\n"); data->app_source = source; - + /* Configure appsrc */ gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16, SAMPLE_RATE, 1, NULL); audio_caps = gst_audio_info_to_caps (&info); @@ -117,36 +117,36 @@ static void source_setup (GstElement *pipeline, GstElement *source, CustomData * g_signal_connect (source, "enough-data", G_CALLBACK (stop_feed), data); gst_caps_unref (audio_caps); } - + int main(int argc, char *argv[]) { CustomData data; GstBus *bus; - + /* Initialize cumstom data structure */ memset (&data, 0, sizeof (data)); data.b = 1; /* For waveform generation */ data.d = 1; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Create the playbin element */ data.pipeline = gst_parse_launch ("playbin uri=appsrc://", NULL); g_signal_connect (data.pipeline, "source-setup", G_CALLBACK (source_setup), &data); - + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (data.pipeline); gst_bus_add_signal_watch (bus); g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, &data); gst_object_unref (bus); - + /* Start playing the pipeline */ gst_element_set_state (data.pipeline, GST_STATE_PLAYING); - + /* Create a GLib Main Loop and set it to run */ data.main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data.main_loop); - + /* Free resources */ gst_element_set_state (data.pipeline, GST_STATE_NULL); gst_object_unref (data.pipeline); diff --git a/tutorials/playback-tutorial-4.c b/examples/tutorials/playback-tutorial-4.c similarity index 98% rename from tutorials/playback-tutorial-4.c rename to examples/tutorials/playback-tutorial-4.c index cfcf434..4a8e007 100644 --- a/tutorials/playback-tutorial-4.c +++ b/examples/tutorials/playback-tutorial-4.c @@ -1,20 +1,20 @@ #include #include - + #define GRAPH_LENGTH 78 - + /* playbin flags */ typedef enum { GST_PLAY_FLAG_DOWNLOAD = (1 << 7) /* Enable progressive download (on selected formats) */ } GstPlayFlags; - + typedef struct _CustomData { gboolean is_live; GstElement *pipeline; GMainLoop *loop; gint buffering_level; } CustomData; - + static void got_location (GstObject *gstobject, GstObject *prop_object, GParamSpec *prop, gpointer data) { gchar *location; g_object_get (G_OBJECT (prop_object), "temp-location", &location, NULL); @@ -23,19 +23,19 @@ static void got_location (GstObject *gstobject, GstObject *prop_object, GParamSp /* Uncomment this line to keep the temporary file after the program exits */ /* g_object_set (G_OBJECT (prop_object), "temp-remove", FALSE, NULL); */ } - + static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) { - + switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_ERROR: { GError *err; gchar *debug; - + gst_message_parse_error (msg, &err, &debug); g_print ("Error: %s\n", err->message); g_error_free (err); g_free (debug); - + gst_element_set_state (data->pipeline, GST_STATE_READY); g_main_loop_quit (data->loop); break; @@ -48,9 +48,9 @@ static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) { case GST_MESSAGE_BUFFERING: /* If the stream is live, we do not care about buffering. */ if (data->is_live) break; - + gst_message_parse_buffering (msg, &data->buffering_level); - + /* Wait until buffering is complete before start/resume playing */ if (data->buffering_level < 100) gst_element_set_state (data->pipeline, GST_STATE_PAUSED); @@ -67,21 +67,21 @@ static void cb_message (GstBus *bus, GstMessage *msg, CustomData *data) { break; } } - + static gboolean refresh_ui (CustomData *data) { GstQuery *query; gboolean result; - + query = gst_query_new_buffering (GST_FORMAT_PERCENT); result = gst_element_query (data->pipeline, query); if (result) { gint n_ranges, range, i; gchar graph[GRAPH_LENGTH + 1]; gint64 position = 0, duration = 0; - + memset (graph, ' ', GRAPH_LENGTH); graph[GRAPH_LENGTH] = '\0'; - + n_ranges = gst_query_get_n_buffering_ranges (query); for (range = 0; range < n_ranges; range++) { gint64 start, stop; @@ -106,11 +106,11 @@ static gboolean refresh_ui (CustomData *data) { } g_print ("\r"); } - + return TRUE; - + } - + int main(int argc, char *argv[]) { GstElement *pipeline; GstBus *bus; @@ -118,26 +118,26 @@ int main(int argc, char *argv[]) { GMainLoop *main_loop; CustomData data; guint flags; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Initialize our data structure */ memset (&data, 0, sizeof (data)); data.buffering_level = 100; - + /* Build the pipeline */ pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); bus = gst_element_get_bus (pipeline); - + /* Set the download flag */ g_object_get (pipeline, "flags", &flags, NULL); flags |= GST_PLAY_FLAG_DOWNLOAD; g_object_set (pipeline, "flags", flags, NULL); - + /* Uncomment this line to limit the amount of downloaded data */ /* g_object_set (pipeline, "ring-buffer-max-size", (guint64)4000000, NULL); */ - + /* Start playing */ ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { @@ -147,20 +147,20 @@ int main(int argc, char *argv[]) { } else if (ret == GST_STATE_CHANGE_NO_PREROLL) { data.is_live = TRUE; } - + main_loop = g_main_loop_new (NULL, FALSE); data.loop = main_loop; data.pipeline = pipeline; - + gst_bus_add_signal_watch (bus); g_signal_connect (bus, "message", G_CALLBACK (cb_message), &data); g_signal_connect (pipeline, "deep-notify::temp-location", G_CALLBACK (got_location), NULL); - + /* Register a function that GLib will call every second */ g_timeout_add_seconds (1, (GSourceFunc)refresh_ui, &data); - + g_main_loop_run (main_loop); - + /* Free resources */ g_main_loop_unref (main_loop); gst_object_unref (bus); diff --git a/tutorials/playback-tutorial-5.c b/examples/tutorials/playback-tutorial-5.c similarity index 98% rename from tutorials/playback-tutorial-5.c rename to examples/tutorials/playback-tutorial-5.c index 0b3f0a1..9a4d02e 100644 --- a/tutorials/playback-tutorial-5.c +++ b/examples/tutorials/playback-tutorial-5.c @@ -2,24 +2,24 @@ #include #include #include - + typedef struct _CustomData { GstElement *pipeline; GMainLoop *loop; } CustomData; - + /* Process a color balance command */ static void update_color_channel (const gchar *channel_name, gboolean increase, GstColorBalance *cb) { gdouble step; gint value; GstColorBalanceChannel *channel = NULL; const GList *channels, *l; - + /* Retrieve the list of channels and locate the requested one */ channels = gst_color_balance_list_channels (cb); for (l = channels; l != NULL; l = l->next) { GstColorBalanceChannel *tmp = (GstColorBalanceChannel *)l->data; - + if (g_strrstr (tmp->label, channel_name)) { channel = tmp; break; @@ -27,7 +27,7 @@ static void update_color_channel (const gchar *channel_name, gboolean increase, } if (!channel) return; - + /* Change the channel's value */ step = 0.1 * (channel->max_value - channel->min_value); value = gst_color_balance_get_value (cb, channel); @@ -42,11 +42,11 @@ static void update_color_channel (const gchar *channel_name, gboolean increase, } gst_color_balance_set_value (cb, channel, value); } - + /* Output the current values of all Color Balance channels */ static void print_current_values (GstElement *pipeline) { const GList *channels, *l; - + /* Output Color Balance values */ channels = gst_color_balance_list_channels (GST_COLOR_BALANCE (pipeline)); for (l = channels; l != NULL; l = l->next) { @@ -57,15 +57,15 @@ static void print_current_values (GstElement *pipeline) { } g_print ("\n"); } - + /* Process keyboard input */ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) { gchar *str = NULL; - + if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) { return TRUE; } - + switch (g_ascii_tolower (str[0])) { case 'c': update_color_channel ("CONTRAST", g_ascii_isupper (str[0]), GST_COLOR_BALANCE (data->pipeline)); @@ -85,25 +85,25 @@ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomDa default: break; } - + g_free (str); - + print_current_values (data->pipeline); - + return TRUE; } - + int main(int argc, char *argv[]) { CustomData data; GstStateChangeReturn ret; GIOChannel *io_stdin; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Initialize our data structure */ memset (&data, 0, sizeof (data)); - + /* Print usage map */ g_print ( "USAGE: Choose one of the following options, then press enter:\n" @@ -112,10 +112,10 @@ int main(int argc, char *argv[]) { " 'H' to increase hue, 'h' to decrease hue\n" " 'S' to increase saturation, 's' to decrease saturation\n" " 'Q' to quit\n"); - + /* Build the pipeline */ data.pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - + /* Add a keyboard watch so we get notified of keystrokes */ #ifdef G_OS_WIN32 io_stdin = g_io_channel_win32_new_fd (fileno (stdin)); @@ -123,7 +123,7 @@ int main(int argc, char *argv[]) { io_stdin = g_io_channel_unix_new (fileno (stdin)); #endif g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data); - + /* Start playing */ ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING); if (ret == GST_STATE_CHANGE_FAILURE) { @@ -132,11 +132,11 @@ int main(int argc, char *argv[]) { return -1; } print_current_values (data.pipeline); - + /* Create a GLib Main Loop and set it to run */ data.loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (data.loop); - + /* Free resources */ g_main_loop_unref (data.loop); g_io_channel_unref (io_stdin); diff --git a/tutorials/playback-tutorial-6.c b/examples/tutorials/playback-tutorial-6.c similarity index 97% rename from tutorials/playback-tutorial-6.c rename to examples/tutorials/playback-tutorial-6.c index cf33e16..52b4238 100644 --- a/tutorials/playback-tutorial-6.c +++ b/examples/tutorials/playback-tutorial-6.c @@ -1,23 +1,23 @@ #include - + /* playbin2 flags */ typedef enum { GST_PLAY_FLAG_VIS = (1 << 3) /* Enable rendering of visualizations when there is no video stream. */ } GstPlayFlags; - + /* Return TRUE if this is a Visualization element */ static gboolean filter_vis_features (GstPluginFeature *feature, gpointer data) { GstElementFactory *factory; - + if (!GST_IS_ELEMENT_FACTORY (feature)) return FALSE; factory = GST_ELEMENT_FACTORY (feature); if (!g_strrstr (gst_element_factory_get_klass (factory), "Visualization")) return FALSE; - + return TRUE; } - + int main(int argc, char *argv[]) { GstElement *pipeline, *vis_plugin; GstBus *bus; @@ -25,59 +25,59 @@ int main(int argc, char *argv[]) { GList *list, *walk; GstElementFactory *selected_factory = NULL; guint flags; - + /* Initialize GStreamer */ gst_init (&argc, &argv); - + /* Get a list of all visualization plugins */ list = gst_registry_feature_filter (gst_registry_get (), filter_vis_features, FALSE, NULL); - + /* Print their names */ g_print("Available visualization plugins:\n"); for (walk = list; walk != NULL; walk = g_list_next (walk)) { const gchar *name; GstElementFactory *factory; - + factory = GST_ELEMENT_FACTORY (walk->data); name = gst_element_factory_get_longname (factory); g_print(" %s\n", name); - + if (selected_factory == NULL || g_str_has_prefix (name, "GOOM")) { selected_factory = factory; } } - + /* Don't use the factory if it's still empty */ /* e.g. no visualization plugins found */ if (!selected_factory) { g_print ("No visualization plugins found!\n"); return -1; } - + /* We have now selected a factory for the visualization element */ g_print ("Selected '%s'\n", gst_element_factory_get_longname (selected_factory)); vis_plugin = gst_element_factory_create (selected_factory, NULL); if (!vis_plugin) return -1; - + /* Build the pipeline */ pipeline = gst_parse_launch ("playbin uri=http://radio.hbr1.com:19800/ambient.ogg", NULL); - + /* Set the visualization flag */ g_object_get (pipeline, "flags", &flags, NULL); flags |= GST_PLAY_FLAG_VIS; g_object_set (pipeline, "flags", flags, NULL); - + /* set vis plugin for playbin2 */ g_object_set (pipeline, "vis-plugin", vis_plugin, NULL); - + /* Start playing */ gst_element_set_state (pipeline, GST_STATE_PLAYING); - + /* Wait until error or EOS */ bus = gst_element_get_bus (pipeline); msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - + /* Free resources */ if (msg != NULL) gst_message_unref (msg); diff --git a/tutorials/playback-tutorial-7.c b/examples/tutorials/playback-tutorial-7.c similarity index 95% rename from tutorials/playback-tutorial-7.c rename to examples/tutorials/playback-tutorial-7.c index 4bdc66b..9c500de 100644 --- a/tutorials/playback-tutorial-7.c +++ b/examples/tutorials/playback-tutorial-7.c @@ -1,55 +1,55 @@ -#include - -int main(int argc, char *argv[]) { - GstElement *pipeline, *bin, *equalizer, *convert, *sink; - GstPad *pad, *ghost_pad; - GstBus *bus; - GstMessage *msg; - - /* Initialize GStreamer */ - gst_init (&argc, &argv); - - /* Build the pipeline */ - pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); - - /* Create the elements inside the sink bin */ - equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer"); - convert = gst_element_factory_make ("audioconvert", "convert"); - sink = gst_element_factory_make ("autoaudiosink", "audio_sink"); - if (!equalizer || !convert || !sink) { - g_printerr ("Not all elements could be created.\n"); - return -1; - } - - /* Create the sink bin, add the elements and link them */ - bin = gst_bin_new ("audio_sink_bin"); - gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL); - gst_element_link_many (equalizer, convert, sink, NULL); - pad = gst_element_get_static_pad (equalizer, "sink"); - ghost_pad = gst_ghost_pad_new ("sink", pad); - gst_pad_set_active (ghost_pad, TRUE); - gst_element_add_pad (bin, ghost_pad); - gst_object_unref (pad); - - /* Configure the equalizer */ - g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL); - g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL); - - /* Set playbin2's audio sink to be our sink bin */ - g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL); - - /* Start playing */ - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - /* Wait until error or EOS */ - bus = gst_element_get_bus (pipeline); - msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); - - /* Free resources */ - if (msg != NULL) - gst_message_unref (msg); - gst_object_unref (bus); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - return 0; -} +#include + +int main(int argc, char *argv[]) { + GstElement *pipeline, *bin, *equalizer, *convert, *sink; + GstPad *pad, *ghost_pad; + GstBus *bus; + GstMessage *msg; + + /* Initialize GStreamer */ + gst_init (&argc, &argv); + + /* Build the pipeline */ + pipeline = gst_parse_launch ("playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL); + + /* Create the elements inside the sink bin */ + equalizer = gst_element_factory_make ("equalizer-3bands", "equalizer"); + convert = gst_element_factory_make ("audioconvert", "convert"); + sink = gst_element_factory_make ("autoaudiosink", "audio_sink"); + if (!equalizer || !convert || !sink) { + g_printerr ("Not all elements could be created.\n"); + return -1; + } + + /* Create the sink bin, add the elements and link them */ + bin = gst_bin_new ("audio_sink_bin"); + gst_bin_add_many (GST_BIN (bin), equalizer, convert, sink, NULL); + gst_element_link_many (equalizer, convert, sink, NULL); + pad = gst_element_get_static_pad (equalizer, "sink"); + ghost_pad = gst_ghost_pad_new ("sink", pad); + gst_pad_set_active (ghost_pad, TRUE); + gst_element_add_pad (bin, ghost_pad); + gst_object_unref (pad); + + /* Configure the equalizer */ + g_object_set (G_OBJECT (equalizer), "band1", (gdouble)-24.0, NULL); + g_object_set (G_OBJECT (equalizer), "band2", (gdouble)-24.0, NULL); + + /* Set playbin2's audio sink to be our sink bin */ + g_object_set (GST_OBJECT (pipeline), "audio-sink", bin, NULL); + + /* Start playing */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* Wait until error or EOS */ + bus = gst_element_get_bus (pipeline); + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); + + /* Free resources */ + if (msg != NULL) + gst_message_unref (msg); + gst_object_unref (bus); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return 0; +} diff --git a/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj b/examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj index 67fd093..da19586 100644 --- a/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters index b5b0063..4f6a2f9 100644 --- a/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-1/basic-tutorial-1.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj b/examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj index 477166f..aeb6eb1 100644 --- a/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {A2E63C29-3375-4930-B7D3-2F23EC824EAF} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {A2E63C29-3375-4930-B7D3-2F23EC824EAF} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters index 3f66ae1..d89ecfc 100644 --- a/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-12/basic-tutorial-12.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj b/examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj index 4c8f40f..9e30bdf 100644 --- a/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {6D962544-E7A2-450B-998B-6D09B17ACCB3} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {6D962544-E7A2-450B-998B-6D09B17ACCB3} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters index 910fa05..725fd8c 100644 --- a/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-13/basic-tutorial-13.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj b/examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj index 3e5b9cd..776482f 100644 --- a/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj @@ -1,100 +1,100 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - false - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + false + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters index 790763f..c912492 100644 --- a/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-15/basic-tutorial-15.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj b/examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj index fded79d..b410d41 100644 --- a/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters index 20de244..e535bca 100644 --- a/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-2/basic-tutorial-2.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj b/examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj index 6d6d88f..7bebde3 100644 --- a/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {48361596-FE9B-4CC8-B846-B2897550E3A0} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {48361596-FE9B-4CC8-B846-B2897550E3A0} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters index db211db..fc0a854 100644 --- a/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-3/basic-tutorial-3.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj b/examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj index ff4b549..baabec7 100644 --- a/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {38771206-5047-4FE6-B0F8-E36C2C44EA3F} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {38771206-5047-4FE6-B0F8-E36C2C44EA3F} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters index 42706ff..c40d0e8 100644 --- a/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-4/basic-tutorial-4.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj b/examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj index 5204272..7c75501 100644 --- a/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj @@ -1,99 +1,99 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters index a4a46c3..082ba8a 100644 --- a/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-5/basic-tutorial-5.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj b/examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj index b3763ae..656a885 100644 --- a/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {22CBF273-BFBC-41AB-842C-5E56045C1220} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {22CBF273-BFBC-41AB-842C-5E56045C1220} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters index 97b4a54..19875e0 100644 --- a/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-6/basic-tutorial-6.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj b/examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj index 18442b0..cd406ae 100644 --- a/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {16607817-1262-46A5-8FA2-5C5865189FE2} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {16607817-1262-46A5-8FA2-5C5865189FE2} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters index e2bbe80..c986e2b 100644 --- a/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-7/basic-tutorial-7.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj b/examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj index 163e31d..e200e66 100644 --- a/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {7D5B2500-D176-45D5-AA39-BC70C6A58D59} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {7D5B2500-D176-45D5-AA39-BC70C6A58D59} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters index e14f0f5..961fb3b 100644 --- a/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-8/basic-tutorial-8.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj b/examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj similarity index 98% rename from tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj rename to examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj index 712187d..84b6e90 100644 --- a/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj +++ b/examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj @@ -1,97 +1,97 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {7B61F2C6-5202-48B7-8589-164F81BC636C} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {7B61F2C6-5202-48B7-8589-164F81BC636C} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters b/examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters similarity index 93% rename from tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters rename to examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters index 965f49c..c50d5f5 100644 --- a/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters +++ b/examples/tutorials/vs2010/basic-tutorial-9/basic-tutorial-9.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj b/examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj index c0efc33..48340a5 100644 --- a/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters index 98ab89a..2883282 100644 --- a/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-1/playback-tutorial-1.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj b/examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj index 68d5167..c68aac9 100644 --- a/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {9AC36197-6B43-49D2-B747-75AA06550637} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {9AC36197-6B43-49D2-B747-75AA06550637} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters index 92690d5..4ccfb1c 100644 --- a/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-2/playback-tutorial-2.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj b/examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj index cb664f2..6e0840f 100644 --- a/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {B84F4F87-E804-456C-874E-AC76E0116268} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {B84F4F87-E804-456C-874E-AC76E0116268} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters index 97cf279..cab5df1 100644 --- a/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-3/playback-tutorial-3.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj b/examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj index 4964c26..d7fe69a 100644 --- a/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {0342A79A-3522-416B-A4F8-58F5664B8415} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {0342A79A-3522-416B-A4F8-58F5664B8415} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters index 9e1c365..70f25d7 100644 --- a/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-4/playback-tutorial-4.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj b/examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj index bbad658..0307b97 100644 --- a/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj @@ -1,97 +1,97 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {57F94395-E9A1-430E-AF28-165FD9BE0872} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {57F94395-E9A1-430E-AF28-165FD9BE0872} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters index d11ad27..652c3ba 100644 --- a/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-5/playback-tutorial-5.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj b/examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj index 76b178b..106228c 100644 --- a/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters index 44ffbcd..1a71af3 100644 --- a/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-6/playback-tutorial-6.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj b/examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj similarity index 98% rename from tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj rename to examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj index f6c7756..794d2ab 100644 --- a/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj +++ b/examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj @@ -1,95 +1,95 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - Win32Proj - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A} - v4.0 - - - - Application - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - true - - - false - - - - - - Level3 - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - true - %(AdditionalDependencies) - %(AdditionalLibraryDirectories) - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - - - Console - false - true - - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + Win32Proj + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A} + v4.0 + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + true + %(AdditionalDependencies) + %(AdditionalLibraryDirectories) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + + + Console + false + true + + + + + + diff --git a/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters b/examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters similarity index 93% rename from tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters rename to examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters index 46528cc..2b3ab8e 100644 --- a/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters +++ b/examples/tutorials/vs2010/playback-tutorial-7/playback-tutorial-7.vcxproj.filters @@ -1,6 +1,6 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tutorials/vs2010/tutorials.sln b/examples/tutorials/vs2010/tutorials.sln similarity index 98% rename from tutorials/vs2010/tutorials.sln rename to examples/tutorials/vs2010/tutorials.sln index b755671..2e04060 100644 --- a/tutorials/vs2010/tutorials.sln +++ b/examples/tutorials/vs2010/tutorials.sln @@ -1,206 +1,206 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual C++ Express 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-1", "basic-tutorial-1\basic-tutorial-1.vcxproj", "{63AEFB51-5FB8-409B-BDF3-893A23D28BF3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-2", "basic-tutorial-2\basic-tutorial-2.vcxproj", "{4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-3", "basic-tutorial-3\basic-tutorial-3.vcxproj", "{48361596-FE9B-4CC8-B846-B2897550E3A0}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-4", "basic-tutorial-4\basic-tutorial-4.vcxproj", "{38771206-5047-4FE6-B0F8-E36C2C44EA3F}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-5", "basic-tutorial-5\basic-tutorial-5.vcxproj", "{71882E71-E5D8-47BE-A8FF-35F99B78A5A6}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-6", "basic-tutorial-6\basic-tutorial-6.vcxproj", "{22CBF273-BFBC-41AB-842C-5E56045C1220}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-7", "basic-tutorial-7\basic-tutorial-7.vcxproj", "{16607817-1262-46A5-8FA2-5C5865189FE2}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-8", "basic-tutorial-8\basic-tutorial-8.vcxproj", "{7D5B2500-D176-45D5-AA39-BC70C6A58D59}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-1", "playback-tutorial-1\playback-tutorial-1.vcxproj", "{EE66402B-FA3A-473F-ADC6-484B25B4B1DB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-2", "playback-tutorial-2\playback-tutorial-2.vcxproj", "{9AC36197-6B43-49D2-B747-75AA06550637}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-9", "basic-tutorial-9\basic-tutorial-9.vcxproj", "{7B61F2C6-5202-48B7-8589-164F81BC636C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-12", "basic-tutorial-12\basic-tutorial-12.vcxproj", "{A2E63C29-3375-4930-B7D3-2F23EC824EAF}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-4", "playback-tutorial-4\playback-tutorial-4.vcxproj", "{0342A79A-3522-416B-A4F8-58F5664B8415}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-3", "playback-tutorial-3\playback-tutorial-3.vcxproj", "{B84F4F87-E804-456C-874E-AC76E0116268}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-5", "playback-tutorial-5\playback-tutorial-5.vcxproj", "{57F94395-E9A1-430E-AF28-165FD9BE0872}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-6", "playback-tutorial-6\playback-tutorial-6.vcxproj", "{D6293AFD-41DA-44B6-AE57-F1EEE74338AC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-7", "playback-tutorial-7\playback-tutorial-7.vcxproj", "{9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-13", "basic-tutorial-13\basic-tutorial-13.vcxproj", "{6D962544-E7A2-450B-998B-6D09B17ACCB3}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-15", "basic-tutorial-15\basic-tutorial-15.vcxproj", "{94A762CB-2856-4CFF-BF1A-DB44882D4BD5}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|Win32.ActiveCfg = Debug|Win32 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|Win32.Build.0 = Debug|Win32 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|x64.ActiveCfg = Debug|x64 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|x64.Build.0 = Debug|x64 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|Win32.ActiveCfg = Release|Win32 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|Win32.Build.0 = Release|Win32 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|x64.ActiveCfg = Release|x64 - {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|x64.Build.0 = Release|x64 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|Win32.ActiveCfg = Debug|Win32 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|Win32.Build.0 = Debug|Win32 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|x64.ActiveCfg = Debug|x64 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|x64.Build.0 = Debug|x64 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|Win32.ActiveCfg = Release|Win32 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|Win32.Build.0 = Release|Win32 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|x64.ActiveCfg = Release|x64 - {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|x64.Build.0 = Release|x64 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|Win32.ActiveCfg = Debug|Win32 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|Win32.Build.0 = Debug|Win32 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|x64.ActiveCfg = Debug|x64 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|x64.Build.0 = Debug|x64 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|Win32.ActiveCfg = Release|Win32 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|Win32.Build.0 = Release|Win32 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|x64.ActiveCfg = Release|x64 - {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|x64.Build.0 = Release|x64 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|Win32.ActiveCfg = Debug|Win32 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|Win32.Build.0 = Debug|Win32 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|x64.ActiveCfg = Debug|x64 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|x64.Build.0 = Debug|x64 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|Win32.ActiveCfg = Release|Win32 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|Win32.Build.0 = Release|Win32 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|x64.ActiveCfg = Release|x64 - {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|x64.Build.0 = Release|x64 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|Win32.ActiveCfg = Debug|Win32 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|Win32.Build.0 = Debug|Win32 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|x64.ActiveCfg = Debug|x64 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|x64.Build.0 = Debug|x64 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|Win32.ActiveCfg = Release|Win32 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|Win32.Build.0 = Release|Win32 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|x64.ActiveCfg = Release|x64 - {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|x64.Build.0 = Release|x64 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|Win32.ActiveCfg = Debug|Win32 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|Win32.Build.0 = Debug|Win32 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|x64.ActiveCfg = Debug|x64 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|x64.Build.0 = Debug|x64 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|Win32.ActiveCfg = Release|Win32 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|Win32.Build.0 = Release|Win32 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|x64.ActiveCfg = Release|x64 - {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|x64.Build.0 = Release|x64 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|Win32.ActiveCfg = Debug|Win32 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|Win32.Build.0 = Debug|Win32 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|x64.ActiveCfg = Debug|x64 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|x64.Build.0 = Debug|x64 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|Win32.ActiveCfg = Release|Win32 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|Win32.Build.0 = Release|Win32 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|x64.ActiveCfg = Release|x64 - {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|x64.Build.0 = Release|x64 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|Win32.ActiveCfg = Debug|Win32 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|Win32.Build.0 = Debug|Win32 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|x64.ActiveCfg = Debug|x64 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|x64.Build.0 = Debug|x64 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|Win32.ActiveCfg = Release|Win32 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|Win32.Build.0 = Release|Win32 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|x64.ActiveCfg = Release|x64 - {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|x64.Build.0 = Release|x64 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|Win32.ActiveCfg = Debug|Win32 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|Win32.Build.0 = Debug|Win32 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|x64.ActiveCfg = Debug|x64 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|x64.Build.0 = Debug|x64 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|Win32.ActiveCfg = Release|Win32 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|Win32.Build.0 = Release|Win32 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|x64.ActiveCfg = Release|x64 - {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|x64.Build.0 = Release|x64 - {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|Win32.ActiveCfg = Debug|Win32 - {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|Win32.Build.0 = Debug|Win32 - {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|x64.ActiveCfg = Debug|x64 - {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|x64.Build.0 = Debug|x64 - {9AC36197-6B43-49D2-B747-75AA06550637}.Release|Win32.ActiveCfg = Release|Win32 - {9AC36197-6B43-49D2-B747-75AA06550637}.Release|Win32.Build.0 = Release|Win32 - {9AC36197-6B43-49D2-B747-75AA06550637}.Release|x64.ActiveCfg = Release|x64 - {9AC36197-6B43-49D2-B747-75AA06550637}.Release|x64.Build.0 = Release|x64 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|Win32.ActiveCfg = Debug|Win32 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|Win32.Build.0 = Debug|Win32 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|x64.ActiveCfg = Debug|x64 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|x64.Build.0 = Debug|x64 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|Win32.ActiveCfg = Release|Win32 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|Win32.Build.0 = Release|Win32 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|x64.ActiveCfg = Release|x64 - {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|x64.Build.0 = Release|x64 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|Win32.ActiveCfg = Debug|Win32 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|Win32.Build.0 = Debug|Win32 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|x64.ActiveCfg = Debug|x64 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|x64.Build.0 = Debug|x64 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|Win32.ActiveCfg = Release|Win32 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|Win32.Build.0 = Release|Win32 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|x64.ActiveCfg = Release|x64 - {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|x64.Build.0 = Release|x64 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|Win32.ActiveCfg = Debug|Win32 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|Win32.Build.0 = Debug|Win32 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|x64.ActiveCfg = Debug|x64 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|x64.Build.0 = Debug|x64 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|Win32.ActiveCfg = Release|Win32 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|Win32.Build.0 = Release|Win32 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|x64.ActiveCfg = Release|x64 - {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|x64.Build.0 = Release|x64 - {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|Win32.ActiveCfg = Debug|Win32 - {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|Win32.Build.0 = Debug|Win32 - {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|x64.ActiveCfg = Debug|x64 - {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|x64.Build.0 = Debug|x64 - {B84F4F87-E804-456C-874E-AC76E0116268}.Release|Win32.ActiveCfg = Release|Win32 - {B84F4F87-E804-456C-874E-AC76E0116268}.Release|Win32.Build.0 = Release|Win32 - {B84F4F87-E804-456C-874E-AC76E0116268}.Release|x64.ActiveCfg = Release|x64 - {B84F4F87-E804-456C-874E-AC76E0116268}.Release|x64.Build.0 = Release|x64 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|Win32.ActiveCfg = Debug|Win32 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|Win32.Build.0 = Debug|Win32 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|x64.ActiveCfg = Debug|x64 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|x64.Build.0 = Debug|x64 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|Win32.ActiveCfg = Release|Win32 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|Win32.Build.0 = Release|Win32 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|x64.ActiveCfg = Release|x64 - {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|x64.Build.0 = Release|x64 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|Win32.ActiveCfg = Debug|Win32 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|Win32.Build.0 = Debug|Win32 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|x64.ActiveCfg = Debug|x64 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|x64.Build.0 = Debug|x64 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|Win32.ActiveCfg = Release|Win32 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|Win32.Build.0 = Release|Win32 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|x64.ActiveCfg = Release|x64 - {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|x64.Build.0 = Release|x64 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|Win32.ActiveCfg = Debug|Win32 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|Win32.Build.0 = Debug|Win32 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|x64.ActiveCfg = Debug|x64 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|x64.Build.0 = Debug|x64 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|Win32.ActiveCfg = Release|Win32 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|Win32.Build.0 = Release|Win32 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|x64.ActiveCfg = Release|x64 - {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|x64.Build.0 = Release|x64 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|Win32.ActiveCfg = Debug|Win32 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|Win32.Build.0 = Debug|Win32 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|x64.ActiveCfg = Debug|x64 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|x64.Build.0 = Debug|x64 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|Win32.ActiveCfg = Release|Win32 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|Win32.Build.0 = Release|Win32 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.ActiveCfg = Release|x64 - {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.Build.0 = Release|x64 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.ActiveCfg = Debug|Win32 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.Build.0 = Debug|Win32 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.ActiveCfg = Debug|x64 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.Build.0 = Debug|x64 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.ActiveCfg = Release|Win32 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.Build.0 = Release|Win32 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.ActiveCfg = Release|x64 - {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-1", "basic-tutorial-1\basic-tutorial-1.vcxproj", "{63AEFB51-5FB8-409B-BDF3-893A23D28BF3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-2", "basic-tutorial-2\basic-tutorial-2.vcxproj", "{4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-3", "basic-tutorial-3\basic-tutorial-3.vcxproj", "{48361596-FE9B-4CC8-B846-B2897550E3A0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-4", "basic-tutorial-4\basic-tutorial-4.vcxproj", "{38771206-5047-4FE6-B0F8-E36C2C44EA3F}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-5", "basic-tutorial-5\basic-tutorial-5.vcxproj", "{71882E71-E5D8-47BE-A8FF-35F99B78A5A6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-6", "basic-tutorial-6\basic-tutorial-6.vcxproj", "{22CBF273-BFBC-41AB-842C-5E56045C1220}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-7", "basic-tutorial-7\basic-tutorial-7.vcxproj", "{16607817-1262-46A5-8FA2-5C5865189FE2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-8", "basic-tutorial-8\basic-tutorial-8.vcxproj", "{7D5B2500-D176-45D5-AA39-BC70C6A58D59}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-1", "playback-tutorial-1\playback-tutorial-1.vcxproj", "{EE66402B-FA3A-473F-ADC6-484B25B4B1DB}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-2", "playback-tutorial-2\playback-tutorial-2.vcxproj", "{9AC36197-6B43-49D2-B747-75AA06550637}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-9", "basic-tutorial-9\basic-tutorial-9.vcxproj", "{7B61F2C6-5202-48B7-8589-164F81BC636C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-12", "basic-tutorial-12\basic-tutorial-12.vcxproj", "{A2E63C29-3375-4930-B7D3-2F23EC824EAF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-4", "playback-tutorial-4\playback-tutorial-4.vcxproj", "{0342A79A-3522-416B-A4F8-58F5664B8415}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-3", "playback-tutorial-3\playback-tutorial-3.vcxproj", "{B84F4F87-E804-456C-874E-AC76E0116268}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-5", "playback-tutorial-5\playback-tutorial-5.vcxproj", "{57F94395-E9A1-430E-AF28-165FD9BE0872}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-6", "playback-tutorial-6\playback-tutorial-6.vcxproj", "{D6293AFD-41DA-44B6-AE57-F1EEE74338AC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "playback-tutorial-7", "playback-tutorial-7\playback-tutorial-7.vcxproj", "{9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-13", "basic-tutorial-13\basic-tutorial-13.vcxproj", "{6D962544-E7A2-450B-998B-6D09B17ACCB3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-tutorial-15", "basic-tutorial-15\basic-tutorial-15.vcxproj", "{94A762CB-2856-4CFF-BF1A-DB44882D4BD5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|Win32.ActiveCfg = Debug|Win32 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|Win32.Build.0 = Debug|Win32 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|x64.ActiveCfg = Debug|x64 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Debug|x64.Build.0 = Debug|x64 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|Win32.ActiveCfg = Release|Win32 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|Win32.Build.0 = Release|Win32 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|x64.ActiveCfg = Release|x64 + {63AEFB51-5FB8-409B-BDF3-893A23D28BF3}.Release|x64.Build.0 = Release|x64 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|Win32.ActiveCfg = Debug|Win32 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|Win32.Build.0 = Debug|Win32 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|x64.ActiveCfg = Debug|x64 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Debug|x64.Build.0 = Debug|x64 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|Win32.ActiveCfg = Release|Win32 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|Win32.Build.0 = Release|Win32 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|x64.ActiveCfg = Release|x64 + {4FA695D0-7A7B-4ED6-BA2B-B14997D8231E}.Release|x64.Build.0 = Release|x64 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|Win32.ActiveCfg = Debug|Win32 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|Win32.Build.0 = Debug|Win32 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|x64.ActiveCfg = Debug|x64 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Debug|x64.Build.0 = Debug|x64 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|Win32.ActiveCfg = Release|Win32 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|Win32.Build.0 = Release|Win32 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|x64.ActiveCfg = Release|x64 + {48361596-FE9B-4CC8-B846-B2897550E3A0}.Release|x64.Build.0 = Release|x64 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|Win32.ActiveCfg = Debug|Win32 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|Win32.Build.0 = Debug|Win32 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|x64.ActiveCfg = Debug|x64 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Debug|x64.Build.0 = Debug|x64 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|Win32.ActiveCfg = Release|Win32 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|Win32.Build.0 = Release|Win32 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|x64.ActiveCfg = Release|x64 + {38771206-5047-4FE6-B0F8-E36C2C44EA3F}.Release|x64.Build.0 = Release|x64 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|Win32.ActiveCfg = Debug|Win32 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|Win32.Build.0 = Debug|Win32 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|x64.ActiveCfg = Debug|x64 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Debug|x64.Build.0 = Debug|x64 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|Win32.ActiveCfg = Release|Win32 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|Win32.Build.0 = Release|Win32 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|x64.ActiveCfg = Release|x64 + {71882E71-E5D8-47BE-A8FF-35F99B78A5A6}.Release|x64.Build.0 = Release|x64 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|Win32.ActiveCfg = Debug|Win32 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|Win32.Build.0 = Debug|Win32 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|x64.ActiveCfg = Debug|x64 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Debug|x64.Build.0 = Debug|x64 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|Win32.ActiveCfg = Release|Win32 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|Win32.Build.0 = Release|Win32 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|x64.ActiveCfg = Release|x64 + {22CBF273-BFBC-41AB-842C-5E56045C1220}.Release|x64.Build.0 = Release|x64 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|Win32.ActiveCfg = Debug|Win32 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|Win32.Build.0 = Debug|Win32 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|x64.ActiveCfg = Debug|x64 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Debug|x64.Build.0 = Debug|x64 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|Win32.ActiveCfg = Release|Win32 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|Win32.Build.0 = Release|Win32 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|x64.ActiveCfg = Release|x64 + {16607817-1262-46A5-8FA2-5C5865189FE2}.Release|x64.Build.0 = Release|x64 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|Win32.ActiveCfg = Debug|Win32 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|Win32.Build.0 = Debug|Win32 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|x64.ActiveCfg = Debug|x64 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Debug|x64.Build.0 = Debug|x64 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|Win32.ActiveCfg = Release|Win32 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|Win32.Build.0 = Release|Win32 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|x64.ActiveCfg = Release|x64 + {7D5B2500-D176-45D5-AA39-BC70C6A58D59}.Release|x64.Build.0 = Release|x64 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|Win32.ActiveCfg = Debug|Win32 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|Win32.Build.0 = Debug|Win32 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|x64.ActiveCfg = Debug|x64 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Debug|x64.Build.0 = Debug|x64 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|Win32.ActiveCfg = Release|Win32 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|Win32.Build.0 = Release|Win32 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|x64.ActiveCfg = Release|x64 + {EE66402B-FA3A-473F-ADC6-484B25B4B1DB}.Release|x64.Build.0 = Release|x64 + {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|Win32.ActiveCfg = Debug|Win32 + {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|Win32.Build.0 = Debug|Win32 + {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|x64.ActiveCfg = Debug|x64 + {9AC36197-6B43-49D2-B747-75AA06550637}.Debug|x64.Build.0 = Debug|x64 + {9AC36197-6B43-49D2-B747-75AA06550637}.Release|Win32.ActiveCfg = Release|Win32 + {9AC36197-6B43-49D2-B747-75AA06550637}.Release|Win32.Build.0 = Release|Win32 + {9AC36197-6B43-49D2-B747-75AA06550637}.Release|x64.ActiveCfg = Release|x64 + {9AC36197-6B43-49D2-B747-75AA06550637}.Release|x64.Build.0 = Release|x64 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|Win32.ActiveCfg = Debug|Win32 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|Win32.Build.0 = Debug|Win32 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|x64.ActiveCfg = Debug|x64 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Debug|x64.Build.0 = Debug|x64 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|Win32.ActiveCfg = Release|Win32 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|Win32.Build.0 = Release|Win32 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|x64.ActiveCfg = Release|x64 + {7B61F2C6-5202-48B7-8589-164F81BC636C}.Release|x64.Build.0 = Release|x64 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|Win32.ActiveCfg = Debug|Win32 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|Win32.Build.0 = Debug|Win32 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|x64.ActiveCfg = Debug|x64 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Debug|x64.Build.0 = Debug|x64 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|Win32.ActiveCfg = Release|Win32 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|Win32.Build.0 = Release|Win32 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|x64.ActiveCfg = Release|x64 + {A2E63C29-3375-4930-B7D3-2F23EC824EAF}.Release|x64.Build.0 = Release|x64 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|Win32.ActiveCfg = Debug|Win32 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|Win32.Build.0 = Debug|Win32 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|x64.ActiveCfg = Debug|x64 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Debug|x64.Build.0 = Debug|x64 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|Win32.ActiveCfg = Release|Win32 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|Win32.Build.0 = Release|Win32 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|x64.ActiveCfg = Release|x64 + {0342A79A-3522-416B-A4F8-58F5664B8415}.Release|x64.Build.0 = Release|x64 + {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|Win32.ActiveCfg = Debug|Win32 + {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|Win32.Build.0 = Debug|Win32 + {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|x64.ActiveCfg = Debug|x64 + {B84F4F87-E804-456C-874E-AC76E0116268}.Debug|x64.Build.0 = Debug|x64 + {B84F4F87-E804-456C-874E-AC76E0116268}.Release|Win32.ActiveCfg = Release|Win32 + {B84F4F87-E804-456C-874E-AC76E0116268}.Release|Win32.Build.0 = Release|Win32 + {B84F4F87-E804-456C-874E-AC76E0116268}.Release|x64.ActiveCfg = Release|x64 + {B84F4F87-E804-456C-874E-AC76E0116268}.Release|x64.Build.0 = Release|x64 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|Win32.ActiveCfg = Debug|Win32 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|Win32.Build.0 = Debug|Win32 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|x64.ActiveCfg = Debug|x64 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Debug|x64.Build.0 = Debug|x64 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|Win32.ActiveCfg = Release|Win32 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|Win32.Build.0 = Release|Win32 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|x64.ActiveCfg = Release|x64 + {57F94395-E9A1-430E-AF28-165FD9BE0872}.Release|x64.Build.0 = Release|x64 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|Win32.ActiveCfg = Debug|Win32 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|Win32.Build.0 = Debug|Win32 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|x64.ActiveCfg = Debug|x64 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Debug|x64.Build.0 = Debug|x64 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|Win32.ActiveCfg = Release|Win32 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|Win32.Build.0 = Release|Win32 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|x64.ActiveCfg = Release|x64 + {D6293AFD-41DA-44B6-AE57-F1EEE74338AC}.Release|x64.Build.0 = Release|x64 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|Win32.ActiveCfg = Debug|Win32 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|Win32.Build.0 = Debug|Win32 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|x64.ActiveCfg = Debug|x64 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Debug|x64.Build.0 = Debug|x64 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|Win32.ActiveCfg = Release|Win32 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|Win32.Build.0 = Release|Win32 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|x64.ActiveCfg = Release|x64 + {9C06FA1E-E571-42EA-B4AA-B91F9DA77D5A}.Release|x64.Build.0 = Release|x64 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|Win32.Build.0 = Debug|Win32 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|x64.ActiveCfg = Debug|x64 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Debug|x64.Build.0 = Debug|x64 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|Win32.ActiveCfg = Release|Win32 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|Win32.Build.0 = Release|Win32 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.ActiveCfg = Release|x64 + {6D962544-E7A2-450B-998B-6D09B17ACCB3}.Release|x64.Build.0 = Release|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.ActiveCfg = Debug|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|Win32.Build.0 = Debug|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.ActiveCfg = Debug|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Debug|x64.Build.0 = Debug|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.ActiveCfg = Release|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|Win32.Build.0 = Release|Win32 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.ActiveCfg = Release|x64 + {94A762CB-2856-4CFF-BF1A-DB44882D4BD5}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.pbxproj b/examples/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.pbxproj similarity index 100% rename from tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.pbxproj rename to examples/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.pbxproj diff --git a/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to examples/tutorials/xcode iOS/GStreamer iOS Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/tutorials/xcode iOS/Tutorial 5/AppDelegate.h b/examples/tutorials/xcode iOS/Tutorial 1/AppDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/AppDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 1/AppDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 2/AppDelegate.m b/examples/tutorials/xcode iOS/Tutorial 1/AppDelegate.m similarity index 98% rename from tutorials/xcode iOS/Tutorial 2/AppDelegate.m rename to examples/tutorials/xcode iOS/Tutorial 1/AppDelegate.m index 31ef04e..0fe9773 100644 --- a/tutorials/xcode iOS/Tutorial 2/AppDelegate.m +++ b/examples/tutorials/xcode iOS/Tutorial 1/AppDelegate.m @@ -7,7 +7,7 @@ // Override point for customization after application launch. return YES; } - + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. @@ -16,7 +16,7 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } diff --git a/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.h b/examples/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/GStreamerBackend.h rename to examples/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.h diff --git a/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m b/examples/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m rename to examples/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m index e36233b..9401217 100644 --- a/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m +++ b/examples/tutorials/xcode iOS/Tutorial 1/GStreamerBackend.m @@ -13,4 +13,3 @@ } @end - diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Contents.json b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-60@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-60@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-60@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-60@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-72@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-76@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-83.5@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-83.5@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-83.5@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon-83.5@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Icon@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/Contents.json b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Contents.json b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x-1.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x-1.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x-1.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x-1.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x.png b/examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x.png rename to examples/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Info.plist b/examples/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Tutorial 1-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch b/examples/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch rename to examples/tutorials/xcode iOS/Tutorial 1/Tutorial 1-Prefix.pch diff --git a/tutorials/xcode iOS/Tutorial 5/Ubuntu-R.ttf b/examples/tutorials/xcode iOS/Tutorial 1/Ubuntu-R.ttf similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Ubuntu-R.ttf rename to examples/tutorials/xcode iOS/Tutorial 1/Ubuntu-R.ttf diff --git a/tutorials/xcode iOS/Tutorial 1/ViewController.h b/examples/tutorials/xcode iOS/Tutorial 1/ViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/ViewController.h rename to examples/tutorials/xcode iOS/Tutorial 1/ViewController.h diff --git a/tutorials/xcode iOS/Tutorial 1/ViewController.m b/examples/tutorials/xcode iOS/Tutorial 1/ViewController.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 1/ViewController.m rename to examples/tutorials/xcode iOS/Tutorial 1/ViewController.m index 96c8b29..a57e063 100644 --- a/tutorials/xcode iOS/Tutorial 1/ViewController.m +++ b/examples/tutorials/xcode iOS/Tutorial 1/ViewController.m @@ -16,7 +16,7 @@ [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. gst_backend = [[GStreamerBackend alloc] init]; - + label.text = [NSString stringWithFormat:@"Welcome to %@!", [gst_backend getGStreamerVersion]]; } diff --git a/tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings b/examples/tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings similarity index 97% rename from tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings rename to examples/tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings index 477b28f..b92732c 100644 --- a/tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings +++ b/examples/tutorials/xcode iOS/Tutorial 1/en.lproj/InfoPlist.strings @@ -1,2 +1 @@ /* Localized versions of Info.plist keys */ - diff --git a/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPad.storyboard b/examples/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPad.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPad.storyboard rename to examples/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPad.storyboard diff --git a/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPhone.storyboard b/examples/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPhone.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPhone.storyboard rename to examples/tutorials/xcode iOS/Tutorial 1/en.lproj/MainStoryboard_iPhone.storyboard diff --git a/tutorials/xcode iOS/Tutorial 2/fonts.conf b/examples/tutorials/xcode iOS/Tutorial 1/fonts.conf similarity index 99% rename from tutorials/xcode iOS/Tutorial 2/fonts.conf rename to examples/tutorials/xcode iOS/Tutorial 1/fonts.conf index 6b780ea..e364473 100644 --- a/tutorials/xcode iOS/Tutorial 2/fonts.conf +++ b/examples/tutorials/xcode iOS/Tutorial 1/fonts.conf @@ -123,4 +123,3 @@ - diff --git a/tutorials/xcode iOS/Tutorial 1/gst_ios_init.h b/examples/tutorials/xcode iOS/Tutorial 1/gst_ios_init.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/gst_ios_init.h rename to examples/tutorials/xcode iOS/Tutorial 1/gst_ios_init.h diff --git a/tutorials/xcode iOS/Tutorial 2/gst_ios_init.m b/examples/tutorials/xcode iOS/Tutorial 1/gst_ios_init.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 2/gst_ios_init.m rename to examples/tutorials/xcode iOS/Tutorial 1/gst_ios_init.m index c2934df..8850f11 100644 --- a/tutorials/xcode iOS/Tutorial 2/gst_ios_init.m +++ b/examples/tutorials/xcode iOS/Tutorial 1/gst_ios_init.m @@ -516,19 +516,19 @@ gst_ios_init (void) NSString *tmp = NSTemporaryDirectory(); NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; - + const gchar *resources_dir = [resources UTF8String]; const gchar *tmp_dir = [tmp UTF8String]; const gchar *cache_dir = [cache UTF8String]; const gchar *docs_dir = [docs UTF8String]; gchar *ca_certificates; - + g_setenv ("TMP", tmp_dir, TRUE); g_setenv ("TEMP", tmp_dir, TRUE); g_setenv ("TMPDIR", tmp_dir, TRUE); g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE); g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE); - + g_setenv ("HOME", docs_dir, TRUE); g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE); g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE); @@ -539,7 +539,7 @@ gst_ios_init (void) ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certifcates.crt", NULL); g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE); g_free (ca_certificates); - + gst_init (NULL, NULL); #if defined(GST_IOS_PLUGIN_NLE) || defined(GST_IOS_PLUGINS_GES) diff --git a/tutorials/xcode iOS/Tutorial 5/main.m b/examples/tutorials/xcode iOS/Tutorial 1/main.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/main.m rename to examples/tutorials/xcode iOS/Tutorial 1/main.m diff --git a/tutorials/xcode iOS/Tutorial 4/AppDelegate.h b/examples/tutorials/xcode iOS/Tutorial 2/AppDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/AppDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 2/AppDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 4/AppDelegate.m b/examples/tutorials/xcode iOS/Tutorial 2/AppDelegate.m similarity index 98% rename from tutorials/xcode iOS/Tutorial 4/AppDelegate.m rename to examples/tutorials/xcode iOS/Tutorial 2/AppDelegate.m index 31ef04e..0fe9773 100644 --- a/tutorials/xcode iOS/Tutorial 4/AppDelegate.m +++ b/examples/tutorials/xcode iOS/Tutorial 2/AppDelegate.m @@ -7,7 +7,7 @@ // Override point for customization after application launch. return YES; } - + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. @@ -16,7 +16,7 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } diff --git a/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.h b/examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/GStreamerBackend.h rename to examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.h diff --git a/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m b/examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m rename to examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m index 814d15a..4a71355 100644 --- a/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m +++ b/examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackend.m @@ -85,7 +85,7 @@ static void error_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) GError *err; gchar *debug_info; gchar *message_string; - + gst_message_parse_error (msg, &err, &debug_info); message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); g_clear_error (&err); @@ -134,7 +134,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se /* Create our own GLib Main Context and make it the default one */ context = g_main_context_new (); g_main_context_push_thread_default(context); - + /* Build pipeline */ pipeline = gst_parse_launch("audiotestsrc ! audioconvert ! audioresample ! autoaudiosink", &error); if (error) { @@ -144,7 +144,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se g_free (message); return; } - + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ bus = gst_element_get_bus (pipeline); bus_source = gst_bus_create_watch (bus); @@ -154,7 +154,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, (__bridge void *)self); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, (__bridge void *)self); gst_object_unref (bus); - + /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop..."); main_loop = g_main_loop_new (context, FALSE); @@ -163,15 +163,14 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se GST_DEBUG ("Exited main loop"); g_main_loop_unref (main_loop); main_loop = NULL; - + /* Free resources */ g_main_context_pop_thread_default(context); g_main_context_unref (context); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); - + return; } @end - diff --git a/tutorials/xcode iOS/Tutorial 3/GStreamerBackendDelegate.h b/examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackendDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/GStreamerBackendDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 2/GStreamerBackendDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Contents.json b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-60@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-60@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-60@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-60@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-72@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-76@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-83.5@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-83.5@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-83.5@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon-83.5@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Icon@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/Contents.json b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Contents.json b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x-1.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x-1.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x-1.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x-1.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x.png b/examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x.png rename to examples/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Info.plist b/examples/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Tutorial 2-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch b/examples/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch rename to examples/tutorials/xcode iOS/Tutorial 2/Tutorial 2-Prefix.pch diff --git a/tutorials/xcode iOS/Tutorial 2/Tutorial2-Info.plist b/examples/tutorials/xcode iOS/Tutorial 2/Tutorial2-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Tutorial2-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 2/Tutorial2-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 4/Ubuntu-R.ttf b/examples/tutorials/xcode iOS/Tutorial 2/Ubuntu-R.ttf similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Ubuntu-R.ttf rename to examples/tutorials/xcode iOS/Tutorial 2/Ubuntu-R.ttf diff --git a/tutorials/xcode iOS/Tutorial 2/ViewController.h b/examples/tutorials/xcode iOS/Tutorial 2/ViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/ViewController.h rename to examples/tutorials/xcode iOS/Tutorial 2/ViewController.h diff --git a/tutorials/xcode iOS/Tutorial 2/ViewController.m b/examples/tutorials/xcode iOS/Tutorial 2/ViewController.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 2/ViewController.m rename to examples/tutorials/xcode iOS/Tutorial 2/ViewController.m index 512ede7..58d00c4 100644 --- a/tutorials/xcode iOS/Tutorial 2/ViewController.m +++ b/examples/tutorials/xcode iOS/Tutorial 2/ViewController.m @@ -17,7 +17,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - + play_button.enabled = FALSE; pause_button.enabled = FALSE; diff --git a/tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings b/examples/tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings similarity index 97% rename from tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings rename to examples/tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings index 477b28f..b92732c 100644 --- a/tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings +++ b/examples/tutorials/xcode iOS/Tutorial 2/en.lproj/InfoPlist.strings @@ -1,2 +1 @@ /* Localized versions of Info.plist keys */ - diff --git a/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPad.storyboard b/examples/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPad.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPad.storyboard rename to examples/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPad.storyboard diff --git a/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPhone.storyboard b/examples/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPhone.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPhone.storyboard rename to examples/tutorials/xcode iOS/Tutorial 2/en.lproj/MainStoryboard_iPhone.storyboard diff --git a/tutorials/xcode iOS/Tutorial 3/fonts.conf b/examples/tutorials/xcode iOS/Tutorial 2/fonts.conf similarity index 99% rename from tutorials/xcode iOS/Tutorial 3/fonts.conf rename to examples/tutorials/xcode iOS/Tutorial 2/fonts.conf index 6b780ea..e364473 100644 --- a/tutorials/xcode iOS/Tutorial 3/fonts.conf +++ b/examples/tutorials/xcode iOS/Tutorial 2/fonts.conf @@ -123,4 +123,3 @@ - diff --git a/tutorials/xcode iOS/Tutorial 2/gst_ios_init.h b/examples/tutorials/xcode iOS/Tutorial 2/gst_ios_init.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/gst_ios_init.h rename to examples/tutorials/xcode iOS/Tutorial 2/gst_ios_init.h diff --git a/tutorials/xcode iOS/Tutorial 1/gst_ios_init.m b/examples/tutorials/xcode iOS/Tutorial 2/gst_ios_init.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 1/gst_ios_init.m rename to examples/tutorials/xcode iOS/Tutorial 2/gst_ios_init.m index c2934df..8850f11 100644 --- a/tutorials/xcode iOS/Tutorial 1/gst_ios_init.m +++ b/examples/tutorials/xcode iOS/Tutorial 2/gst_ios_init.m @@ -516,19 +516,19 @@ gst_ios_init (void) NSString *tmp = NSTemporaryDirectory(); NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; - + const gchar *resources_dir = [resources UTF8String]; const gchar *tmp_dir = [tmp UTF8String]; const gchar *cache_dir = [cache UTF8String]; const gchar *docs_dir = [docs UTF8String]; gchar *ca_certificates; - + g_setenv ("TMP", tmp_dir, TRUE); g_setenv ("TEMP", tmp_dir, TRUE); g_setenv ("TMPDIR", tmp_dir, TRUE); g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE); g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE); - + g_setenv ("HOME", docs_dir, TRUE); g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE); g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE); @@ -539,7 +539,7 @@ gst_ios_init (void) ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certifcates.crt", NULL); g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE); g_free (ca_certificates); - + gst_init (NULL, NULL); #if defined(GST_IOS_PLUGIN_NLE) || defined(GST_IOS_PLUGINS_GES) diff --git a/tutorials/xcode iOS/Tutorial 4/main.m b/examples/tutorials/xcode iOS/Tutorial 2/main.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/main.m rename to examples/tutorials/xcode iOS/Tutorial 2/main.m diff --git a/tutorials/xcode iOS/Tutorial 3/AppDelegate.h b/examples/tutorials/xcode iOS/Tutorial 3/AppDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/AppDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 3/AppDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 3/AppDelegate.m b/examples/tutorials/xcode iOS/Tutorial 3/AppDelegate.m similarity index 98% rename from tutorials/xcode iOS/Tutorial 3/AppDelegate.m rename to examples/tutorials/xcode iOS/Tutorial 3/AppDelegate.m index 31ef04e..0fe9773 100644 --- a/tutorials/xcode iOS/Tutorial 3/AppDelegate.m +++ b/examples/tutorials/xcode iOS/Tutorial 3/AppDelegate.m @@ -7,7 +7,7 @@ // Override point for customization after application launch. return YES; } - + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. @@ -16,7 +16,7 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } diff --git a/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h b/examples/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h similarity index 99% rename from tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h rename to examples/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h index ac4e798..e7b80e5 100644 --- a/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h +++ b/examples/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.h @@ -8,4 +8,3 @@ } @end - diff --git a/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.m b/examples/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/EaglUIVIew.m rename to examples/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.m diff --git a/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.h b/examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/GStreamerBackend.h rename to examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.h diff --git a/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m b/examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m rename to examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m index 0942bb0..17d314b 100644 --- a/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m +++ b/examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackend.m @@ -89,7 +89,7 @@ static void error_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) GError *err; gchar *debug_info; gchar *message_string; - + gst_message_parse_error (msg, &err, &debug_info); message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); g_clear_error (&err); @@ -138,7 +138,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se /* Create our own GLib Main Context and make it the default one */ context = g_main_context_new (); g_main_context_push_thread_default(context); - + /* Build pipeline */ pipeline = gst_parse_launch("videotestsrc ! warptv ! videoconvert ! autovideosink", &error); if (error) { @@ -151,7 +151,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se /* Set the pipeline to READY, so it can already accept a window handle */ gst_element_set_state(pipeline, GST_STATE_READY); - + video_sink = gst_bin_get_by_interface(GST_BIN(pipeline), GST_TYPE_VIDEO_OVERLAY); if (!video_sink) { GST_ERROR ("Could not retrieve video sink"); @@ -168,7 +168,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, (__bridge void *)self); g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, (__bridge void *)self); gst_object_unref (bus); - + /* Create a GLib Main Loop and set it to run */ GST_DEBUG ("Entering main loop..."); main_loop = g_main_loop_new (context, FALSE); @@ -177,15 +177,14 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se GST_DEBUG ("Exited main loop"); g_main_loop_unref (main_loop); main_loop = NULL; - + /* Free resources */ g_main_context_pop_thread_default(context); g_main_context_unref (context); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); - + return; } @end - diff --git a/tutorials/xcode iOS/Tutorial 2/GStreamerBackendDelegate.h b/examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackendDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/GStreamerBackendDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 3/GStreamerBackendDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Contents.json b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-60@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-60@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-60@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-60@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-72@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-76@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-83.5@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-83.5@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-83.5@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon-83.5@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/AppIcon-3.appiconset/Icon@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/Contents.json b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Contents.json b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x-1.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x-1.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x-1.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x-1.png diff --git a/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x.png b/examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x.png rename to examples/tutorials/xcode iOS/Tutorial 3/Images-3.xcassets/LaunchImage-3.launchimage/Default-568h@2x.png diff --git a/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Info.plist b/examples/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Tutorial 3-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch b/examples/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch rename to examples/tutorials/xcode iOS/Tutorial 3/Tutorial 3-Prefix.pch diff --git a/tutorials/xcode iOS/Tutorial 3/Ubuntu-R.ttf b/examples/tutorials/xcode iOS/Tutorial 3/Ubuntu-R.ttf similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/Ubuntu-R.ttf rename to examples/tutorials/xcode iOS/Tutorial 3/Ubuntu-R.ttf diff --git a/tutorials/xcode iOS/Tutorial 3/ViewController.h b/examples/tutorials/xcode iOS/Tutorial 3/ViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/ViewController.h rename to examples/tutorials/xcode iOS/Tutorial 3/ViewController.h diff --git a/tutorials/xcode iOS/Tutorial 3/ViewController.m b/examples/tutorials/xcode iOS/Tutorial 3/ViewController.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 3/ViewController.m rename to examples/tutorials/xcode iOS/Tutorial 3/ViewController.m index 93eae20..bd9eb56 100644 --- a/tutorials/xcode iOS/Tutorial 3/ViewController.m +++ b/examples/tutorials/xcode iOS/Tutorial 3/ViewController.m @@ -19,10 +19,10 @@ - (void)viewDidLoad { [super viewDidLoad]; - + play_button.enabled = FALSE; pause_button.enabled = FALSE; - + /* Make these constant for now, later tutorials will change them */ media_width = 320; media_height = 240; diff --git a/tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings b/examples/tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings similarity index 97% rename from tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings rename to examples/tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings index 477b28f..b92732c 100644 --- a/tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings +++ b/examples/tutorials/xcode iOS/Tutorial 3/en.lproj/InfoPlist.strings @@ -1,2 +1 @@ /* Localized versions of Info.plist keys */ - diff --git a/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPad.storyboard b/examples/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPad.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPad.storyboard rename to examples/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPad.storyboard diff --git a/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPhone.storyboard b/examples/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPhone.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPhone.storyboard rename to examples/tutorials/xcode iOS/Tutorial 3/en.lproj/MainStoryboard_iPhone.storyboard diff --git a/tutorials/xcode iOS/Tutorial 1/fonts.conf b/examples/tutorials/xcode iOS/Tutorial 3/fonts.conf similarity index 99% rename from tutorials/xcode iOS/Tutorial 1/fonts.conf rename to examples/tutorials/xcode iOS/Tutorial 3/fonts.conf index 6b780ea..e364473 100644 --- a/tutorials/xcode iOS/Tutorial 1/fonts.conf +++ b/examples/tutorials/xcode iOS/Tutorial 3/fonts.conf @@ -123,4 +123,3 @@ - diff --git a/tutorials/xcode iOS/Tutorial 3/gst_ios_init.h b/examples/tutorials/xcode iOS/Tutorial 3/gst_ios_init.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/gst_ios_init.h rename to examples/tutorials/xcode iOS/Tutorial 3/gst_ios_init.h diff --git a/tutorials/xcode iOS/Tutorial 3/gst_ios_init.m b/examples/tutorials/xcode iOS/Tutorial 3/gst_ios_init.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 3/gst_ios_init.m rename to examples/tutorials/xcode iOS/Tutorial 3/gst_ios_init.m index c2934df..8850f11 100644 --- a/tutorials/xcode iOS/Tutorial 3/gst_ios_init.m +++ b/examples/tutorials/xcode iOS/Tutorial 3/gst_ios_init.m @@ -516,19 +516,19 @@ gst_ios_init (void) NSString *tmp = NSTemporaryDirectory(); NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; - + const gchar *resources_dir = [resources UTF8String]; const gchar *tmp_dir = [tmp UTF8String]; const gchar *cache_dir = [cache UTF8String]; const gchar *docs_dir = [docs UTF8String]; gchar *ca_certificates; - + g_setenv ("TMP", tmp_dir, TRUE); g_setenv ("TEMP", tmp_dir, TRUE); g_setenv ("TMPDIR", tmp_dir, TRUE); g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE); g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE); - + g_setenv ("HOME", docs_dir, TRUE); g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE); g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE); @@ -539,7 +539,7 @@ gst_ios_init (void) ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certifcates.crt", NULL); g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE); g_free (ca_certificates); - + gst_init (NULL, NULL); #if defined(GST_IOS_PLUGIN_NLE) || defined(GST_IOS_PLUGINS_GES) diff --git a/tutorials/xcode iOS/Tutorial 3/main.m b/examples/tutorials/xcode iOS/Tutorial 3/main.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/main.m rename to examples/tutorials/xcode iOS/Tutorial 3/main.m diff --git a/tutorials/xcode iOS/Tutorial 2/AppDelegate.h b/examples/tutorials/xcode iOS/Tutorial 4/AppDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/AppDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 4/AppDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 1/AppDelegate.m b/examples/tutorials/xcode iOS/Tutorial 4/AppDelegate.m similarity index 98% rename from tutorials/xcode iOS/Tutorial 1/AppDelegate.m rename to examples/tutorials/xcode iOS/Tutorial 4/AppDelegate.m index 31ef04e..0fe9773 100644 --- a/tutorials/xcode iOS/Tutorial 1/AppDelegate.m +++ b/examples/tutorials/xcode iOS/Tutorial 4/AppDelegate.m @@ -7,7 +7,7 @@ // Override point for customization after application launch. return YES; } - + - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. @@ -16,7 +16,7 @@ - (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } diff --git a/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h b/examples/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h similarity index 99% rename from tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h rename to examples/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h index ac4e798..e7b80e5 100644 --- a/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h +++ b/examples/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h @@ -8,4 +8,3 @@ } @end - diff --git a/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.m b/examples/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/EaglUIVIew.m rename to examples/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.m diff --git a/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.h b/examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/GStreamerBackend.h rename to examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.h diff --git a/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m b/examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m similarity index 97% rename from tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m rename to examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m index c6170bc..e19cab0 100644 --- a/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m +++ b/examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.m @@ -1,387 +1,386 @@ -#import "GStreamerBackend.h" - -#include -#include - -GST_DEBUG_CATEGORY_STATIC (debug_category); -#define GST_CAT_DEFAULT debug_category - -/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably - * confuse some demuxers. */ -#define SEEK_MIN_DELAY (500 * GST_MSECOND) - -@interface GStreamerBackend() --(void)setUIMessage:(gchar*) message; --(void)app_function; --(void)check_initialization_complete; -@end - -@implementation GStreamerBackend { - id ui_delegate; /* Class that we use to interact with the user interface */ - GstElement *pipeline; /* The running pipeline */ - GstElement *video_sink; /* The video sink element which receives XOverlay commands */ - GMainContext *context; /* GLib context used to run the main loop */ - GMainLoop *main_loop; /* GLib main loop */ - gboolean initialized; /* To avoid informing the UI multiple times about the initialization */ - UIView *ui_video_view; /* UIView that holds the video */ - GstState state; /* Current pipeline state */ - GstState target_state; /* Desired pipeline state, to be set once buffering is complete */ - gint64 duration; /* Cached clip duration */ - gint64 desired_position; /* Position to seek to, once the pipeline is running */ - GstClockTime last_seek_time; /* For seeking overflow prevention (throttling) */ - gboolean is_live; /* Live streams do not use buffering */ -} - -/* - * Interface methods - */ - --(id) init:(id) uiDelegate videoView:(UIView *)video_view -{ - if (self = [super init]) - { - self->ui_delegate = uiDelegate; - self->ui_video_view = video_view; - self->duration = GST_CLOCK_TIME_NONE; - - GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-4", 0, "iOS tutorial 4"); - gst_debug_set_threshold_for_name("tutorial-4", GST_LEVEL_DEBUG); - - /* Start the bus monitoring task */ - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - [self app_function]; - }); - } - - return self; -} - --(void) deinit -{ - if (main_loop) { - g_main_loop_quit(main_loop); - } -} - --(void) play -{ - target_state = GST_STATE_PLAYING; - is_live = (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); -} - --(void) pause -{ - target_state = GST_STATE_PAUSED; - is_live = (gst_element_set_state (pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); -} - --(void) setUri:(NSString*)uri -{ - const char *char_uri = [uri UTF8String]; - g_object_set(pipeline, "uri", char_uri, NULL); - GST_DEBUG ("URI set to %s", char_uri); -} - --(void) setPosition:(NSInteger)milliseconds -{ - gint64 position = (gint64)(milliseconds * GST_MSECOND); - if (state >= GST_STATE_PAUSED) { - execute_seek(position, self); - } else { - GST_DEBUG ("Scheduling seek to %" GST_TIME_FORMAT " for later", GST_TIME_ARGS (position)); - self->desired_position = position; - } -} - -/* - * Private methods - */ - -/* Change the message on the UI through the UI delegate */ --(void)setUIMessage:(gchar*) message -{ - NSString *string = [NSString stringWithUTF8String:message]; - if(ui_delegate && [ui_delegate respondsToSelector:@selector(gstreamerSetUIMessage:)]) - { - [ui_delegate gstreamerSetUIMessage:string]; - } -} - -/* Tell the application what is the current position and clip duration */ --(void) setCurrentUIPosition:(gint)pos duration:(gint)dur -{ - if(ui_delegate && [ui_delegate respondsToSelector:@selector(setCurrentPosition:duration:)]) - { - [ui_delegate setCurrentPosition:pos duration:dur]; - } -} - -/* If we have pipeline and it is running, query the current position and clip duration and inform - * the application */ -static gboolean refresh_ui (GStreamerBackend *self) { - gint64 position; - - /* We do not want to update anything unless we have a working pipeline in the PAUSED or PLAYING state */ - if (!self || !self->pipeline || self->state < GST_STATE_PAUSED) - return TRUE; - - /* If we didn't know it yet, query the stream duration */ - if (!GST_CLOCK_TIME_IS_VALID (self->duration)) { - gst_element_query_duration (self->pipeline, GST_FORMAT_TIME, &self->duration); - } - - if (gst_element_query_position (self->pipeline, GST_FORMAT_TIME, &position)) { - /* The UI expects these values in milliseconds, and GStreamer provides nanoseconds */ - [self setCurrentUIPosition:position / GST_MSECOND duration:self->duration / GST_MSECOND]; - } - return TRUE; -} - -/* Forward declaration for the delayed seek callback */ -static gboolean delayed_seek_cb (GStreamerBackend *self); - -/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for - * some time in the future. */ -static void execute_seek (gint64 position, GStreamerBackend *self) { - gint64 diff; - - if (position == GST_CLOCK_TIME_NONE) - return; - - diff = gst_util_get_timestamp () - self->last_seek_time; - - if (GST_CLOCK_TIME_IS_VALID (self->last_seek_time) && diff < SEEK_MIN_DELAY) { - /* The previous seek was too close, delay this one */ - GSource *timeout_source; - - if (self->desired_position == GST_CLOCK_TIME_NONE) { - /* There was no previous seek scheduled. Setup a timer for some time in the future */ - timeout_source = g_timeout_source_new ((SEEK_MIN_DELAY - diff) / GST_MSECOND); - g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, (__bridge void *)self, NULL); - g_source_attach (timeout_source, self->context); - g_source_unref (timeout_source); - } - /* Update the desired seek position. If multiple requests are received before it is time - * to perform a seek, only the last one is remembered. */ - self->desired_position = position; - GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, - GST_TIME_ARGS (position), GST_TIME_ARGS (SEEK_MIN_DELAY - diff)); - } else { - /* Perform the seek now */ - GST_DEBUG ("Seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); - self->last_seek_time = gst_util_get_timestamp (); - gst_element_seek_simple (self->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, position); - self->desired_position = GST_CLOCK_TIME_NONE; - } -} - -/* Delayed seek callback. This gets called by the timer setup in the above function. */ -static gboolean delayed_seek_cb (GStreamerBackend *self) { - GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (self->desired_position)); - execute_seek (self->desired_position, self); - return FALSE; -} - -/* Retrieve errors from the bus and show them on the UI */ -static void error_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) -{ - GError *err; - gchar *debug_info; - gchar *message_string; - - gst_message_parse_error (msg, &err, &debug_info); - message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); - g_clear_error (&err); - g_free (debug_info); - [self setUIMessage:message_string]; - g_free (message_string); - gst_element_set_state (self->pipeline, GST_STATE_NULL); -} - -/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */ -static void eos_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { - self->target_state = GST_STATE_PAUSED; - self->is_live = (gst_element_set_state (self->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); - execute_seek (0, self); -} - -/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */ -static void duration_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { - self->duration = GST_CLOCK_TIME_NONE; -} - -/* Called when buffering messages are received. We inform the UI about the current buffering level and - * keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */ -static void buffering_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { - gint percent; - - if (self->is_live) - return; - - gst_message_parse_buffering (msg, &percent); - if (percent < 100 && self->target_state >= GST_STATE_PAUSED) { - gchar * message_string = g_strdup_printf ("Buffering %d%%", percent); - gst_element_set_state (self->pipeline, GST_STATE_PAUSED); - [self setUIMessage:message_string]; - g_free (message_string); - } else if (self->target_state >= GST_STATE_PLAYING) { - gst_element_set_state (self->pipeline, GST_STATE_PLAYING); - } else if (self->target_state >= GST_STATE_PAUSED) { - [self setUIMessage:"Buffering complete"]; - } -} - -/* Called when the clock is lost */ -static void clock_lost_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { - if (self->target_state >= GST_STATE_PLAYING) { - gst_element_set_state (self->pipeline, GST_STATE_PAUSED); - gst_element_set_state (self->pipeline, GST_STATE_PLAYING); - } -} - -/* Retrieve the video sink's Caps and tell the application about the media size */ -static void check_media_size (GStreamerBackend *self) { - GstElement *video_sink; - GstPad *video_sink_pad; - GstCaps *caps; - GstVideoInfo info; - - /* Retrieve the Caps at the entrance of the video sink */ - g_object_get (self->pipeline, "video-sink", &video_sink, NULL); - - /* Do nothing if there is no video sink (this might be an audio-only clip */ - if (!video_sink) return; - - video_sink_pad = gst_element_get_static_pad (video_sink, "sink"); - caps = gst_pad_get_current_caps (video_sink_pad); - - if (gst_video_info_from_caps (&info, caps)) { - info.width = info.width * info.par_n / info.par_d; - GST_DEBUG ("Media size is %dx%d, notifying application", info.width, info.height); - - if (self->ui_delegate && [self->ui_delegate respondsToSelector:@selector(mediaSizeChanged:height:)]) - { - [self->ui_delegate mediaSizeChanged:info.width height:info.height]; - } - } - - gst_caps_unref(caps); - gst_object_unref (video_sink_pad); - gst_object_unref(video_sink); -} - -/* Notify UI about pipeline state changes */ -static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) -{ - GstState old_state, new_state, pending_state; - gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); - /* Only pay attention to messages coming from the pipeline, not its children */ - if (GST_MESSAGE_SRC (msg) == GST_OBJECT (self->pipeline)) { - self->state = new_state; - gchar *message = g_strdup_printf("State changed to %s", gst_element_state_get_name(new_state)); - [self setUIMessage:message]; - g_free (message); - - if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) - { - check_media_size(self); - - /* If there was a scheduled seek, perform it now that we have moved to the Paused state */ - if (GST_CLOCK_TIME_IS_VALID (self->desired_position)) - execute_seek (self->desired_position, self); - } - } -} - -/* Check if all conditions are met to report GStreamer as initialized. - * These conditions will change depending on the application */ --(void) check_initialization_complete -{ - if (!initialized && main_loop) { - GST_DEBUG ("Initialization complete, notifying application."); - if (ui_delegate && [ui_delegate respondsToSelector:@selector(gstreamerInitialized)]) - { - [ui_delegate gstreamerInitialized]; - } - initialized = TRUE; - } -} - -/* Main method for the bus monitoring code */ --(void) app_function -{ - GstBus *bus; - GSource *timeout_source; - GSource *bus_source; - GError *error = NULL; - - GST_DEBUG ("Creating pipeline"); - - /* Create our own GLib Main Context and make it the default one */ - context = g_main_context_new (); - g_main_context_push_thread_default(context); - - /* Build pipeline */ - pipeline = gst_parse_launch("playbin", &error); - if (error) { - gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message); - g_clear_error (&error); - [self setUIMessage:message]; - g_free (message); - return; - } - - /* Set the pipeline to READY, so it can already accept a window handle */ - gst_element_set_state(pipeline, GST_STATE_READY); - - video_sink = gst_bin_get_by_interface(GST_BIN(pipeline), GST_TYPE_VIDEO_OVERLAY); - if (!video_sink) { - GST_ERROR ("Could not retrieve video sink"); - return; - } - gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink), (guintptr) (id) ui_video_view); - - /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ - bus = gst_element_get_bus (pipeline); - bus_source = gst_bus_create_watch (bus); - g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); - g_source_attach (bus_source, context); - g_source_unref (bus_source); - g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, (__bridge void *)self); - g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, (__bridge void *)self); - g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, (__bridge void *)self); - g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, (__bridge void *)self); - g_signal_connect (G_OBJECT (bus), "message::buffering", (GCallback)buffering_cb, (__bridge void *)self); - g_signal_connect (G_OBJECT (bus), "message::clock-lost", (GCallback)clock_lost_cb, (__bridge void *)self); - gst_object_unref (bus); - - /* Register a function that GLib will call 4 times per second */ - timeout_source = g_timeout_source_new (250); - g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, (__bridge void *)self, NULL); - g_source_attach (timeout_source, context); - g_source_unref (timeout_source); - - /* Create a GLib Main Loop and set it to run */ - GST_DEBUG ("Entering main loop..."); - main_loop = g_main_loop_new (context, FALSE); - [self check_initialization_complete]; - g_main_loop_run (main_loop); - GST_DEBUG ("Exited main loop"); - g_main_loop_unref (main_loop); - main_loop = NULL; - - /* Free resources */ - g_main_context_pop_thread_default(context); - g_main_context_unref (context); - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - pipeline = NULL; - - ui_delegate = NULL; - ui_video_view = NULL; - - return; -} - -@end - +#import "GStreamerBackend.h" + +#include +#include + +GST_DEBUG_CATEGORY_STATIC (debug_category); +#define GST_CAT_DEFAULT debug_category + +/* Do not allow seeks to be performed closer than this distance. It is visually useless, and will probably + * confuse some demuxers. */ +#define SEEK_MIN_DELAY (500 * GST_MSECOND) + +@interface GStreamerBackend() +-(void)setUIMessage:(gchar*) message; +-(void)app_function; +-(void)check_initialization_complete; +@end + +@implementation GStreamerBackend { + id ui_delegate; /* Class that we use to interact with the user interface */ + GstElement *pipeline; /* The running pipeline */ + GstElement *video_sink; /* The video sink element which receives XOverlay commands */ + GMainContext *context; /* GLib context used to run the main loop */ + GMainLoop *main_loop; /* GLib main loop */ + gboolean initialized; /* To avoid informing the UI multiple times about the initialization */ + UIView *ui_video_view; /* UIView that holds the video */ + GstState state; /* Current pipeline state */ + GstState target_state; /* Desired pipeline state, to be set once buffering is complete */ + gint64 duration; /* Cached clip duration */ + gint64 desired_position; /* Position to seek to, once the pipeline is running */ + GstClockTime last_seek_time; /* For seeking overflow prevention (throttling) */ + gboolean is_live; /* Live streams do not use buffering */ +} + +/* + * Interface methods + */ + +-(id) init:(id) uiDelegate videoView:(UIView *)video_view +{ + if (self = [super init]) + { + self->ui_delegate = uiDelegate; + self->ui_video_view = video_view; + self->duration = GST_CLOCK_TIME_NONE; + + GST_DEBUG_CATEGORY_INIT (debug_category, "tutorial-4", 0, "iOS tutorial 4"); + gst_debug_set_threshold_for_name("tutorial-4", GST_LEVEL_DEBUG); + + /* Start the bus monitoring task */ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [self app_function]; + }); + } + + return self; +} + +-(void) deinit +{ + if (main_loop) { + g_main_loop_quit(main_loop); + } +} + +-(void) play +{ + target_state = GST_STATE_PLAYING; + is_live = (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_NO_PREROLL); +} + +-(void) pause +{ + target_state = GST_STATE_PAUSED; + is_live = (gst_element_set_state (pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); +} + +-(void) setUri:(NSString*)uri +{ + const char *char_uri = [uri UTF8String]; + g_object_set(pipeline, "uri", char_uri, NULL); + GST_DEBUG ("URI set to %s", char_uri); +} + +-(void) setPosition:(NSInteger)milliseconds +{ + gint64 position = (gint64)(milliseconds * GST_MSECOND); + if (state >= GST_STATE_PAUSED) { + execute_seek(position, self); + } else { + GST_DEBUG ("Scheduling seek to %" GST_TIME_FORMAT " for later", GST_TIME_ARGS (position)); + self->desired_position = position; + } +} + +/* + * Private methods + */ + +/* Change the message on the UI through the UI delegate */ +-(void)setUIMessage:(gchar*) message +{ + NSString *string = [NSString stringWithUTF8String:message]; + if(ui_delegate && [ui_delegate respondsToSelector:@selector(gstreamerSetUIMessage:)]) + { + [ui_delegate gstreamerSetUIMessage:string]; + } +} + +/* Tell the application what is the current position and clip duration */ +-(void) setCurrentUIPosition:(gint)pos duration:(gint)dur +{ + if(ui_delegate && [ui_delegate respondsToSelector:@selector(setCurrentPosition:duration:)]) + { + [ui_delegate setCurrentPosition:pos duration:dur]; + } +} + +/* If we have pipeline and it is running, query the current position and clip duration and inform + * the application */ +static gboolean refresh_ui (GStreamerBackend *self) { + gint64 position; + + /* We do not want to update anything unless we have a working pipeline in the PAUSED or PLAYING state */ + if (!self || !self->pipeline || self->state < GST_STATE_PAUSED) + return TRUE; + + /* If we didn't know it yet, query the stream duration */ + if (!GST_CLOCK_TIME_IS_VALID (self->duration)) { + gst_element_query_duration (self->pipeline, GST_FORMAT_TIME, &self->duration); + } + + if (gst_element_query_position (self->pipeline, GST_FORMAT_TIME, &position)) { + /* The UI expects these values in milliseconds, and GStreamer provides nanoseconds */ + [self setCurrentUIPosition:position / GST_MSECOND duration:self->duration / GST_MSECOND]; + } + return TRUE; +} + +/* Forward declaration for the delayed seek callback */ +static gboolean delayed_seek_cb (GStreamerBackend *self); + +/* Perform seek, if we are not too close to the previous seek. Otherwise, schedule the seek for + * some time in the future. */ +static void execute_seek (gint64 position, GStreamerBackend *self) { + gint64 diff; + + if (position == GST_CLOCK_TIME_NONE) + return; + + diff = gst_util_get_timestamp () - self->last_seek_time; + + if (GST_CLOCK_TIME_IS_VALID (self->last_seek_time) && diff < SEEK_MIN_DELAY) { + /* The previous seek was too close, delay this one */ + GSource *timeout_source; + + if (self->desired_position == GST_CLOCK_TIME_NONE) { + /* There was no previous seek scheduled. Setup a timer for some time in the future */ + timeout_source = g_timeout_source_new ((SEEK_MIN_DELAY - diff) / GST_MSECOND); + g_source_set_callback (timeout_source, (GSourceFunc)delayed_seek_cb, (__bridge void *)self, NULL); + g_source_attach (timeout_source, self->context); + g_source_unref (timeout_source); + } + /* Update the desired seek position. If multiple requests are received before it is time + * to perform a seek, only the last one is remembered. */ + self->desired_position = position; + GST_DEBUG ("Throttling seek to %" GST_TIME_FORMAT ", will be in %" GST_TIME_FORMAT, + GST_TIME_ARGS (position), GST_TIME_ARGS (SEEK_MIN_DELAY - diff)); + } else { + /* Perform the seek now */ + GST_DEBUG ("Seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + self->last_seek_time = gst_util_get_timestamp (); + gst_element_seek_simple (self->pipeline, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, position); + self->desired_position = GST_CLOCK_TIME_NONE; + } +} + +/* Delayed seek callback. This gets called by the timer setup in the above function. */ +static gboolean delayed_seek_cb (GStreamerBackend *self) { + GST_DEBUG ("Doing delayed seek to %" GST_TIME_FORMAT, GST_TIME_ARGS (self->desired_position)); + execute_seek (self->desired_position, self); + return FALSE; +} + +/* Retrieve errors from the bus and show them on the UI */ +static void error_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) +{ + GError *err; + gchar *debug_info; + gchar *message_string; + + gst_message_parse_error (msg, &err, &debug_info); + message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); + g_clear_error (&err); + g_free (debug_info); + [self setUIMessage:message_string]; + g_free (message_string); + gst_element_set_state (self->pipeline, GST_STATE_NULL); +} + +/* Called when the End Of the Stream is reached. Just move to the beginning of the media and pause. */ +static void eos_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { + self->target_state = GST_STATE_PAUSED; + self->is_live = (gst_element_set_state (self->pipeline, GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); + execute_seek (0, self); +} + +/* Called when the duration of the media changes. Just mark it as unknown, so we re-query it in the next UI refresh. */ +static void duration_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { + self->duration = GST_CLOCK_TIME_NONE; +} + +/* Called when buffering messages are received. We inform the UI about the current buffering level and + * keep the pipeline paused until 100% buffering is reached. At that point, set the desired state. */ +static void buffering_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { + gint percent; + + if (self->is_live) + return; + + gst_message_parse_buffering (msg, &percent); + if (percent < 100 && self->target_state >= GST_STATE_PAUSED) { + gchar * message_string = g_strdup_printf ("Buffering %d%%", percent); + gst_element_set_state (self->pipeline, GST_STATE_PAUSED); + [self setUIMessage:message_string]; + g_free (message_string); + } else if (self->target_state >= GST_STATE_PLAYING) { + gst_element_set_state (self->pipeline, GST_STATE_PLAYING); + } else if (self->target_state >= GST_STATE_PAUSED) { + [self setUIMessage:"Buffering complete"]; + } +} + +/* Called when the clock is lost */ +static void clock_lost_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) { + if (self->target_state >= GST_STATE_PLAYING) { + gst_element_set_state (self->pipeline, GST_STATE_PAUSED); + gst_element_set_state (self->pipeline, GST_STATE_PLAYING); + } +} + +/* Retrieve the video sink's Caps and tell the application about the media size */ +static void check_media_size (GStreamerBackend *self) { + GstElement *video_sink; + GstPad *video_sink_pad; + GstCaps *caps; + GstVideoInfo info; + + /* Retrieve the Caps at the entrance of the video sink */ + g_object_get (self->pipeline, "video-sink", &video_sink, NULL); + + /* Do nothing if there is no video sink (this might be an audio-only clip */ + if (!video_sink) return; + + video_sink_pad = gst_element_get_static_pad (video_sink, "sink"); + caps = gst_pad_get_current_caps (video_sink_pad); + + if (gst_video_info_from_caps (&info, caps)) { + info.width = info.width * info.par_n / info.par_d; + GST_DEBUG ("Media size is %dx%d, notifying application", info.width, info.height); + + if (self->ui_delegate && [self->ui_delegate respondsToSelector:@selector(mediaSizeChanged:height:)]) + { + [self->ui_delegate mediaSizeChanged:info.width height:info.height]; + } + } + + gst_caps_unref(caps); + gst_object_unref (video_sink_pad); + gst_object_unref(video_sink); +} + +/* Notify UI about pipeline state changes */ +static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) +{ + GstState old_state, new_state, pending_state; + gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state); + /* Only pay attention to messages coming from the pipeline, not its children */ + if (GST_MESSAGE_SRC (msg) == GST_OBJECT (self->pipeline)) { + self->state = new_state; + gchar *message = g_strdup_printf("State changed to %s", gst_element_state_get_name(new_state)); + [self setUIMessage:message]; + g_free (message); + + if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) + { + check_media_size(self); + + /* If there was a scheduled seek, perform it now that we have moved to the Paused state */ + if (GST_CLOCK_TIME_IS_VALID (self->desired_position)) + execute_seek (self->desired_position, self); + } + } +} + +/* Check if all conditions are met to report GStreamer as initialized. + * These conditions will change depending on the application */ +-(void) check_initialization_complete +{ + if (!initialized && main_loop) { + GST_DEBUG ("Initialization complete, notifying application."); + if (ui_delegate && [ui_delegate respondsToSelector:@selector(gstreamerInitialized)]) + { + [ui_delegate gstreamerInitialized]; + } + initialized = TRUE; + } +} + +/* Main method for the bus monitoring code */ +-(void) app_function +{ + GstBus *bus; + GSource *timeout_source; + GSource *bus_source; + GError *error = NULL; + + GST_DEBUG ("Creating pipeline"); + + /* Create our own GLib Main Context and make it the default one */ + context = g_main_context_new (); + g_main_context_push_thread_default(context); + + /* Build pipeline */ + pipeline = gst_parse_launch("playbin", &error); + if (error) { + gchar *message = g_strdup_printf("Unable to build pipeline: %s", error->message); + g_clear_error (&error); + [self setUIMessage:message]; + g_free (message); + return; + } + + /* Set the pipeline to READY, so it can already accept a window handle */ + gst_element_set_state(pipeline, GST_STATE_READY); + + video_sink = gst_bin_get_by_interface(GST_BIN(pipeline), GST_TYPE_VIDEO_OVERLAY); + if (!video_sink) { + GST_ERROR ("Could not retrieve video sink"); + return; + } + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(video_sink), (guintptr) (id) ui_video_view); + + /* Instruct the bus to emit signals for each received message, and connect to the interesting signals */ + bus = gst_element_get_bus (pipeline); + bus_source = gst_bus_create_watch (bus); + g_source_set_callback (bus_source, (GSourceFunc) gst_bus_async_signal_func, NULL, NULL); + g_source_attach (bus_source, context); + g_source_unref (bus_source); + g_signal_connect (G_OBJECT (bus), "message::error", (GCallback)error_cb, (__bridge void *)self); + g_signal_connect (G_OBJECT (bus), "message::eos", (GCallback)eos_cb, (__bridge void *)self); + g_signal_connect (G_OBJECT (bus), "message::state-changed", (GCallback)state_changed_cb, (__bridge void *)self); + g_signal_connect (G_OBJECT (bus), "message::duration", (GCallback)duration_cb, (__bridge void *)self); + g_signal_connect (G_OBJECT (bus), "message::buffering", (GCallback)buffering_cb, (__bridge void *)self); + g_signal_connect (G_OBJECT (bus), "message::clock-lost", (GCallback)clock_lost_cb, (__bridge void *)self); + gst_object_unref (bus); + + /* Register a function that GLib will call 4 times per second */ + timeout_source = g_timeout_source_new (250); + g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, (__bridge void *)self, NULL); + g_source_attach (timeout_source, context); + g_source_unref (timeout_source); + + /* Create a GLib Main Loop and set it to run */ + GST_DEBUG ("Entering main loop..."); + main_loop = g_main_loop_new (context, FALSE); + [self check_initialization_complete]; + g_main_loop_run (main_loop); + GST_DEBUG ("Exited main loop"); + g_main_loop_unref (main_loop); + main_loop = NULL; + + /* Free resources */ + g_main_context_pop_thread_default(context); + g_main_context_unref (context); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + pipeline = NULL; + + ui_delegate = NULL; + ui_video_view = NULL; + + return; +} + +@end diff --git a/tutorials/xcode iOS/Tutorial 5/GStreamerBackendDelegate.h b/examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackendDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/GStreamerBackendDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 4/GStreamerBackendDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Contents.json b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/AppIcon-2.appiconset/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-60@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-60@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-60@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-60@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-72@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-76@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-83.5@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-83.5@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-83.5@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon-83.5@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon.png diff --git a/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/AppIcon-4.appiconset/Icon@2x.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/Contents.json b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Contents.json b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x-1.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x-1.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x-1.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x-1.png diff --git a/tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png b/examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Images-2.xcassets/LaunchImage-2.launchimage/Default-568h@2x.png rename to examples/tutorials/xcode iOS/Tutorial 4/Images-4.xcassets/LaunchImage-4.launchimage/Default-568h@2x.png diff --git a/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Info.plist b/examples/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Tutorial 4-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch b/examples/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch rename to examples/tutorials/xcode iOS/Tutorial 4/Tutorial 4-Prefix.pch diff --git a/tutorials/xcode iOS/Tutorial 2/Ubuntu-R.ttf b/examples/tutorials/xcode iOS/Tutorial 4/Ubuntu-R.ttf similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/Ubuntu-R.ttf rename to examples/tutorials/xcode iOS/Tutorial 4/Ubuntu-R.ttf diff --git a/tutorials/xcode iOS/Tutorial 5/VideoViewController.h b/examples/tutorials/xcode iOS/Tutorial 4/VideoViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/VideoViewController.h rename to examples/tutorials/xcode iOS/Tutorial 4/VideoViewController.h diff --git a/tutorials/xcode iOS/Tutorial 4/VideoViewController.m b/examples/tutorials/xcode iOS/Tutorial 4/VideoViewController.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 4/VideoViewController.m rename to examples/tutorials/xcode iOS/Tutorial 4/VideoViewController.m index 8d01771..dba4311 100644 --- a/tutorials/xcode iOS/Tutorial 4/VideoViewController.m +++ b/examples/tutorials/xcode iOS/Tutorial 4/VideoViewController.m @@ -58,10 +58,10 @@ - (void)viewDidLoad { [super viewDidLoad]; - + play_button.enabled = FALSE; pause_button.enabled = FALSE; - + /* As soon as the GStreamer backend knows the real values, these ones will be replaced */ media_width = 320; media_height = 240; diff --git a/tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings b/examples/tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings similarity index 97% rename from tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings rename to examples/tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings index 477b28f..b92732c 100644 --- a/tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings +++ b/examples/tutorials/xcode iOS/Tutorial 4/en.lproj/InfoPlist.strings @@ -1,2 +1 @@ /* Localized versions of Info.plist keys */ - diff --git a/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPad.storyboard b/examples/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPad.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPad.storyboard rename to examples/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPad.storyboard diff --git a/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPhone.storyboard b/examples/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPhone.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPhone.storyboard rename to examples/tutorials/xcode iOS/Tutorial 4/en.lproj/MainStoryboard_iPhone.storyboard diff --git a/tutorials/xcode iOS/Tutorial 4/fonts.conf b/examples/tutorials/xcode iOS/Tutorial 4/fonts.conf similarity index 99% rename from tutorials/xcode iOS/Tutorial 4/fonts.conf rename to examples/tutorials/xcode iOS/Tutorial 4/fonts.conf index 6b780ea..e364473 100644 --- a/tutorials/xcode iOS/Tutorial 4/fonts.conf +++ b/examples/tutorials/xcode iOS/Tutorial 4/fonts.conf @@ -123,4 +123,3 @@ - diff --git a/tutorials/xcode iOS/Tutorial 4/gst_ios_init.h b/examples/tutorials/xcode iOS/Tutorial 4/gst_ios_init.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/gst_ios_init.h rename to examples/tutorials/xcode iOS/Tutorial 4/gst_ios_init.h diff --git a/tutorials/xcode iOS/Tutorial 5/gst_ios_init.m b/examples/tutorials/xcode iOS/Tutorial 4/gst_ios_init.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 5/gst_ios_init.m rename to examples/tutorials/xcode iOS/Tutorial 4/gst_ios_init.m index 8ca95f0..6cf7dc5 100644 --- a/tutorials/xcode iOS/Tutorial 5/gst_ios_init.m +++ b/examples/tutorials/xcode iOS/Tutorial 4/gst_ios_init.m @@ -516,19 +516,19 @@ gst_ios_init (void) NSString *tmp = NSTemporaryDirectory(); NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; - + const gchar *resources_dir = [resources UTF8String]; const gchar *tmp_dir = [tmp UTF8String]; const gchar *cache_dir = [cache UTF8String]; const gchar *docs_dir = [docs UTF8String]; gchar *ca_certificates; - + g_setenv ("TMP", tmp_dir, TRUE); g_setenv ("TEMP", tmp_dir, TRUE); g_setenv ("TMPDIR", tmp_dir, TRUE); g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE); g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE); - + g_setenv ("HOME", docs_dir, TRUE); g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE); g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE); @@ -539,7 +539,7 @@ gst_ios_init (void) ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certificates.crt", NULL); g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE); g_free (ca_certificates); - + gst_init (NULL, NULL); #if defined(GST_IOS_PLUGIN_NLE) || defined(GST_IOS_PLUGINS_GES) diff --git a/tutorials/xcode iOS/Tutorial 2/main.m b/examples/tutorials/xcode iOS/Tutorial 4/main.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 2/main.m rename to examples/tutorials/xcode iOS/Tutorial 4/main.m diff --git a/tutorials/xcode iOS/Tutorial 5/ssl/certs/ca-certificates.crt b/examples/tutorials/xcode iOS/Tutorial 4/ssl/certs/ca-certificates.crt similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/ssl/certs/ca-certificates.crt rename to examples/tutorials/xcode iOS/Tutorial 4/ssl/certs/ca-certificates.crt diff --git a/tutorials/xcode iOS/Tutorial 1/AppDelegate.h b/examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/AppDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.h diff --git a/examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.m b/examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.m new file mode 100644 index 0000000..0fe9773 --- /dev/null +++ b/examples/tutorials/xcode iOS/Tutorial 5/AppDelegate.m @@ -0,0 +1,38 @@ +#import "AppDelegate.h" + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + // Override point for customization after application launch. + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application +{ + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application +{ + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application +{ + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application +{ + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + +@end diff --git a/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h b/examples/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h similarity index 99% rename from tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h rename to examples/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h index ac4e798..e7b80e5 100644 --- a/tutorials/xcode iOS/Tutorial 4/EaglUIVIew.h +++ b/examples/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.h @@ -8,4 +8,3 @@ } @end - diff --git a/tutorials/xcode iOS/Tutorial 3/EaglUIVIew.m b/examples/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 3/EaglUIVIew.m rename to examples/tutorials/xcode iOS/Tutorial 5/EaglUIVIew.m diff --git a/tutorials/xcode iOS/Tutorial 4/GStreamerBackend.h b/examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/GStreamerBackend.h rename to examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.h diff --git a/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m b/examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m rename to examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m index 234eabc..be91ba7 100644 --- a/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m +++ b/examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackend.m @@ -188,7 +188,7 @@ static void error_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *self) GError *err; gchar *debug_info; gchar *message_string; - + gst_message_parse_error (msg, &err, &debug_info); message_string = g_strdup_printf ("Error received from element %s: %s", GST_OBJECT_NAME (msg->src), err->message); g_clear_error (&err); @@ -320,7 +320,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se /* Create our own GLib Main Context and make it the default one */ context = g_main_context_new (); g_main_context_push_thread_default(context); - + /* Build pipeline */ pipeline = gst_parse_launch("playbin", &error); if (error) { @@ -333,7 +333,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se /* Set the pipeline to READY, so it can already accept a window handle */ gst_element_set_state(pipeline, GST_STATE_READY); - + video_sink = gst_bin_get_by_interface(GST_BIN(pipeline), GST_TYPE_VIDEO_OVERLAY); if (!video_sink) { GST_ERROR ("Could not retrieve video sink"); @@ -369,14 +369,14 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se GST_DEBUG ("Exited main loop"); g_main_loop_unref (main_loop); main_loop = NULL; - + /* Free resources */ g_main_context_pop_thread_default(context); g_main_context_unref (context); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); pipeline = NULL; - + ui_delegate = NULL; ui_video_view = NULL; @@ -384,4 +384,3 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se } @end - diff --git a/tutorials/xcode iOS/Tutorial 4/GStreamerBackendDelegate.h b/examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackendDelegate.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/GStreamerBackendDelegate.h rename to examples/tutorials/xcode iOS/Tutorial 5/GStreamerBackendDelegate.h diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Contents.json b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/AppIcon-1.appiconset/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-60@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-60@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-60@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-60@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-72@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-76@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-83.5@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-83.5@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-83.5@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon-83.5@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon.png diff --git a/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/AppIcon-5.appiconset/Icon@2x.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/Contents.json b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Contents.json b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Contents.json similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Contents.json rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Contents.json diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x-1.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x-1.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x-1.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x-1.png diff --git a/tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x.png b/examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x.png similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Images-1.xcassets/LaunchImage-1.launchimage/Default-568h@2x.png rename to examples/tutorials/xcode iOS/Tutorial 5/Images-5.xcassets/LaunchImage-5.launchimage/Default-568h@2x.png diff --git a/tutorials/xcode iOS/Tutorial 5/LibraryViewController.h b/examples/tutorials/xcode iOS/Tutorial 5/LibraryViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/LibraryViewController.h rename to examples/tutorials/xcode iOS/Tutorial 5/LibraryViewController.h diff --git a/tutorials/xcode iOS/Tutorial 5/LibraryViewController.m b/examples/tutorials/xcode iOS/Tutorial 5/LibraryViewController.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/LibraryViewController.m rename to examples/tutorials/xcode iOS/Tutorial 5/LibraryViewController.m diff --git a/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Info.plist b/examples/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Info.plist similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Tutorial 5-Info.plist rename to examples/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Info.plist diff --git a/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch b/examples/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch rename to examples/tutorials/xcode iOS/Tutorial 5/Tutorial 5-Prefix.pch diff --git a/tutorials/xcode iOS/Tutorial 1/Ubuntu-R.ttf b/examples/tutorials/xcode iOS/Tutorial 5/Ubuntu-R.ttf similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/Ubuntu-R.ttf rename to examples/tutorials/xcode iOS/Tutorial 5/Ubuntu-R.ttf diff --git a/tutorials/xcode iOS/Tutorial 4/VideoViewController.h b/examples/tutorials/xcode iOS/Tutorial 5/VideoViewController.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/VideoViewController.h rename to examples/tutorials/xcode iOS/Tutorial 5/VideoViewController.h diff --git a/tutorials/xcode iOS/Tutorial 5/VideoViewController.m b/examples/tutorials/xcode iOS/Tutorial 5/VideoViewController.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 5/VideoViewController.m rename to examples/tutorials/xcode iOS/Tutorial 5/VideoViewController.m index 65d9642..90ac28f 100644 --- a/tutorials/xcode iOS/Tutorial 5/VideoViewController.m +++ b/examples/tutorials/xcode iOS/Tutorial 5/VideoViewController.m @@ -58,10 +58,10 @@ - (void)viewDidLoad { [super viewDidLoad]; - + play_button.enabled = FALSE; pause_button.enabled = FALSE; - + /* As soon as the GStreamer backend knows the real values, these ones will be replaced */ media_width = 320; media_height = 240; diff --git a/examples/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings b/examples/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings new file mode 100644 index 0000000..b92732c --- /dev/null +++ b/examples/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings @@ -0,0 +1 @@ +/* Localized versions of Info.plist keys */ diff --git a/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPad.storyboard b/examples/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPad.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPad.storyboard rename to examples/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPad.storyboard diff --git a/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPhone.storyboard b/examples/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPhone.storyboard similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPhone.storyboard rename to examples/tutorials/xcode iOS/Tutorial 5/en.lproj/MainStoryboard_iPhone.storyboard diff --git a/examples/tutorials/xcode iOS/Tutorial 5/fonts.conf b/examples/tutorials/xcode iOS/Tutorial 5/fonts.conf new file mode 100644 index 0000000..e364473 --- /dev/null +++ b/examples/tutorials/xcode iOS/Tutorial 5/fonts.conf @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + mono + + + monospace + + + + + + + sans serif + + + sans-serif + + + + + + + sans + + + sans-serif + + + + + + + 0x0020 + 0x00A0 + 0x00AD + 0x034F + 0x0600 + 0x0601 + 0x0602 + 0x0603 + 0x06DD + 0x070F + 0x115F + 0x1160 + 0x1680 + 0x17B4 + 0x17B5 + 0x180E + 0x2000 + 0x2001 + 0x2002 + 0x2003 + 0x2004 + 0x2005 + 0x2006 + 0x2007 + 0x2008 + 0x2009 + 0x200A + 0x200B + 0x200C + 0x200D + 0x200E + 0x200F + 0x2028 + 0x2029 + 0x202A + 0x202B + 0x202C + 0x202D + 0x202E + 0x202F + 0x205F + 0x2060 + 0x2061 + 0x2062 + 0x2063 + 0x206A + 0x206B + 0x206C + 0x206D + 0x206E + 0x206F + 0x2800 + 0x3000 + 0x3164 + 0xFEFF + 0xFFA0 + 0xFFF9 + 0xFFFA + 0xFFFB + + + + 30 + + + + diff --git a/tutorials/xcode iOS/Tutorial 5/gst_ios_init.h b/examples/tutorials/xcode iOS/Tutorial 5/gst_ios_init.h similarity index 100% rename from tutorials/xcode iOS/Tutorial 5/gst_ios_init.h rename to examples/tutorials/xcode iOS/Tutorial 5/gst_ios_init.h diff --git a/tutorials/xcode iOS/Tutorial 4/gst_ios_init.m b/examples/tutorials/xcode iOS/Tutorial 5/gst_ios_init.m similarity index 99% rename from tutorials/xcode iOS/Tutorial 4/gst_ios_init.m rename to examples/tutorials/xcode iOS/Tutorial 5/gst_ios_init.m index 8ca95f0..6cf7dc5 100644 --- a/tutorials/xcode iOS/Tutorial 4/gst_ios_init.m +++ b/examples/tutorials/xcode iOS/Tutorial 5/gst_ios_init.m @@ -516,19 +516,19 @@ gst_ios_init (void) NSString *tmp = NSTemporaryDirectory(); NSString *cache = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Caches"]; NSString *docs = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; - + const gchar *resources_dir = [resources UTF8String]; const gchar *tmp_dir = [tmp UTF8String]; const gchar *cache_dir = [cache UTF8String]; const gchar *docs_dir = [docs UTF8String]; gchar *ca_certificates; - + g_setenv ("TMP", tmp_dir, TRUE); g_setenv ("TEMP", tmp_dir, TRUE); g_setenv ("TMPDIR", tmp_dir, TRUE); g_setenv ("XDG_RUNTIME_DIR", resources_dir, TRUE); g_setenv ("XDG_CACHE_HOME", cache_dir, TRUE); - + g_setenv ("HOME", docs_dir, TRUE); g_setenv ("XDG_DATA_DIRS", resources_dir, TRUE); g_setenv ("XDG_CONFIG_DIRS", resources_dir, TRUE); @@ -539,7 +539,7 @@ gst_ios_init (void) ca_certificates = g_build_filename (resources_dir, "ssl", "certs", "ca-certificates.crt", NULL); g_setenv ("CA_CERTIFICATES", ca_certificates, TRUE); g_free (ca_certificates); - + gst_init (NULL, NULL); #if defined(GST_IOS_PLUGIN_NLE) || defined(GST_IOS_PLUGINS_GES) diff --git a/tutorials/xcode iOS/Tutorial 1/main.m b/examples/tutorials/xcode iOS/Tutorial 5/main.m similarity index 100% rename from tutorials/xcode iOS/Tutorial 1/main.m rename to examples/tutorials/xcode iOS/Tutorial 5/main.m diff --git a/tutorials/xcode iOS/Tutorial 4/ssl/certs/ca-certificates.crt b/examples/tutorials/xcode iOS/Tutorial 5/ssl/certs/ca-certificates.crt similarity index 100% rename from tutorials/xcode iOS/Tutorial 4/ssl/certs/ca-certificates.crt rename to examples/tutorials/xcode iOS/Tutorial 5/ssl/certs/ca-certificates.crt diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.pbxproj diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/01-Tutorial 1.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/01-Tutorial 1.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/01-Tutorial 1.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/01-Tutorial 1.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/02-Tutorial 2.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/02-Tutorial 2.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/02-Tutorial 2.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/02-Tutorial 2.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/03-Turorial 3.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/03-Turorial 3.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/03-Turorial 3.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/03-Turorial 3.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/04-Tutorial 4.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/04-Tutorial 4.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/04-Tutorial 4.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/04-Tutorial 4.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/05-Tutorial 5.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/05-Tutorial 5.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/05-Tutorial 5.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/05-Tutorial 5.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/06-Tutorial 6.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/06-Tutorial 6.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/06-Tutorial 6.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/06-Tutorial 6.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/07-Tutorial 7.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/07-Tutorial 7.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/07-Tutorial 7.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/07-Tutorial 7.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/08-Tutorial 8.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/08-Tutorial 8.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/08-Tutorial 8.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/08-Tutorial 8.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/09-Tutorial 9.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/09-Tutorial 9.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/09-Tutorial 9.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/09-Tutorial 9.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/12-Tutorial 12.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/12-Tutorial 12.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/12-Tutorial 12.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/12-Tutorial 12.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/13-Tutorial 13.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/13-Tutorial 13.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/13-Tutorial 13.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/13-Tutorial 13.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/15-Tutorial 15.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/15-Tutorial 15.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/15-Tutorial 15.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/15-Tutorial 15.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/21-Playback Tutorial 1.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/21-Playback Tutorial 1.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/21-Playback Tutorial 1.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/21-Playback Tutorial 1.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/22-Playback Tutorial 2.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/22-Playback Tutorial 2.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/22-Playback Tutorial 2.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/22-Playback Tutorial 2.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/23-Playback Tutorial 3.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/23-Playback Tutorial 3.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/23-Playback Tutorial 3.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/23-Playback Tutorial 3.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/24-Playback Tutorial 4.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/24-Playback Tutorial 4.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/24-Playback Tutorial 4.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/24-Playback Tutorial 4.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/25-Playback Tutorial 5.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/25-Playback Tutorial 5.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/25-Playback Tutorial 5.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/25-Playback Tutorial 5.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/26-Playback Tutorial 6.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/26-Playback Tutorial 6.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/26-Playback Tutorial 6.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/26-Playback Tutorial 6.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/27-Playback Tutorial 7.xcscheme b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/27-Playback Tutorial 7.xcscheme similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/27-Playback Tutorial 7.xcscheme rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/27-Playback Tutorial 7.xcscheme diff --git a/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist b/examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist similarity index 100% rename from tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist rename to examples/tutorials/xcode/GStreamer Tutorials.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist diff --git a/hotdoc.json b/hotdoc.json index 4875f39..26061db 100644 --- a/hotdoc.json +++ b/hotdoc.json @@ -1,10 +1,9 @@ { "add_anchors": true, "extra_assets": [ - "attachments", "images" ], - "index": "index.md", + "index": "markdown/index.md", "output": "built_doc", "pkg_config_packages": [ "gstreamer-1.0" @@ -13,6 +12,7 @@ "sitemap": "sitemap.txt", "syntax_highlighting_activate": true, "devhelp_activate": true, - "html_theme": "hotdoc_bootstrap_theme/dist", - "html_extra_theme": "extra_theme" + "html_theme": "theme/hotdoc_bootstrap_theme/dist", + "html_extra_theme": "theme/extra", + "include_paths": ["examples"] } diff --git a/attachments/WindowsInstall-BuildSolution.png b/images/WindowsInstall-BuildSolution.png similarity index 100% rename from attachments/WindowsInstall-BuildSolution.png rename to images/WindowsInstall-BuildSolution.png diff --git a/attachments/WindowsInstall-Configuration.png b/images/WindowsInstall-Configuration.png similarity index 100% rename from attachments/WindowsInstall-Configuration.png rename to images/WindowsInstall-Configuration.png diff --git a/attachments/WindowsInstall1.png b/images/WindowsInstall1.png similarity index 100% rename from attachments/WindowsInstall1.png rename to images/WindowsInstall1.png diff --git a/attachments/WindowsInstall10.png b/images/WindowsInstall10.png similarity index 100% rename from attachments/WindowsInstall10.png rename to images/WindowsInstall10.png diff --git a/attachments/WindowsInstall11.png b/images/WindowsInstall11.png similarity index 100% rename from attachments/WindowsInstall11.png rename to images/WindowsInstall11.png diff --git a/attachments/WindowsInstall2.png b/images/WindowsInstall2.png similarity index 100% rename from attachments/WindowsInstall2.png rename to images/WindowsInstall2.png diff --git a/attachments/WindowsInstall3.png b/images/WindowsInstall3.png similarity index 100% rename from attachments/WindowsInstall3.png rename to images/WindowsInstall3.png diff --git a/attachments/WindowsInstall4.png b/images/WindowsInstall4.png similarity index 100% rename from attachments/WindowsInstall4.png rename to images/WindowsInstall4.png diff --git a/attachments/WindowsInstall5.png b/images/WindowsInstall5.png similarity index 100% rename from attachments/WindowsInstall5.png rename to images/WindowsInstall5.png diff --git a/attachments/WindowsInstall6.png b/images/WindowsInstall6.png similarity index 100% rename from attachments/WindowsInstall6.png rename to images/WindowsInstall6.png diff --git a/attachments/WindowsInstall7.png b/images/WindowsInstall7.png similarity index 100% rename from attachments/WindowsInstall7.png rename to images/WindowsInstall7.png diff --git a/attachments/WindowsInstall8.png b/images/WindowsInstall8.png similarity index 100% rename from attachments/WindowsInstall8.png rename to images/WindowsInstall8.png diff --git a/attachments/WindowsInstall9.png b/images/WindowsInstall9.png similarity index 100% rename from attachments/WindowsInstall9.png rename to images/WindowsInstall9.png diff --git a/attachments/android.png b/images/android.png similarity index 100% rename from attachments/android.png rename to images/android.png diff --git a/attachments/contact.png b/images/contact.png similarity index 100% rename from attachments/contact.png rename to images/contact.png diff --git a/attachments/deploy.png b/images/deploy.png similarity index 100% rename from attachments/deploy.png rename to images/deploy.png diff --git a/attachments/download.png b/images/download.png similarity index 100% rename from attachments/download.png rename to images/download.png diff --git a/attachments/emoticons/information.png b/images/emoticons/information.png similarity index 100% rename from attachments/emoticons/information.png rename to images/emoticons/information.png diff --git a/attachments/faq.png b/images/faq.png similarity index 100% rename from attachments/faq.png rename to images/faq.png diff --git a/attachments/figure-1.png b/images/figure-1.png similarity index 100% rename from attachments/figure-1.png rename to images/figure-1.png diff --git a/attachments/ios.jpeg b/images/ios.jpeg similarity index 100% rename from attachments/ios.jpeg rename to images/ios.jpeg diff --git a/attachments/legal.png b/images/legal.png similarity index 100% rename from attachments/legal.png rename to images/legal.png diff --git a/attachments/linux.png b/images/linux.png similarity index 100% rename from attachments/linux.png rename to images/linux.png diff --git a/attachments/mac.png b/images/mac.png similarity index 100% rename from attachments/mac.png rename to images/mac.png diff --git a/attachments/reference.png b/images/reference.png similarity index 100% rename from attachments/reference.png rename to images/reference.png diff --git a/attachments/releases.png b/images/releases.png similarity index 100% rename from attachments/releases.png rename to images/releases.png diff --git a/attachments/tutorials.png b/images/tutorials.png similarity index 100% rename from attachments/tutorials.png rename to images/tutorials.png diff --git a/images/tutorial-android-a-complete-media-player-screenshot.png b/images/tutorials/android-a-complete-media-player-screenshot.png similarity index 100% rename from images/tutorial-android-a-complete-media-player-screenshot.png rename to images/tutorials/android-a-complete-media-player-screenshot.png diff --git a/images/tutorial-android-a-running-pipeline-screenshot.png b/images/tutorials/android-a-running-pipeline-screenshot.png similarity index 100% rename from images/tutorial-android-a-running-pipeline-screenshot.png rename to images/tutorials/android-a-running-pipeline-screenshot.png diff --git a/images/tutorial-android-link-against-gstreamer-screenshot.png b/images/tutorials/android-link-against-gstreamer-screenshot.png similarity index 100% rename from images/tutorial-android-link-against-gstreamer-screenshot.png rename to images/tutorials/android-link-against-gstreamer-screenshot.png diff --git a/images/tutorial-android-media-player-screenshot.png b/images/tutorials/android-media-player-screenshot.png similarity index 100% rename from images/tutorial-android-media-player-screenshot.png rename to images/tutorials/android-media-player-screenshot.png diff --git a/images/tutorial-android-video-screenshot.png b/images/tutorials/android-video-screenshot.png similarity index 100% rename from images/tutorial-android-video-screenshot.png rename to images/tutorials/android-video-screenshot.png diff --git a/attachments/basic-tutorial-5.png b/images/tutorials/basic-tutorial-5.png similarity index 100% rename from attachments/basic-tutorial-5.png rename to images/tutorials/basic-tutorial-5.png diff --git a/attachments/basic-tutorial-7.png b/images/tutorials/basic-tutorial-7.png similarity index 100% rename from attachments/basic-tutorial-7.png rename to images/tutorials/basic-tutorial-7.png diff --git a/attachments/basic-tutorial-8.png b/images/tutorials/basic-tutorial-8.png similarity index 100% rename from attachments/basic-tutorial-8.png rename to images/tutorials/basic-tutorial-8.png diff --git a/images/tutorial-ios-a-basic-media-player-screenshot.png b/images/tutorials/ios-a-basic-media-player-screenshot.png similarity index 100% rename from images/tutorial-ios-a-basic-media-player-screenshot.png rename to images/tutorials/ios-a-basic-media-player-screenshot.png diff --git a/images/tutorial-ios-a-complete-media-player-screenshot-0.png b/images/tutorials/ios-a-complete-media-player-screenshot-0.png similarity index 100% rename from images/tutorial-ios-a-complete-media-player-screenshot-0.png rename to images/tutorials/ios-a-complete-media-player-screenshot-0.png diff --git a/images/tutorial-ios-a-complete-media-player-screenshot-1.png b/images/tutorials/ios-a-complete-media-player-screenshot-1.png similarity index 100% rename from images/tutorial-ios-a-complete-media-player-screenshot-1.png rename to images/tutorials/ios-a-complete-media-player-screenshot-1.png diff --git a/images/tutorial-ios-a-running-pipeline-screenshot.png b/images/tutorials/ios-a-running-pipeline-screenshot.png similarity index 100% rename from images/tutorial-ios-a-running-pipeline-screenshot.png rename to images/tutorials/ios-a-running-pipeline-screenshot.png diff --git a/images/tutorial-ios-link-against-gstreamer-screenshot.png b/images/tutorials/ios-link-against-gstreamer-screenshot.png similarity index 100% rename from images/tutorial-ios-link-against-gstreamer-screenshot.png rename to images/tutorials/ios-link-against-gstreamer-screenshot.png diff --git a/images/tutorial-ios-video-screenshot.png b/images/tutorials/ios-video-screenshot.png similarity index 100% rename from images/tutorial-ios-video-screenshot.png rename to images/tutorials/ios-video-screenshot.png diff --git a/attachments/windows.png b/images/windows.png similarity index 100% rename from attachments/windows.png rename to images/windows.png diff --git a/deploying-your-application.md b/markdown/deploying/index.md similarity index 96% rename from deploying-your-application.md rename to markdown/deploying/index.md index 9b56f79..448581f 100644 --- a/deploying-your-application.md +++ b/markdown/deploying/index.md @@ -122,7 +122,7 @@ The following pages give further directions for some of the above options. - Platform-specific packaging methods: - - For [Mac OS X](deploying-mac-osx.md) - - For [Windows](deploying-windows.md) + - For [Mac OS X](deploying/mac-osx.md) + - For [Windows](deploying/windows.md) - [Multiplatform deployment using - Cerbero](deploying-multiplatform-using-cerbero.md) + Cerbero](deploying/multiplatform-using-cerbero.md) diff --git a/deploying-mac-osx.md b/markdown/deploying/mac-osx.md similarity index 99% rename from deploying-mac-osx.md rename to markdown/deploying/mac-osx.md index 899d30e..50860d1 100644 --- a/deploying-mac-osx.md +++ b/markdown/deploying/mac-osx.md @@ -1,7 +1,7 @@ # Mac OS X deployment This page explains how to deploy GStreamer along your application. There -are different mechanisms, which have been reviewed in [](deploying-your-application.md). The details for some +are different mechanisms, which have been reviewed in [](deploying/index.md). The details for some of the mechanisms are given here, and more options might be added to this documentation in the future. @@ -17,7 +17,7 @@ are somewhat blurred. With PackageMaker, simply add GStreamer **runtime ** disk image ([the same one you used to install the runtime in your development -machine](installing-on-mac-osx.md)) inside your installer +machine](installing/on-mac-osx.md)) inside your installer package and create a post-install script that mounts the disk image and installs GStreamer package. You can use the following example, where you should replace `$INSTALL_PATH` with the path where your installer copied diff --git a/deploying-multiplatform-using-cerbero.md b/markdown/deploying/multiplatform-using-cerbero.md similarity index 97% rename from deploying-multiplatform-using-cerbero.md rename to markdown/deploying/multiplatform-using-cerbero.md index 729b2e1..7b1e178 100644 --- a/deploying-multiplatform-using-cerbero.md +++ b/markdown/deploying/multiplatform-using-cerbero.md @@ -12,11 +12,11 @@ add a recipe explaining how to build you application and make it depend on the `gstreamer-sdk` project. Then Cerbero can take care of building your application and its dependencies and package them all together. -Read [](building-from-source-using-cerbero.md) to learn how +Read [](installing/building-from-source-using-cerbero.md) to learn how to install and use Cerbero. At this point, after reading the Build from source section in -[](building-from-source-using-cerbero.md), you should be able to +[](installing/building-from-source-using-cerbero.md), you should be able to build GStreamer from source and are ready to create recipe and package files for your application. @@ -115,7 +115,7 @@ class Recipe(recipe.Recipe): Cerbero gets the software sources to build from a GIT repository, which is specified via the `git_root` configuration variable from the Cerbero configuration file (see the "Build from software" section in [Installing -on Linux](installing-on-linux.md)) and can be overridden by the +on Linux](installing/on-linux.md)) and can be overridden by the `remotes` attribute inside the recipes (if setting the `origin` remote). In this case where no “commit” attribute is specified, Cerbero will use the commit named “sdk-0.2+git” from the GIT repository when building @@ -237,7 +237,7 @@ packages\_prefix as the ones in your Cerbero configuration file. Finally, build your package by using: ``` bash -./cerbero-uninstalled package your-package +./cerbero-uninstalled package your-package ``` Where `your-package` is the name of the `.package` file that you created diff --git a/deploying-windows.md b/markdown/deploying/windows.md similarity index 97% rename from deploying-windows.md rename to markdown/deploying/windows.md index 49733de..ad1187d 100644 --- a/deploying-windows.md +++ b/markdown/deploying/windows.md @@ -2,7 +2,7 @@ This page explains how to deploy GStreamer along your application. There are different mechanisms, which have been reviewed -in [](deploying-your-application.md). The details for some of the +in [](deploying/index.md). The details for some of the mechanisms are given here, and more options might be added to this documentation in the future. @@ -15,7 +15,7 @@ among all applications that use it, though, the extra space requirements are somewhat blurred. Simply pack GStreamer **runtime** installer ([the same one you -installed in your development machine](installing-on-windows.md)) +installed in your development machine](installing/on-windows.md)) inside your installer (or download it from your installer) and execute it silently using `msiexec`. `msiexec` is the tool that wraps most of the Windows Installer functionality and offers a number of options to diff --git a/basic-media-player.md b/markdown/for-later/basic-media-player.md similarity index 100% rename from basic-media-player.md rename to markdown/for-later/basic-media-player.md diff --git a/qt-gstreamer-vs-c-gstreamer.md b/markdown/for-later/qt-gstreamer-vs-c-gstreamer.md similarity index 100% rename from qt-gstreamer-vs-c-gstreamer.md rename to markdown/for-later/qt-gstreamer-vs-c-gstreamer.md diff --git a/using-appsink-appsrc-in-qt.md b/markdown/for-later/using-appsink-appsrc-in-qt.md similarity index 100% rename from using-appsink-appsrc-in-qt.md rename to markdown/for-later/using-appsink-appsrc-in-qt.md diff --git a/index.md b/markdown/index.md similarity index 98% rename from index.md rename to markdown/index.md index c6ab878..38d3f4e 100644 --- a/index.md +++ b/markdown/index.md @@ -8,9 +8,9 @@ all about. ## General - * [Application Development Manual (Read this first)](manual-index.md) + * [Application Development Manual (Read this first)](manual/index.md) * Frequently Asked Questions - * [](pwg-index.md) + * [](pwg/index.md) * Core Reference * Core Libraries Reference/a> * [Core Design Documentation](http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/design/) diff --git a/building-from-source-using-cerbero.md b/markdown/installing/building-from-source-using-cerbero.md similarity index 99% rename from building-from-source-using-cerbero.md rename to markdown/installing/building-from-source-using-cerbero.md index fbb7343..ab71100 100644 --- a/building-from-source-using-cerbero.md +++ b/markdown/installing/building-from-source-using-cerbero.md @@ -238,4 +238,4 @@ To cross compile for iOS from OS X, use the configuration file [Windows Driver Kit 7.1.0]: http://msdn.microsoft.com/en-us/windows/hardware/hh852365 [XCode]: https://developer.apple.com/devcenter/ios/index.action#downloads [here]: http://www.freedesktop.org/software/gstreamer-sdk/cerbero.cbc.template - [Installing GStreamer]: installing.md + [Installing GStreamer]: installing/index.md diff --git a/installing-for-android-development.md b/markdown/installing/for-android-development.md similarity index 99% rename from installing-for-android-development.md rename to markdown/installing/for-android-development.md index c35cc2c..b8917b5 100644 --- a/installing-for-android-development.md +++ b/markdown/installing/for-android-development.md @@ -72,7 +72,7 @@ interact through [JNI][Java Native Interface]. The tutorials code are in the [gst-docs](https://cgit.freedesktop.org/gstreamer/gst-docs/) in the -`tutorials/` folder. +`examples/tutorials/` folder. There are a few Android-specific tutorials in the `tutorials/` folder. Each tutorial is a folder containing source code (in Java and @@ -293,7 +293,7 @@ and used as follows: | `GSTREAMER_PLUGINS_ENCODING` | encodebin | | `GSTREAMER_PLUGINS_GES` | nle | -Build and run your application as explained in the [Building the tutorial](installing-for-android-development.md#building-the-tutorials) section. +Build and run your application as explained in the [Building the tutorials] section. [information]: images/icons/emoticons/information.png [Android SDK]: http://developer.android.com/sdk/index.html diff --git a/installing-for-ios-development.md b/markdown/installing/for-ios-development.md similarity index 96% rename from installing-for-ios-development.md rename to markdown/installing/for-ios-development.md index b4585c9..3b1bbbb 100644 --- a/installing-for-ios-development.md +++ b/markdown/installing/for-ios-development.md @@ -51,7 +51,7 @@ example. The tutorials code are in the [gst-docs](https://cgit.freedesktop.org/gstreamer/gst-docs/) in the -`tutorials/xcode iOS` folder. We recommend that you open the project +`examples/tutorials/xcode iOS` folder. We recommend that you open the project in Xcode, take a look at the sources and build them. This should confirm that the installation works and give some insight on how simple it is to mix Objective-C and C code. @@ -85,4 +85,4 @@ keep development consistent across all the platforms the SDK supports. Once a project has been created using a GStreamer SDK Template, it is ready to build and run. All necessary infrastructure is already in place. To understand what files have been created and how they interact, -take a look at the [iOS tutorials](tutorials-ios.md). +take a look at the [iOS tutorials](tutorials/ios/index.md). diff --git a/installing.md b/markdown/installing/index.md similarity index 68% rename from installing.md rename to markdown/installing/index.md index 900f226..8d82265 100644 --- a/installing.md +++ b/markdown/installing/index.md @@ -6,10 +6,10 @@ short-description: Download and install GStreamer ## Choose your platform by clicking on the corresponding logo -[![](attachments/mac.png)](installing-on-mac-osx.md) -[![](attachments/windows.png)](installing-on-windows.md) -[![](attachments/android.png)](installing-for-android-development.md) -[![](attachments/ios.jpeg)](installing-for-ios-development.md) +[![](images/mac.png)](installing/on-mac-osx.md) +[![](images/windows.png)](installing/on-windows.md) +[![](images/android.png)](installing/for-android-development.md) +[![](images/ios.jpeg)](installing/for-ios-development.md) ## Linux @@ -20,4 +20,4 @@ environments, you will just need to make sure you have the development packages installed (refer to your distribution documentation for more information). If you really want to run upstream style binaries on Linux, you can always follow the instructions to [build from source -using cerbero](building-from-source-using-cerbero.md). +using cerbero](installing/building-from-source-using-cerbero.md). diff --git a/installing-on-linux.md b/markdown/installing/on-linux.md similarity index 97% rename from installing-on-linux.md rename to markdown/installing/on-linux.md index e1cb959..9cff5dd 100644 --- a/installing-on-linux.md +++ b/markdown/installing/on-linux.md @@ -47,7 +47,7 @@ the `configure` script from inside the `gst-sdk-shell` environment. The source code for the tutorials can be copied and pasted from the tutorial pages into a text file, but, for convenience, it is also available -in a GIT repository in the `tutorials` subdirectory. +in a GIT repository in the `examples/tutorials` subdirectory. The GIT repository can be cloned with: diff --git a/installing-on-mac-osx.md b/markdown/installing/on-mac-osx.md similarity index 97% rename from installing-on-mac-osx.md rename to markdown/installing/on-mac-osx.md index 5699385..2a23bf3 100644 --- a/installing-on-mac-osx.md +++ b/markdown/installing/on-mac-osx.md @@ -38,9 +38,9 @@ Get **both the runtime and the development installers** from [here](https://gstr > ![Warning](images/icons/emoticons/warning.png) > On Mac OS X 10.6 (Snow Leopard) you have to install Python 2.7 manually. It is included in later versions of OS X already. You can get it from [here](http://www.python.org/getit). -The downloads are +The downloads are [Installer Packages -(.pkg)](http://en.wikipedia.org/wiki/Installer_%28Mac_OS_X%29). +(.pkg)](http://en.wikipedia.org/wiki/Installer_%28Mac_OS_X%29). Double click the package file and follow the instructions presented by the install wizard. In case the system complains about the package not @@ -75,7 +75,7 @@ following [link](https://developer.apple.com/library/mac/#documentation/MacOSX/C The tutorials code, along with project files and a solution file for them all, are in the [gst-docs](https://cgit.freedesktop.org/gstreamer/gst-docs/) in the -`tutorials` subdirectory. +`examples/tutorials` subdirectory. To start building the tutorials, create a new folder in your Documents directory and copy the diff --git a/installing-on-windows.md b/markdown/installing/on-windows.md similarity index 97% rename from installing-on-windows.md rename to markdown/installing/on-windows.md index 412cf60..383f83e 100644 --- a/installing-on-windows.md +++ b/markdown/installing/on-windows.md @@ -51,7 +51,7 @@ There are 3 sets of files in GStreamer binaries: Modules](http://msdn.microsoft.com/en-us/library/windows/desktop/aa369820%28v=vs.85%29.aspx) files are **additional** files you can use to deploy GStreamer binaries alongside your application (see [Windows - deployment](deploying-windows.md)). + deployment](deploying/windows.md)). Get **the Runtime and Development files** installers appropriate for your architecture from here: @@ -99,7 +99,7 @@ plugins are located. The tutorials code, along with project files and a solution file for Visual Studio 2010, are in the [gst-docs](https://cgit.freedesktop.org/gstreamer/gst-docs/) in the -`tutorials` folder. +`examples/tutorials` folder. In order to prevent accidental modification of the original code, and to make sure Visual Studio has the necessary permissions to write the @@ -113,18 +113,18 @@ liking, and work from there. > >Make sure you select the Solution Configuration that matches GStreamer that you have installed: `Win32` for 32 bits or `x64` for 64 bits. > -> ![Windows Install Configuration](attachments/WindowsInstall-Configuration.png) +> ![Windows Install Configuration](images/WindowsInstall-Configuration.png) You can fire up Visual Studio 2010 and load your copy of the `tutorials.sln` solution file (Click on the screen shots to enlarge them). -![](attachments/WindowsInstall2.png) +![](images/WindowsInstall2.png) -![](attachments/WindowsInstall1.png) +![](images/WindowsInstall1.png) Hit **F7**, press the Build Solution button -![](attachments/WindowsInstall-BuildSolution.png) or go to Build → +![](images/WindowsInstall-BuildSolution.png) or go to Build → Build Solution. All projects should build without problems. ### Running the tutorials @@ -168,7 +168,7 @@ Settings. Go to Tools → Settings → Expert Settings. Upon first installation of Visual Studio, Expert Settings are disabled by default. -![](attachments/WindowsInstall10.png) +![](images/WindowsInstall10.png) > ![Warning](images/icons/emoticons/warning.png) > **Depending on the GStreamer libraries you need to use, you will have to add more property pages, besides `gstreamer-1.0`** (each property page corresponds to one GStreamer library). diff --git a/legal-information.md b/markdown/legal-information.md similarity index 98% rename from legal-information.md rename to markdown/legal-information.md index 22bb12d..ddeb916 100644 --- a/legal-information.md +++ b/markdown/legal-information.md @@ -96,8 +96,8 @@ maintenance agreement with a company or entity that is in that business. ## Licensing of code contributed to GStreamer itself GStreamer is a plugin-based framework licensed under the LGPL. The -reason for this choice in licensing is to ensure that everyone can use -GStreamer to build applications using licenses of their choice. +reason for this choice in licensing is to ensure that everyone can use +GStreamer to build applications using licenses of their choice. To keep this policy viable, the GStreamer community has made a few licensing rules for code to be included in GStreamer's core or GStreamer's @@ -252,7 +252,7 @@ decompilation to debug modifications to the library. ## Licensing applications under the GNU GPL using GStreamer -The licensing of GStreamer is no different from a lot of other libraries out +The licensing of GStreamer is no different from a lot of other libraries out there like GTK+ or glibc: we use the [LGPL](http://www.fsf.org/licenses/lgpl.html). @@ -263,19 +263,19 @@ world countries (the US and Australia being the most important of those), the problem is that due to the central place the US hold in the world economy and the computing industry, software patents are hard to ignore wherever you are. -Due to this situation, many companies, including major GNU/Linux distributions, -get trapped in a situation where they either get bad reviews due to lacking -out-of-the-box media playback capabilities (and attempts to educate the -reviewers have met with little success so far), or go against their -own - and the free software movement's - wish to avoid proprietary software. - -Due to competitive pressure, most choose to add some support. Doing that -through pure free software solutions would have them risk heavy litigation and -punishment from patent owners. So when the decision is made to include support -for patented codecs, it leaves them the choice of either using special -proprietary applications, or try to integrate the support for these codecs -through proprietary plugins into the multimedia infrastructure provided by -GStreamer. Faced with one of these two evils the GStreamer community of +Due to this situation, many companies, including major GNU/Linux distributions, +get trapped in a situation where they either get bad reviews due to lacking +out-of-the-box media playback capabilities (and attempts to educate the +reviewers have met with little success so far), or go against their +own - and the free software movement's - wish to avoid proprietary software. + +Due to competitive pressure, most choose to add some support. Doing that +through pure free software solutions would have them risk heavy litigation and +punishment from patent owners. So when the decision is made to include support +for patented codecs, it leaves them the choice of either using special +proprietary applications, or try to integrate the support for these codecs +through proprietary plugins into the multimedia infrastructure provided by +GStreamer. Faced with one of these two evils the GStreamer community of course prefer the second option. The problem which arises is that most free software and open source @@ -311,22 +311,22 @@ GStreamer plugins from the obligations of the GPL. A good example of such a GPL exception clause would be, using the Totem video player project as an example: -*The developers of the Totem video player hereby grants permission for -non-GPL compatible GStreamer plugins to be used and distributed together -with GStreamer and Totem. This permission is above and beyond the permissions -granted by the GPL license by which Totem is covered. If you modify this code, -you may extend this exception to your version of the code, but you are -not obligated to do so. If you do not wish to do so, delete this exception +*The developers of the Totem video player hereby grants permission for +non-GPL compatible GStreamer plugins to be used and distributed together +with GStreamer and Totem. This permission is above and beyond the permissions +granted by the GPL license by which Totem is covered. If you modify this code, +you may extend this exception to your version of the code, but you are +not obligated to do so. If you do not wish to do so, delete this exception statement from your version.* Our suggestion among these choices is to use the LGPL license, as it is what resembles the GPL most and it makes it a good licensing fit with the major GNU/Linux desktop projects like GNOME and KDE. It also allows you to share code more openly with projects that have compatible licenses. As you might -deduce, pure GPL licensed code without the above-mentioned clause is not -re-usable in your application under a GPL plus exception clause unless you -get the author of the pure GPL code to allow a relicensing to GPL plus -exception clause. By choosing the LGPL, there is no need for an exception +deduce, pure GPL licensed code without the above-mentioned clause is not +re-usable in your application under a GPL plus exception clause unless you +get the author of the pure GPL code to allow a relicensing to GPL plus +exception clause. By choosing the LGPL, there is no need for an exception clause and thus code can be shared freely between your application and other LGPL using projects. diff --git a/manual-autoplugging.md b/markdown/manual/advanced/autoplugging.md similarity index 94% rename from manual-autoplugging.md rename to markdown/manual/advanced/autoplugging.md index 60d65de..cd82fef 100644 --- a/manual-autoplugging.md +++ b/markdown/manual/advanced/autoplugging.md @@ -4,7 +4,7 @@ title: Autoplugging # Autoplugging -In [Your first application](manual-helloworld.md), you've learned to +In [Your first application](manual/building/helloworld.md), you've learned to build a simple media player for Ogg/Vorbis files. By using alternative elements, you are able to build media players for other media types, such as Ogg/Speex, MP3 or even video formats. However, you would rather @@ -13,7 +13,7 @@ type of a stream and automatically generate the best possible pipeline by looking at all available elements in a system. This process is called autoplugging, and GStreamer contains high-quality autopluggers. If you're looking for an autoplugger, don't read any further and go to -[Playback Components](manual-playback-components.md). This chapter will +[Playback Components](manual/highlevel/playback-components.md). This chapter will explain the *concept* of autoplugging and typefinding. It will explain what systems GStreamer includes to dynamically detect the type of a media stream, and how to generate a pipeline of decoder elements to @@ -34,7 +34,7 @@ to another, for example for media decoding. We have previously introduced the concept of capabilities as a way for elements (or, rather, pads) to agree on a media type when streaming data from one element to the next (see [Capabilities of a -pad](manual-pads.md#capabilities-of-a-pad)). We have explained that a +pad](manual/building/pads.md#capabilities-of-a-pad)). We have explained that a capability is a combination of a media type and a set of properties. For most container formats (those are the files that you will find on your hard disk; Ogg, for example, is a container format), no properties are @@ -49,7 +49,7 @@ elements and what type of data they expect and emit through the GStreamer registry. This allows for very dynamic and extensible element creation as we will see. -In [Your first application](manual-helloworld.md), we've learned to +In [Your first application](manual/building/helloworld.md), we've learned to build a music player for Ogg/Vorbis files. Let's look at the media types associated with each pad in this pipeline. [The Hello world pipeline with media types](#the-hello-world-pipeline-with-media-types) shows what @@ -130,7 +130,7 @@ cb_typefound (GstElement *typefind, g_idle_add (idle_exit_loop, loop); } -gint +gint main (gint argc, gchar *argv[]) { @@ -174,7 +174,7 @@ main (gint argc, return 0; } - + ``` Once a media type has been detected, you can plug an element (e.g. a @@ -183,6 +183,5 @@ decoding of the media stream will start right after. ## Dynamically autoplugging a pipeline -See [Playback Components](manual-playback-components.md) for using the +See [Playback Components](manual/highlevel/playback-components.md) for using the high level object that you can use to dynamically construct pipelines. - diff --git a/manual-buffering.md b/markdown/manual/advanced/buffering.md similarity index 99% rename from manual-buffering.md rename to markdown/manual/advanced/buffering.md index c0e2fd0..4c628eb 100644 --- a/manual-buffering.md +++ b/markdown/manual/advanced/buffering.md @@ -73,17 +73,17 @@ strategies](#buffering-strategies). [...] - + ``` ## Stream buffering -``` +``` +---------+ +---------+ +-------+ | httpsrc | | buffer | | demux | | src - sink src - sink .... +---------+ +---------+ +-------+ - + ``` In this case we are reading from a slow network source into a buffer @@ -120,7 +120,7 @@ ideas: - It is possible to measure the network bandwidth and configure the low/high watermarks in such a way that buffering takes a fixed amount of time. - + The queue2 element in GStreamer core has the max-size-time property that, together with the use-rate-estimate property, does exactly that. Also the playbin buffer-duration property uses the rate @@ -146,14 +146,14 @@ network drive (with filesrc) this can be an interesting way to buffer. ## Download buffering -``` +``` +---------+ +---------+ +-------+ | httpsrc | | buffer | | demux | | src - sink src - sink .... +---------+ +----|----+ +-------+ V file - + ``` If we know the server is streaming a fixed length file to the client, @@ -174,14 +174,14 @@ strategies](#buffering-strategies). ## Timeshift buffering -``` +``` +---------+ +---------+ +-------+ | httpsrc | | buffer | | demux | | src - sink src - sink .... +---------+ +----|----+ +-------+ V file-ringbuffer - + ``` In this mode, a fixed size ringbuffer is kept to download the server @@ -381,7 +381,7 @@ main (gint argc, } - + ``` See how we set the pipeline to the PAUSED state first. We will receive @@ -390,4 +390,3 @@ When we are prerolled (on\_message\_async\_done) we see if buffering is going on, if not, we start playback. If buffering was going on, we start a timeout to poll the buffering state. If the estimated time to download is less than the remaining playback time, we start playback. - diff --git a/manual-clocks.md b/markdown/manual/advanced/clocks.md similarity index 99% rename from manual-clocks.md rename to markdown/manual/advanced/clocks.md index 22cc332..3a520b3 100644 --- a/manual-clocks.md +++ b/markdown/manual/advanced/clocks.md @@ -198,4 +198,3 @@ bus. The application can then decide to query and redistribute a new latency or not. Changing the latency in a pipeline might cause visual or audible glitches and should therefore only be done by the application when it is allowed. - diff --git a/manual-dataaccess.md b/markdown/manual/advanced/dataaccess.md similarity index 99% rename from manual-dataaccess.md rename to markdown/manual/advanced/dataaccess.md index 3b2cec7..7f68cc2 100644 --- a/manual-dataaccess.md +++ b/markdown/manual/advanced/dataaccess.md @@ -31,7 +31,7 @@ The probe can notify you of the following activity on pads: the pad can be scheduled in different ways, it is possible to also specify in what scheduling mode you are interested with the optional GST\_PAD\_PROBE\_TYPE\_PUSH and GST\_PAD\_PROBE\_TYPE\_PULL flags. - + You can use this probe to inspect, modify or drop the buffer. See [Data probes](#data-probes). @@ -47,7 +47,7 @@ The probe can notify you of the following activity on pads: a notification. You need to explicitly enable GST\_PAD\_PROBE\_TYPE\_EVENT\_FLUSH to receive callbacks from flushing events. Events are always only notified in push mode. - + You can use this probe to inspect, modify or drop the event. - A query travels over a pad. Use the @@ -61,7 +61,7 @@ The probe can notify you of the following activity on pads: with the GST\_PAD\_PROBE\_TYPE\_PUSH and GST\_PAD\_PROBE\_TYPE\_PULL, respectively when the query is performed and when the query result is returned. - + You can use this probe to inspect or modify the query. You can also answer the query in the probe callback by placing the result value in the query and by returning GST\_PAD\_PROBE\_DROP from the @@ -76,7 +76,7 @@ The probe can notify you of the following activity on pads: GST\_PAD\_PROBE\_REMOVE from the callback. You can let only the currently blocked item pass by returning GST\_PAD\_PROBE\_PASS from the callback, it will block again on the next item. - + Blocking probes are used to temporarily block pads because they are unlinked or because you are going to unlink them. If the dataflow is not blocked, the pipeline would go into an error state if data is @@ -90,7 +90,7 @@ The probe can notify you of the following activity on pads: only be notified depending on the pad scheduling mode. The IDLE probe is also a blocking probe in that it will not let any data pass on the pad for as long as the IDLE probe is installed. - + You can use idle probes to dynamically relink a pad. We will see how to use idle probes to replace an element in the pipeline. See also [Dynamically changing the @@ -228,7 +228,7 @@ main (gint argc, } - + ``` Compare that output with the output of “gst-launch-1.0 videotestsrc \! @@ -707,7 +707,7 @@ main (gint argc, } - + ``` ### Grabbing data with appsink @@ -923,7 +923,7 @@ the “capsfilter” element in between the two elements, and specifying a `GstCaps` as “caps” property on this element. It will then only allow types matching that specified capability set for negotiation. See also [Creating capabilities for -filtering](manual-pads.md#creating-capabilities-for-filtering). +filtering](manual/building/pads.md#creating-capabilities-for-filtering). ### Changing format in a PLAYING pipeline @@ -1017,7 +1017,7 @@ main (int argc, char **argv) } - + ``` Note how we use `gst_bus_poll()` with a small timeout to get messages @@ -1061,7 +1061,7 @@ pipelines: flush any queued data in the element by sending an EOS event down the element sink pad(s) and by waiting that the EOS leaves the elements (with an event probe). - + If you do not do this, you will lose the data which is buffered by the unlinked element. This can result in a simple frame loss (one or more video frames, several milliseconds of audio). However if you @@ -1069,17 +1069,17 @@ pipelines: from the pipeline, you risk getting a corrupted file which could not be played properly, as some relevant metadata (header, seek/index tables, internal sync tags) will not be stored or updated properly. - + See also [Changing elements in a pipeline](#changing-elements-in-a-pipeline). - A live source will produce buffers with a running-time of the current running-time in the pipeline. - + A pipeline without a live source produces buffers with a running-time starting from 0. Likewise, after a flushing seek, those pipelines reset the running-time back to 0. - + The running-time can be changed with `gst_pad_set_offset ()`. It is important to know the running-time of the elements in the pipeline in order to maintain synchronization. @@ -1088,11 +1088,11 @@ pipelines: non-prerolled sink, for example, brings the pipeline back to the prerolling state. Removing a non-prerolled sink, for example, might change the pipeline to PAUSED and PLAYING state. - + Adding a live source cancels the preroll stage and put the pipeline to the playing state. Adding a live source or other live elements might also change the latency of a pipeline. - + Adding or removing elements to the pipeline might change the clock selection of the pipeline. If the newly added element provides a clock, it might be worth changing the clock in the pipeline to the @@ -1104,7 +1104,7 @@ pipelines: need to do anything from the application, plugins largely adapt themself to the new pipeline topology in order to optimize their formats and allocation strategy. - + What is important is that when you add, remove or change elements in the pipeline, it is possible that the pipeline needs to negotiate a new format and this can fail. Usually you can fix this by inserting @@ -1120,12 +1120,12 @@ will demonstrate a couple of typical use-cases. In the next example we look at the following chain of elements: -``` +``` - ----. .----------. .---- - element1 | | element2 | | element3 src -> sink src -> sink - ----' '----------' '---- - - + ``` We want to change element2 by element4 while the pipeline is in the @@ -1151,12 +1151,12 @@ following steps: internally keep some data, you need to make sure not to lose data by forcing it out of element2. You can do this by pushing EOS into element2, like this: - + - Put an event probe on element2's source pad. - + - Send EOS to element2's sinkpad. This makes sure the all the data inside element2 is forced out. - + - Wait for the EOS event to appear on element2's source pad. When the EOS is received, drop it and remove the event probe. @@ -1394,11 +1394,10 @@ main (int argc, char **argv) } - + ``` Note how we added videoconvert elements before and after the effect. This is needed because some elements might operate in different colorspaces than other elements. By inserting the conversion elements you ensure that the right format can be negotiated at any time. - diff --git a/manual-dparams.md b/markdown/manual/advanced/dparams.md similarity index 99% rename from manual-dparams.md rename to markdown/manual/advanced/dparams.md index 023182f..c5d64d5 100644 --- a/manual-dparams.md +++ b/markdown/manual/advanced/dparams.md @@ -32,7 +32,7 @@ application's source file: #include #include ... - + ``` Your application should link to the shared library @@ -48,7 +48,7 @@ control-source: ``` c csource = gst_interpolation_control_source_new (); g_object_set (csource, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL); - + ``` Now we need to attach the control-source to the gobject property. This @@ -58,7 +58,7 @@ control-bindings. ``` c gst_object_add_control_binding (object, gst_direct_control_binding_new (object, "prop1", csource)); - + ``` This type control-source takes new property values from a list of @@ -81,7 +81,7 @@ well. GstTimedValueControlSource *tv_csource = (GstTimedValueControlSource *)csource; gst_timed_value_control_source_set (tv_csource, 0 * GST_SECOND, 0.0); gst_timed_value_control_source_set (tv_csource, 1 * GST_SECOND, 1.0); - + ``` Now everything is ready to play. If the control-source is e.g. bound to @@ -99,4 +99,3 @@ this remains active until the next programmed control-source value overrides it. This also works with smoothed parameters. It does not work for control-sources that constantly update the property (e.g. the lfo\_control\_source). - diff --git a/manual-advanced.md b/markdown/manual/advanced/index.md similarity index 99% rename from manual-advanced.md rename to markdown/manual/advanced/index.md index ee7db5f..96c165b 100644 --- a/manual-advanced.md +++ b/markdown/manual/advanced/index.md @@ -18,4 +18,3 @@ however, discuss more advanced ways of pipeline-application interaction, and can turn out to be very useful for certain applications. This includes the chapters on metadata, querying and events, interfaces, dynamic parameters and pipeline data manipulation. - diff --git a/manual-interfaces.md b/markdown/manual/advanced/interfaces.md similarity index 97% rename from manual-interfaces.md rename to markdown/manual/advanced/interfaces.md index 75fb642..5ef74c4 100644 --- a/manual-interfaces.md +++ b/markdown/manual/advanced/interfaces.md @@ -5,7 +5,7 @@ title: Interfaces # Interfaces In [Using an element as a -GObject](manual-elements.md#using-an-element-as-a-gobject), you have +GObject](manual/building/elements.md#using-an-element-as-a-gobject), you have learned how to use `GObject` properties as a simple way to do interaction between applications and elements. This method suffices for the simple'n'straight settings, but fails for anything more complicated @@ -61,4 +61,3 @@ video in video players. This interface is implemented by, amongst others, the Video4linux2 elements and by ximagesink, xvimagesink and sdlvideosink. - diff --git a/manual-metadata.md b/markdown/manual/advanced/metadata.md similarity index 97% rename from manual-metadata.md rename to markdown/manual/advanced/metadata.md index aab66b8..486e423 100644 --- a/manual-metadata.md +++ b/markdown/manual/advanced/metadata.md @@ -18,12 +18,12 @@ using the GStreamer tagging system. Stream-info can be retrieved from a Stream information can most easily be read by reading it from a `GstPad`. This has already been discussed before in [Using capabilities -for metadata](manual-pads.md#using-capabilities-for-metadata). +for metadata](manual/building/pads.md#using-capabilities-for-metadata). Therefore, we will skip it here. Note that this requires access to all pads of which you want stream information. Tag reading is done through a bus in GStreamer, which has been discussed -previously in [Bus](manual-bus.md). You can listen for +previously in [Bus](manual/building/bus.md). You can listen for `GST_MESSAGE_TAG` messages and handle them as you wish. Note, however, that the `GST_MESSAGE_TAG` message may be fired multiple @@ -159,7 +159,7 @@ main (int argc, char ** argv) g_free (uri); return 0; } - + ``` ## Tag writing @@ -180,4 +180,3 @@ in pipelines. This means that if you transcode one file containing tags into another media type, and that new media type supports tags too, then the tags will be handled as part of the data stream and be merged into the newly written media file, too. - diff --git a/manual-queryevents.md b/markdown/manual/advanced/queryevents.md similarity index 99% rename from manual-queryevents.md rename to markdown/manual/advanced/queryevents.md index 8dbabc3..d6ff450 100644 --- a/manual-queryevents.md +++ b/markdown/manual/advanced/queryevents.md @@ -69,7 +69,7 @@ main (gint argc, [..] } - + ``` ## Events: seeking (and more) @@ -102,7 +102,7 @@ seek_to_time (GstElement *pipeline, g_print ("Seek failed!\n"); } } - + ``` Seeks with the GST\_SEEK\_FLAG\_FLUSH should be done when the pipeline @@ -135,4 +135,3 @@ onwards and this will continue until all sinks have data again. If it was playing originally, it will be set to playing again, too. Since the new position is immediately available in a video output, you will see the new frame, even if your pipeline is not in the playing state. - diff --git a/manual-threads.md b/markdown/manual/advanced/threads.md similarity index 99% rename from manual-threads.md rename to markdown/manual/advanced/threads.md index a123102..3b897ef 100644 --- a/manual-threads.md +++ b/markdown/manual/advanced/threads.md @@ -45,7 +45,7 @@ from the message: possible to configure a `GstTaskPool` in the `GstTask`. The custom taskpool will provide custom threads for the task to implement the streaming threads. - + This message needs to be handled synchronously if you want to configure a custom taskpool. If you don't configure the taskpool on the task when this message returns, the task will use its default @@ -63,12 +63,12 @@ We will now look at some examples in the next sections. ### Boost priority of a thread -``` +``` .----------. .----------. | faksesrc | | fakesink | | src->sink | '----------' '----------' - + ``` Let's look at the simple pipeline above. We would like to boost the @@ -192,7 +192,7 @@ test_rt_pool_new (void) } - + ``` The important function to implement when writing an taskpool is the @@ -267,7 +267,7 @@ main (int argc, char *argv[]) GstElement *bin, *fakesrc, *fakesink; GstBus *bus; GstStateChangeReturn ret; - + gst_init (&argc, &argv); /* create a new bin to hold the elements */ @@ -322,7 +322,7 @@ main (int argc, char *argv[]) } - + ``` c Note that this program likely needs root permissions in order to create @@ -350,16 +350,16 @@ situations where threads can be particularly useful: when recording data from a live stream such as a video or audio card. Short hickups elsewhere in the pipeline will not cause data loss. See also [Stream - buffering](manual-buffering.md#stream-buffering) about network + buffering](manual/advanced/buffering.md#stream-buffering) about network buffering with queue2. - + ![Data buffering, from a networked source](images/thread-buffering.png "fig:") - Synchronizing output devices, e.g. when playing a stream containing both video and audio data. By using threads for both outputs, they will run independently and their synchronization will be better. - + ![Synchronizing audio and video sinks](images/thread-synchronizing.png "fig:") @@ -379,4 +379,3 @@ To use a queue (and therefore force the use of two distinct threads in the pipeline), one can simply create a “queue” element and put this in as part of the pipeline. GStreamer will take care of all threading details internally. - diff --git a/manual-checklist-element.md b/markdown/manual/appendix/checklist-element.md similarity index 99% rename from manual-checklist-element.md rename to markdown/manual/appendix/checklist-element.md index efb21a5..3f29190 100644 --- a/manual-checklist-element.md +++ b/markdown/manual/appendix/checklist-element.md @@ -106,7 +106,7 @@ help in application development. We will discuss only `gst-launch` and `gst-launch` is a simple script-like commandline application that can be used to test pipelines. For example, the command `gst-launch -audiotestsrc ! audioconvert ! +audiotestsrc ! audioconvert ! audio/x-raw,channels=2 ! alsasink` will run a pipeline which generates a sine-wave audio stream and plays it to your ALSA audio card. `gst-launch` also allows the use of threads (will be used automatically @@ -129,4 +129,3 @@ useful to see which `GObject` properties or which signals (and using what arguments) an element supports. Run `gst-inspect fakesrc` to get an idea of what it does. See the manual page of `gst-inspect` for more information. - diff --git a/manual-compiling.md b/markdown/manual/appendix/compiling.md similarity index 99% rename from manual-compiling.md rename to markdown/manual/appendix/compiling.md index a9451f0..c01f245 100644 --- a/manual-compiling.md +++ b/markdown/manual/appendix/compiling.md @@ -65,6 +65,5 @@ my_code_init (void) ... } - -``` +``` diff --git a/manual-appendices.md b/markdown/manual/appendix/index.md similarity index 99% rename from manual-appendices.md rename to markdown/manual/appendix/index.md index ebb44ae..0b5ea22 100644 --- a/manual-appendices.md +++ b/markdown/manual/appendix/index.md @@ -15,4 +15,3 @@ information on debugging. In addition, we also provide a porting guide which will explain easily how to port GStreamer-0.10 applications to GStreamer-1.0. - diff --git a/manual-integration.md b/markdown/manual/appendix/integration.md similarity index 99% rename from manual-integration.md rename to markdown/manual/appendix/integration.md index b7960b3..416900f 100644 --- a/manual-integration.md +++ b/markdown/manual/appendix/integration.md @@ -62,7 +62,7 @@ integrate as closely as possible with the GNOME desktop: * the GOption section in the GLib API reference for a more elaborate * example of how to add your own command line options here */ - /* at the end we have a special option that collects all remaining + /* at the end we have a special option that collects all remaining * command line arguments (like filenames) for us. If you don't * need this, you can safely remove it */ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &cmd_filenames, @@ -154,7 +154,7 @@ builds using the standard development tools for OS X. ## Windows > **Warning** -> +> > Note: this section is out of date. GStreamer-1.0 has much better > support for win32 than previous versions though and should usually > compile and work out-of-the-box both using MSYS/MinGW or Microsoft @@ -199,18 +199,18 @@ list](http://news.gmane.org/gmane.comp.video.gstreamer.devel) for the latest developments in this respect. > **Note** -> +> > GNU tools needed that you can find on > -> +> > - GNU flex (tested with 2.5.4) -> +> > - GNU bison (tested with 1.35) -> +> > and -> +> > - GNU make (tested with 3.80) -> +> > the generated files from the -auto makefiles will be available soon > separately on the net for convenience (people who don't want to > install GNU tools). @@ -218,4 +218,3 @@ latest developments in this respect. ### Installation on the system FIXME: This section needs be updated for GStreamer-1.0. - diff --git a/manual-licensing.md b/markdown/manual/appendix/licensing.md similarity index 99% rename from manual-licensing.md rename to markdown/manual/appendix/licensing.md index 1066fc6..e36a455 100644 --- a/manual-licensing.md +++ b/markdown/manual/appendix/licensing.md @@ -90,4 +90,3 @@ unethical, they ask your help to give them a legal reason to do so. This advisory is part of a bigger advisory with a FAQ which you can find on the [GStreamer website](http://gstreamer.freedesktop.org/documentation/licensing.html) - diff --git a/manual-porting-1.0.md b/markdown/manual/appendix/porting-1.0.md similarity index 99% rename from manual-porting-1.0.md rename to markdown/manual/appendix/porting-1.0.md index 58710b7..9f06825 100644 --- a/manual-porting-1.0.md +++ b/markdown/manual/appendix/porting-1.0.md @@ -41,7 +41,7 @@ less than a day. interface, so most applications can just remove the sync bus handler where they would set the window ID, and instead just set the window ID on playbin from the application thread before starting playback. - + playbin also proxies the GstColorBalance and GstNavigation interfaces, so applications that use this don't need to go fishing for elements that may implement those any more, but can just use on @@ -69,7 +69,7 @@ less than a day. - The GstXOverlay interface was renamed to GstVideoOverlay, and now part of the video library in gst-plugins-base, as the interfaces library no longer exists. - + The name of the GstXOverlay "prepare-xwindow-id" message has changed to "prepare-window-handle" (and GstXOverlay has been renamed to GstVideoOverlay). Code that checks for the string directly should be @@ -86,11 +86,11 @@ less than a day. - gst\_uri\_handler\_get\_uri() and the get\_uri vfunc now return a copy of the URI string - + gst\_uri\_handler\_set\_uri() and the set\_uri vfunc now take an additional GError argument so the handler can notify the caller why it didn't accept a particular URI. - + gst\_uri\_handler\_set\_uri() now checks if the protocol of the URI passed is one of the protocols advertised by the uri handler, so set\_uri vfunc implementations no longer need to check that as well. @@ -100,12 +100,12 @@ less than a day. required because of missing taglist API) to cast a GstTagList to a GstStructure or use gst\_structure\_\* API on taglists, you can no longer do that. Doing so will cause crashes. - + Also, tag lists are refcounted now, and can therefore not be freely modified any longer. Make sure to call gst\_tag\_list\_make\_writable (taglist) before adding, removing or changing tags in the taglist. - + GST\_TAG\_IMAGE, GST\_TAG\_PREVIEW\_IMAGE, GST\_TAG\_ATTACHMENT: many tags that used to be of type GstBuffer are now of type GstSample (which is basically a struct containing a buffer alongside @@ -118,9 +118,8 @@ less than a day. change is that control sources generate a sequence of gdouble values and those are mapped to the property type and value range by GstControlBindings. - + The whole gst\_controller\_\* API is gone and now available in simplified form under gst\_object\_\*. ControlSources are now attached via GstControlBinding to properties. There are no GValue arguments used anymore when programming control sources. - diff --git a/manual-porting.md b/markdown/manual/appendix/porting.md similarity index 95% rename from manual-porting.md rename to markdown/manual/appendix/porting.md index 2371464..b978641 100644 --- a/manual-porting.md +++ b/markdown/manual/appendix/porting.md @@ -28,7 +28,7 @@ applications to GStreamer-0.10 in less than a day. - Applications should no longer use signal handlers to be notified of errors, end-of-stream and other similar pipeline events. Instead, they should use the `GstBus`, which has been discussed in - [Bus](manual-bus.md). The bus will take care that the messages will + [Bus](manual/building/bus.md). The bus will take care that the messages will be delivered in the context of a main loop, which is almost certainly the application's main thread. The big advantage of this is that applications no longer need to be thread-aware; they don't @@ -63,7 +63,7 @@ applications to GStreamer-0.10 in less than a day. pipelines, and the pipeline will do the dispatching internally for you. This means less bookkeeping in your application. For a short code example, see [Position tracking and - seeking](manual-queryevents.md). Related, seeking is now + seeking](manual/advanced/queryevents.md). Related, seeking is now threadsafe, and your video output will show the new video position's frame while seeking, providing a better user experience. @@ -72,7 +72,7 @@ applications to GStreamer-0.10 in less than a day. between for buffering, and GStreamer will take care of creating threads internally. It is still possible to have parts of a pipeline run in different threads than others, by using the “queue” element. - See [Threads](manual-threads.md) for details. + See [Threads](manual/advanced/threads.md) for details. - Filtered caps -\> capsfilter element (the pipeline syntax for gst-launch has not changed though). @@ -88,4 +88,3 @@ applications to GStreamer-0.10 in less than a day. GOption command line option API that was added to GLib 2.6. `gst_init_get_option_group ()` is the new GOption-based equivalent to `gst_init_get_ptop_table ()`. - diff --git a/manual-programs.md b/markdown/manual/appendix/programs.md similarity index 97% rename from manual-programs.md rename to markdown/manual/appendix/programs.md index d33da3a..17d3b89 100644 --- a/manual-programs.md +++ b/markdown/manual/appendix/programs.md @@ -11,18 +11,18 @@ syntax. A simple commandline looks like: -``` +``` gst-launch filesrc location=hello.mp3 ! mad ! audioresample ! osssink - + ``` A more complex pipeline looks like: -``` +``` gst-launch filesrc location=redpill.vob ! dvddemux name=demux \ demux.audio_00 ! queue ! a52dec ! audioconvert ! audioresample ! osssink \ demux.video_00 ! queue ! mpeg2dec ! videoconvert ! xvimagesink - + ``` You can also use the parser in you own code. GStreamer provides a @@ -54,7 +54,7 @@ main (int argc, char *argv[]) g_print ("Parse error: %s\n", error->message); exit (1); } - + filesrc = gst_bin_get_by_name (GST_BIN (pipeline), "my_filesrc"); g_object_set (filesrc, "location", argv[1], NULL); g_object_unref (filesrc); @@ -100,7 +100,7 @@ main (int argc, char *argv[]) return 0; } - + ``` Note how we can retrieve the filesrc element from the constructed bin @@ -114,9 +114,9 @@ deviations from this specification is considered a bug. #### Elements -``` +``` ... mad ... - + ``` A bare identifier (a string beginning with a letter and containing only @@ -126,9 +126,9 @@ instance of the "mad" MP3 decoding plugin will be created. #### Links -``` +``` ... !sink ... - + ``` An exclamation point, optionally having a qualified pad name (an the @@ -142,9 +142,9 @@ pads. Pad names may be preceded by an element name, as in #### Properties -``` +``` ... location="http://gstreamer.net" ... - + ``` The name of a property, optionally qualified with an element name, and a @@ -163,9 +163,9 @@ limitations in the value convert API. #### Bins, Threads, and Pipelines -``` +``` ( ... ) - + ``` A pipeline description between parentheses is placed into a bin. The @@ -181,14 +181,14 @@ This is a tool to query a plugin or an element about its properties. To query the information about the element mad, you would specify: -``` +``` gst-inspect mad - + ``` Below is the output of a query for the osssink element: -``` +``` Factory Details: Rank: secondary (128) @@ -267,7 +267,7 @@ Element Properties: Boolean. Default: true max-lateness : Maximum number of nanoseconds that a buffer can be late before it is dropped (-1 unlimited) flags: readable, writable - Integer64. Range: -1 - 9223372036854775807 Default: -1 + Integer64. Range: -1 - 9223372036854775807 Default: -1 qos : Generate Quality-of-Service events upstream flags: readable, writable Boolean. Default: false @@ -276,7 +276,7 @@ Element Properties: Boolean. Default: true ts-offset : Timestamp offset in nanoseconds flags: readable, writable - Integer64. Range: -9223372036854775808 - 9223372036854775807 Default: 0 + Integer64. Range: -9223372036854775808 - 9223372036854775807 Default: 0 enable-last-sample : Enable the last-sample property flags: readable, writable Boolean. Default: false @@ -285,19 +285,19 @@ Element Properties: Boxed pointer of type "GstSample" blocksize : Size in bytes to pull per buffer (0 = default) flags: readable, writable - Unsigned Integer. Range: 0 - 4294967295 Default: 4096 + Unsigned Integer. Range: 0 - 4294967295 Default: 4096 render-delay : Additional render delay of the sink in nanoseconds flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 + Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 throttle-time : The time to keep between rendered buffers flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 + Unsigned Integer64. Range: 0 - 18446744073709551615 Default: 0 buffer-time : Size of audio buffer in microseconds, this is the minimum latency that the sink reports flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 200000 + Integer64. Range: 1 - 9223372036854775807 Default: 200000 latency-time : The minimum amount of data to write in each iteration in microseconds flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 10000 + Integer64. Range: 1 - 9223372036854775807 Default: 10000 provide-clock : Provide a clock to be used as the global pipeline clock flags: readable, writable Boolean. Default: true @@ -312,24 +312,23 @@ Element Properties: Boolean. Default: false alignment-threshold : Timestamp alignment threshold in nanoseconds flags: readable, writable - Unsigned Integer64. Range: 1 - 18446744073709551614 Default: 40000000 + Unsigned Integer64. Range: 1 - 18446744073709551614 Default: 40000000 drift-tolerance : Tolerance for clock drift in microseconds flags: readable, writable - Integer64. Range: 1 - 9223372036854775807 Default: 40000 + Integer64. Range: 1 - 9223372036854775807 Default: 40000 discont-wait : Window of time in nanoseconds to wait before creating a discontinuity flags: readable, writable - Unsigned Integer64. Range: 0 - 18446744073709551614 Default: 1000000000 + Unsigned Integer64. Range: 0 - 18446744073709551614 Default: 1000000000 device : OSS device (usually /dev/dspN) flags: readable, writable String. Default: "/dev/dsp" - + ``` To query the information about a plugin, you would do: -``` -gst-inspect gstelements - ``` +gst-inspect gstelements +``` diff --git a/manual-quotes.md b/markdown/manual/appendix/quotes.md similarity index 88% rename from manual-quotes.md rename to markdown/manual/appendix/quotes.md index f185c18..620bebc 100644 --- a/manual-quotes.md +++ b/markdown/manual/appendix/quotes.md @@ -10,7 +10,7 @@ contributing. We often hang out on the \#gstreamer IRC channel on irc.freenode.net: the following are a selection of amusing\[1\] quotes from our conversations. - - 6 Mar 2006 + - 6 Mar 2006 When I opened my eyes I was in a court room. There were masters McIlroy and Thompson sitting in the jury and master Kernighan too. There were the GStreamer developers standing in the defendant's @@ -18,184 +18,183 @@ from our conversations. customer lock-down via running on a proprietary pipeline, different from that of the Unix systems. I heard Eric Raymond whispering "got to add this case to my book. - + *behdad's blog* - - 22 May 2007 + - 22 May 2007 *\<\_\_tim\>* Uraeus: amusing, isn't it? - + *\* \_\_tim: I wrote that :) - + *\<\_\_tim\>* Uraeus: of course you did; your refusal to surrender to the oppressive regime of the third-person-singular-rule is so unique in its persistence that it's hard to miss :) - - 12 Sep 2005 + - 12 Sep 2005 *\* we just need to get rid of that mmap stuff - + *\* i think gnomevfssrc is faster for files even - + *\* wingo, no - + *\* and no - + *\* good points ronald - - 23 Jun 2005 + - 23 Jun 2005 *\* wingo* back - + *\* thomasvs* back - + \--- You are now known as everybody - + *\* everybody* back back - + *\* now break it down - + \--- You are now known as thomasvs - + *\* bilboed* back - + \--- bilboed is now known as john-sebastian - + *\* john-sebastian* bach - + \--- john-sebastian is now known as bilboed - + \--- You are now known as scratch\_my - + *\* scratch\_my* back - + \--- bilboed is now known as Illbe - + \--- You are now known as thomasvs - + *\* Illbe* back - + \--- Illbe is now known as bilboed - - 20 Apr 2005 + - 20 Apr 2005 *thomas*: jrb, somehow his screenshotsrc grabs whatever X is showing and makes it available as a stream of frames - + *jrb*: thomas: so, is the point that the screenshooter takes a video? but won't the dialog be in the video? oh, nevermind. I'll just send mail... - + *thomas*: jrb, well, it would shoot first and ask questions later - - 2 Nov 2004 + - 2 Nov 2004 *zaheerm*: wtay: unfair u fixed the bug i was using as a feature\! - - 14 Oct 2004 + - 14 Oct 2004 *\* zaheerm* wonders how he can break gstreamer today :) - + *ensonic*: zaheerm, spider is always a good starting point - - 14 Jun 2004 + - 14 Jun 2004 *teuf*: ok, things work much better when I don't write incredibly stupid and buggy code - + *thaytan*: I find that too - - 23 Nov 2003 + - 23 Nov 2003 *Uraeus*: ah yes, the sleeping part, my mind is not multitasking so I was still thinking about exercise - + *dolphy*: Uraeus: your mind is multitasking - + *dolphy*: Uraeus: you just miss low latency patches - - 14 Sep 2002 + - 14 Sep 2002 \--- *wingo-party* is now known as *wingo* - + \* *wingo* holds head - - 4 Jun 2001 + - 4 Jun 2001 *taaz:* you witchdoctors and your voodoo mpeg2 black magic... - + *omega\_:* um. I count three, no four different cults there \ - + *ajmitch:* hehe - + *omega\_:* witchdoctors, voodoo, black magic, - + *omega\_:* and mpeg - - 16 Feb 2001 + - 16 Feb 2001 *wtay:* I shipped a few commerical products to \>40000 people now but GStreamer is way more exciting... - - 16 Feb 2001 + - 16 Feb 2001 \* *tool-man* is a gstreamer groupie - - 14 Jan 2001 + - 14 Jan 2001 *Omega:* did you run ldconfig? maybe it talks to init? - + *wtay:* not sure, don't think so... I did run gstreamer-register though :-) - + *Omega:* ah, that did it then ;-) - + *wtay:* right - + *Omega:* probably not, but in case GStreamer starts turning into an OS, someone please let me know? - - 9 Jan 2001 + - 9 Jan 2001 *wtay:* me tar, you rpm? - + *wtay:* hehe, forgot "zan" - + *Omega:* ? - + *wtay:* me tar"zan", you ... - - 7 Jan 2001 + - 7 Jan 2001 *Omega:* that means probably building an agreggating, cache-massaging queue to shove N buffers across all at once, forcing cache transfer. - + *wtay:* never done that before... - + *Omega:* nope, but it's easy to do in gstreamer \ - + *wtay:* sure, I need to rewrite cp with gstreamer too, someday :-) - - 7 Jan 2001 + - 7 Jan 2001 *wtay:* GStreamer; always at least one developer is awake... - - 5/6 Jan 2001 + - 5/6 Jan 2001 *wtay:* we need to cut down the time to create an mp3 player down to seconds... - + *richardb:* :) - + *Omega:* I'm wanting to something more interesting soon, I did the "draw an mp3 player in 15sec" back in October '99. - + *wtay:* by the time Omega gets his hands on the editor, you'll see a complete audio mixer in the editor :-) - + *richardb:* Well, it clearly has the potential... - + *Omega:* Working on it... ;-) - - 28 Dec 2000 + - 28 Dec 2000 *MPAA:* We will sue you now, you have violated our IP rights\! - + *wtay:* hehehe - + *MPAA:* How dare you laugh at us? We have lawyers\! We have Congressmen\! We have *LARS*\! - + *wtay:* I'm so sorry your honor - + *MPAA:* Hrumph. - + \* *wtay* bows before thy 1. No guarantee of sense of humour compatibility is given. - diff --git a/manual-bins.md b/markdown/manual/building/bins.md similarity index 98% rename from manual-bins.md rename to markdown/manual/building/bins.md index bf44397..1e9aeea 100644 --- a/manual-bins.md +++ b/markdown/manual/building/bins.md @@ -7,7 +7,7 @@ title: Bins A bin is a container element. You can add elements to a bin. Since a bin is an element itself, a bin can be handled in the same way as any other element. Therefore, the whole previous chapter -([Elements](manual-elements.md)) applies to bins as well. +([Elements](manual/building/elements.md)) applies to bins as well. ## What are bins @@ -42,7 +42,7 @@ take ownership of that element. If you destroy the bin, the element will be dereferenced with it. If you remove an element from a bin, it will be dereferenced automatically. -``` +``` #include int @@ -71,7 +71,7 @@ main (int argc, [..] } - + ``` There are various functions to lookup elements in a bin. The most @@ -87,7 +87,7 @@ The application programmer can create custom bins packed with elements to perform a specific task. This allows you, for example, to write an Ogg/Vorbis decoder with just the following lines of code: -``` +``` int main (int argc, char *argv[]) @@ -107,7 +107,7 @@ main (int argc, gst_element_set_state (GST_ELEMENT (player), GST_STATE_PLAYING); [..] } - + ``` (This is a silly example of course, there already exists a much more @@ -145,4 +145,3 @@ or target state of the bin or pipeline it was added to. Instead, you have to need to set it to the desired target state yourself using `gst_element_set_state ()` or `gst_element_sync_state_with_parent ()` when adding elements to an already-running pipeline. - diff --git a/manual-bus.md b/markdown/manual/building/bus.md similarity index 98% rename from manual-bus.md rename to markdown/manual/building/bus.md index 6eb7fad..8141d8c 100644 --- a/manual-bus.md +++ b/markdown/manual/building/bus.md @@ -25,10 +25,10 @@ There are two different ways to use a bus: yourself regularly) and attach some kind of watch to the bus. This way the GLib main loop will check the bus for new messages and notify you whenever there are messages. - + Typically you would use `gst_bus_add_watch ()` or `gst_bus_add_signal_watch ()` in this case. - + To use a bus, attach a message handler to the bus of a pipeline using `gst_bus_add_watch ()`. This handler will be called whenever the pipeline emits a message to the bus. In this handler, check the @@ -40,7 +40,7 @@ There are two different ways to use a bus: `gst_bus_peek ()` and/or `gst_bus_poll ()`. -{{ examples/bus_example.c }} +{{ bus_example.c }} It is important to know that the handler will be called in the thread context of the mainloop. This means that the interaction between the @@ -74,7 +74,7 @@ g_signal_connect (bus, "message::error", G_CALLBACK (cb_message_error), NULL); g_signal_connect (bus, "message::eos", G_CALLBACK (cb_message_eos), NULL); [..] - + ``` If you aren't using GLib mainloop, the asynchronous message signals @@ -135,7 +135,7 @@ of what they do and how to parse message-specific content. manually extract the progress (in percent) from the message by extracting the “buffer-percent” property from the structure returned by `gst_message_get_structure - ()`. See also [Buffering](manual-buffering.md). + ()`. See also [Buffering](manual/advanced/buffering.md). - Element messages: these are special messages that are unique to certain elements and usually represent additional features. The @@ -147,10 +147,9 @@ of what they do and how to parse message-specific content. - Application-specific messages: any information on those can be extracted by getting the message structure (see above) and reading its fields. Usually these messages can safely be ignored. - + Application messages are primarily meant for internal use in applications in case the application needs to marshal information from some thread into the main thread. This is particularly useful when the application is making use of element signals (as those signals will be emitted in the context of the streaming thread). - diff --git a/manual-data.md b/markdown/manual/building/data.md similarity index 99% rename from manual-data.md rename to markdown/manual/building/data.md index 5844979..0d0f9ac 100644 --- a/manual-data.md +++ b/markdown/manual/building/data.md @@ -71,9 +71,8 @@ seek_to_time (GstElement *element, GST_SEEK_TYPE_NONE, G_GUINT64_CONSTANT (0)); gst_element_send_event (element, event); } - + ``` The function `gst_element_seek ()` is a shortcut for this. This is mostly just to show how it all works. - diff --git a/manual-elements.md b/markdown/manual/building/elements.md similarity index 98% rename from manual-elements.md rename to markdown/manual/building/elements.md index 7f733ff..e6c82c5 100644 --- a/manual-elements.md +++ b/markdown/manual/building/elements.md @@ -19,7 +19,7 @@ boxes. On the one end, you might put something in, the element does something with it and something else comes out at the other side. For a decoder element, for example, you'd put in encoded data, and the element would output decoded data. In the next chapter (see [Pads and -capabilities](manual-pads.md)), you will learn more about data input +capabilities](manual/building/pads.md)), you will learn more about data input and output in elements, and how you can set that up in your application. ### Source elements @@ -91,7 +91,7 @@ used in debug output. You can pass `NULL` as the name argument to get a unique, default name. When you don't need the element anymore, you need to unref it using -[`gst_object_unref +[`gst_object_unref ()`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstObject.html#gst-object-unref). This decreases the reference count for the element by 1. An element has a refcount of 1 when it gets created. An element gets destroyed @@ -124,7 +124,7 @@ main (int argc, return 0; } - + ``` `gst_element_factory_make` is actually a shorthand for a combination of @@ -172,7 +172,7 @@ main (int argc, return 0; } - + ``` ## Using an element as a `GObject` @@ -215,7 +215,7 @@ main (int argc, return 0; } - + ``` Most plugins provide additional properties to provide more information @@ -223,7 +223,7 @@ about their configuration or to configure the element. `gst-inspect` is a useful tool to query the properties of a particular element, it will also use property introspection to give a short explanation about the function of the property and about the parameter types and ranges it -supports. See [gst-inspect](manual-checklist-element.md#gst-inspect) in +supports. See [gst-inspect](manual/appendix/checklist-element.md#gst-inspect) in the appendix for details about `gst-inspect`. For more information about `GObject` properties we recommend you read @@ -292,7 +292,7 @@ main (int argc, return 0; } - + ``` You can use `gst_registry_pool_feature_list (GST_TYPE_ELEMENT_FACTORY)` @@ -309,7 +309,7 @@ for encoders, or it can be used for autoplugging purposes for media players. All current GStreamer-based media players and autopluggers work this way. We'll look closer at these features as we learn about `GstPad` and `GstCaps` in the next chapter: [Pads and -capabilities](manual-pads.md) +capabilities](manual/building/pads.md) ## Linking elements @@ -367,7 +367,7 @@ main (int argc, [..] } - + ``` For more specific behaviour, there are also the functions @@ -380,7 +380,7 @@ them, since adding an element to a bin will disconnect any already existing links. Also, you cannot directly link elements that are not in the same bin or pipeline; if you want to link elements or pads at different hierarchy levels, you will need to use ghost pads (more about -ghost pads later, see [Ghost pads](manual-pads.md#ghost-pads)). +ghost pads later, see [Ghost pads](manual/building/pads.md#ghost-pads)). ## Element States @@ -408,7 +408,7 @@ Those four states are: playback as soon as state is changed to PLAYING, but it is *not* allowed to play the data which would make the clock run. In summary, PAUSED is the same as PLAYING but without a running clock. - + Elements going into the PAUSED state should prepare themselves for moving over to the PLAYING state as soon as possible. Video or audio outputs would, for example, wait for data to arrive and queue it so @@ -434,7 +434,7 @@ GStreamer will start threads that take this task on to them. GStreamer will also take care of switching messages from the pipeline's thread into the application's own thread, by using a [`GstBus`](http://gstreamer.freedesktop.org/data/doc/gstreamer/stable/gstreamer/html/GstBus.html). -See [Bus](manual-bus.md) for details. +See [Bus](manual/building/bus.md) for details. When you set a bin or pipeline to a certain target state, it will usually propagate the state change to all elements within the bin or @@ -448,4 +448,3 @@ set it to the desired target state yourself using `gst_element_set_state 1. The code for this example is automatically extracted from the documentation and built under `tests/examples/manual` in the GStreamer tarball. - diff --git a/manual-helloworld.md b/markdown/manual/building/helloworld.md similarity index 95% rename from manual-helloworld.md rename to markdown/manual/building/helloworld.md index b41bf6b..fe0eb76 100644 --- a/manual-helloworld.md +++ b/markdown/manual/building/helloworld.md @@ -17,7 +17,7 @@ command-line audio player. For this, we will use only standard GStreamer components. The player will read a file specified on the command-line. Let's get started\! -We've learned, in [Initializing GStreamer](manual-init.md), that the +We've learned, in [Initializing GStreamer](manual/building/init.md), that the first thing to do in your application is to initialize GStreamer by calling `gst_init ()`. Also, make sure that the application includes `gst/gst.h` so all function names and objects are properly defined. Use @@ -34,7 +34,7 @@ audio) and is called “oggdemux”. The second is a Vorbis audio decoder, it's conveniently called “vorbisdec”. Since “oggdemux” creates dynamic pads for each elementary stream, you'll need to set a “pad-added” event handler on the “oggdemux” element, like you've learned in [Dynamic (or -sometimes) pads](manual-pads.md#dynamic-or-sometimes-pads), to link the +sometimes) pads](manual/building/pads.md#dynamic-or-sometimes-pads), to link the Ogg demuxer and the Vorbis decoder elements together. At last, we'll also need an audio output element, we will use “autoaudiosink”, which automatically detects your audio device. @@ -42,8 +42,8 @@ automatically detects your audio device. The last thing left to do is to add all elements into a container element, a `GstPipeline`, and wait until we've played the whole song. We've previously learned how to add elements to a container bin in -[Bins](manual-bins.md), and we've learned about element states in -[Element States](manual-elements.md#element-states). We will also +[Bins](manual/building/bins.md), and we've learned about element states in +[Element States](manual/building/elements.md#element-states). We will also attach a message handler to the pipeline bus so we can retrieve errors and detect the end-of-stream. @@ -197,7 +197,7 @@ main (int argc, return 0; } - + ``` We now have created a complete pipeline. We can visualise the pipeline @@ -233,7 +233,7 @@ This concludes our first example. As you see, setting up a pipeline is very low-level but powerful. You will see later in this manual how you can create a more powerful media player with even less effort using higher-level interfaces. We will discuss all that in [Higher-level -interfaces for GStreamer applications](manual-highlevel.md). We will +interfaces for GStreamer applications](manual/advanced/index.md). We will first, however, go more in-depth into more advanced GStreamer internals. It should be clear from the example that we can very easily replace the @@ -246,4 +246,3 @@ you can instead use a filesink to write audio files to disk instead of playing them back. By using an audio card source, you can even do audio capture instead of playback. All this shows the reusability of GStreamer elements, which is its greatest advantage. - diff --git a/manual-building.md b/markdown/manual/building/index.md similarity index 99% rename from manual-building.md rename to markdown/manual/building/index.md index 0266838..924a580 100644 --- a/manual-building.md +++ b/markdown/manual/building/index.md @@ -15,4 +15,3 @@ build a basic command-line application. Note that this part will give a look into the low-level API and concepts of GStreamer. Once you're going to build applications, you might want to use higher-level APIs. Those will be discussed later on in this manual. - diff --git a/manual-init.md b/markdown/manual/building/init.md similarity index 99% rename from manual-init.md rename to markdown/manual/building/init.md index 14a3b5c..7ab2ea6 100644 --- a/manual-init.md +++ b/markdown/manual/building/init.md @@ -47,7 +47,7 @@ main (int argc, return 0; } - + ``` Use the `GST_VERSION_MAJOR`, `GST_VERSION_MINOR` and `GST_VERSION_MICRO` @@ -101,7 +101,7 @@ main (int argc, return 0; } - + ``` As shown in this fragment, you can use a @@ -115,4 +115,3 @@ options. 1. The code for this example is automatically extracted from the documentation and built under `tests/examples/manual` in the GStreamer tarball. - diff --git a/manual-pads.md b/markdown/manual/building/pads.md similarity index 97% rename from manual-pads.md rename to markdown/manual/building/pads.md index 401b81a..9c249a6 100644 --- a/manual-pads.md +++ b/markdown/manual/building/pads.md @@ -4,7 +4,7 @@ title: Pads and capabilities # Pads and capabilities -As we have seen in [Elements](manual-elements.md), the pads are the +As we have seen in [Elements](manual/building/elements.md), the pads are the element's interface to the outside world. Data streams from one element's source pad to another element's sink pad. The specific type of media that the element can handle will be exposed by the pad's @@ -68,9 +68,9 @@ cb_new_pad (GstElement *element, } -int +int main (int argc, - char *argv[]) + char *argv[]) { GstElement *pipeline, *source, *demux; GMainLoop *loop; @@ -101,7 +101,7 @@ main (int argc, [..] } - + ``` It is not uncommon to add elements to the pipeline only from within the @@ -123,7 +123,7 @@ the stream, it can simply request a new output pad from the tee element. The following piece of code shows how you can request a new output pad from a “tee” element: -{{ examples/snippets.c#some_function }} +{{ snippets.c#some_function }} The `gst_element_get_request_pad ()` method can be used to get a pad from the element based on the name of the pad template. It is also @@ -134,7 +134,7 @@ element and you need to request a pad that is compatible. The method pad, as shown in the next example. It will request a compatible pad from an Ogg multiplexer from any input. -{{ examples/snippets.c#link_to_multiplexer }} +{{ snippets.c#link_to_multiplexer }} ## Capabilities of a pad @@ -177,7 +177,7 @@ case, “audio/x-raw”). The source pad will also contain properties for the audio samplerate and the amount of channels, plus some more that you don't need to worry about for now. -``` +``` Pad Templates: SRC template: 'src' @@ -192,7 +192,7 @@ Pad Templates: Availability: Always Capabilities: audio/x-vorbis - + ``` ### Properties and values @@ -204,19 +204,19 @@ possible value types that can be used: - Basic types, this can be pretty much any `GType` registered with Glib. Those properties indicate a specific, non-dynamic value for this property. Examples include: - + - An integer value (`G_TYPE_INT`): the property has this exact value. - + - A boolean value (`G_TYPE_BOOLEAN`): the property is either TRUE or FALSE. - + - A float value (`G_TYPE_FLOAT`): the property has this exact floating point value. - + - A string value (`G_TYPE_STRING`): the property contains a UTF-8 string. - + - A fraction value (`GST_TYPE_FRACTION`): contains a fraction expressed by an integer numerator and denominator. @@ -224,23 +224,23 @@ possible value types that can be used: of possible values. They are used for indicating allowed audio samplerate values or supported video sizes. The two types defined in GStreamer are: - + - An integer range value (`GST_TYPE_INT_RANGE`): the property denotes a range of possible integers, with a lower and an upper boundary. The “vorbisdec” element, for example, has a rate property that can be between 8000 and 50000. - + - A float range value (`GST_TYPE_FLOAT_RANGE`): the property denotes a range of possible floating point values, with a lower and an upper boundary. - + - A fraction range value (`GST_TYPE_FRACTION_RANGE`): the property denotes a range of possible fraction values, with a lower and an upper boundary. - A list value (`GST_TYPE_LIST`): the property can take any value from a list of basic values given in this list. - + Example: caps that express that either a sample rate of 44100 Hz and a sample rate of 48000 Hz is supported would use a list of integer values, with one value being 44100 and one value being 48000. @@ -252,7 +252,7 @@ possible value types that can be used: of integers, integer ranges together, and the same for floats or strings, but it can not contain both floats and ints at the same time. - + Example: for audio where there are more than two channels involved the channel layout needs to be specified (for one and two channel audio the channel layout is implicit unless stated otherwise in the @@ -287,7 +287,7 @@ very useful for various purposes: that should stream between two pads. You will see an example of filtered caps later in this manual, in [Manually adding or removing data from/to a - pipeline](manual-dataaccess.md#manually-adding-or-removing-data-fromto-a-pipeline). + pipeline](manual/advanced/dataaccess.md#manually-adding-or-removing-data-fromto-a-pipeline). You can do caps filtering by inserting a capsfilter element into your pipeline and setting its “caps” property. Caps filters are often placed after converter elements like audioconvert, @@ -344,7 +344,7 @@ read_video_props (GstCaps *caps) g_print ("The video size of this set of capabilities is %dx%d\n", width, height); } - + ``` ### Creating capabilities for filtering @@ -382,7 +382,7 @@ link_elements_with_filter (GstElement *element1, GstElement *element2) return link_ok; } - + ``` This will force the data flow between those two elements to a certain @@ -405,7 +405,7 @@ link_elements_with_filter (GstElement *element1, GstElement *element2) { gboolean link_ok; GstCaps *caps; - + caps = gst_caps_new_full ( gst_structure_new ("video/x-raw", "width", G_TYPE_INT, 384, @@ -428,7 +428,7 @@ link_elements_with_filter (GstElement *element1, GstElement *element2) return link_ok; } - + ``` See the API references for the full API of @@ -490,7 +490,7 @@ main (int argc, [..] } - + ``` In the above example, the bin now also has a pad: the pad called “sink” @@ -502,4 +502,3 @@ the bin. to the sink pad of an element upstream (to the left of this element in drawings). Data will, however, always flow from a source pad of one element to the sink pad of another. - diff --git a/manual-highlevel.md b/markdown/manual/highlevel/index.md similarity index 99% rename from manual-highlevel.md rename to markdown/manual/highlevel/index.md index d02eb2e..1b0b5b9 100644 --- a/manual-highlevel.md +++ b/markdown/manual/highlevel/index.md @@ -14,4 +14,3 @@ elements and other such things. Those higher-level interfaces are intended to simplify GStreamer-based application programming. They do, however, also reduce the flexibility. It is up to the application developer to choose which interface he will want to use. - diff --git a/manual-playback-components.md b/markdown/manual/highlevel/playback-components.md similarity index 97% rename from manual-playback-components.md rename to markdown/manual/highlevel/playback-components.md index e19cba8..c7b1796 100644 --- a/manual-playback-components.md +++ b/markdown/manual/highlevel/playback-components.md @@ -10,7 +10,7 @@ now) are targetted at media playback. The idea of each of these components is to integrate as closely as possible with a GStreamer pipeline, but to hide the complexity of media type detection and several other rather complex topics that have been discussed in [Advanced -GStreamer concepts](manual-advanced.md). +GStreamer concepts](manual/advanced/index.md). We currently recommend people to use either playbin (see [Playbin](#playbin)) or decodebin (see [Decodebin](#decodebin)), @@ -80,7 +80,7 @@ main (gint argc, return 0; } - + ``` Playbin has several features that have been discussed previously: @@ -220,7 +220,7 @@ main (gint argc, return 0; } - + ``` Decodebin, similar to playbin, supports the following features: @@ -255,7 +255,7 @@ given. Uridecodebin will also automatically insert buffering elements when the uri is a slow network source. The buffering element will post BUFFERING messages that the application needs to handle as explained in -[Buffering](manual-buffering.md). The following properties can be used +[Buffering](manual/advanced/buffering.md). The following properties can be used to configure the buffering method: - The buffer-size property allows you to configure a maximum size in @@ -267,7 +267,7 @@ to configure the buffering method: - With the download property you can enable the download buffering method as described in [Download - buffering](manual-buffering.md#download-buffering). Setting this + buffering](manual/advanced/buffering.md#download-buffering). Setting this option to TRUE will only enable download buffering for selected formats such as quicktime, flash video, avi and webm. @@ -390,7 +390,7 @@ main (gint argc, /* create audio output */ sink = gst_element_factory_make ("playsink", "sink"); - gst_util_set_object_arg (G_OBJECT (sink), "flags", + gst_util_set_object_arg (G_OBJECT (sink), "flags", "soft-colorbalance+soft-volume+vis+text+audio+video"); gst_bin_add_many (GST_BIN (pipeline), dec, sink, NULL); @@ -406,11 +406,10 @@ main (gint argc, } - + ``` This example will show audio and video depending on what you give it. Try this example on an audio file and you will see that it shows visualizations. You can change the visualization at runtime by changing the vis-plugin property. - diff --git a/manual-index.md b/markdown/manual/index.md similarity index 88% rename from manual-index.md rename to markdown/manual/index.md index 2b5ad5e..eb1f924 100644 --- a/manual-index.md +++ b/markdown/manual/index.md @@ -27,7 +27,7 @@ but also at other forms of media processing (capture, editing, etc.). This book is about GStreamer from an application developer's point of view; it describes how to write a GStreamer application using the GStreamer libraries and tools. For an explanation about writing plugins, -we suggest the [Plugin Writers Guide](pwg-index.md). +we suggest the [Plugin Writers Guide](pwg/index.md). Also check out the other documentation available on the [GStreamer web site](http://gstreamer.freedesktop.org/documentation/). @@ -64,14 +64,14 @@ large parts. Each part addresses a particular broad topic concerning GStreamer appliction development. The parts of this guide are laid out in the following order: -[About GStreamer](manual-introduction.md) gives you an overview of +[About GStreamer](manual/introduction/index.md) gives you an overview of GStreamer, it's design principles and foundations. -[Building an Application](manual-building.md) covers the basics of +[Building an Application](manual/building/index.md) covers the basics of GStreamer application programming. At the end of this part, you should be able to build your own audio player using GStreamer -In [Advanced GStreamer concepts](manual-advanced.md), we will move on to +In [Advanced GStreamer concepts](manual/advanced/index.md), we will move on to advanced subjects which make GStreamer stand out of its competitors. We will discuss application-pipeline interaction using dynamic parameters and interfaces, we will discuss threading and threaded pipelines, @@ -81,14 +81,13 @@ deeper insight in solving application programming problems with GStreamer and understanding their concepts. Next, in [Higher-level interfaces for GStreamer -applications](manual-highlevel.md), we will go into higher-level +applications](manual/advanced/index.md), we will go into higher-level programming APIs for GStreamer. You don't exactly need to know all the details from the previous parts to understand this, but you will need to understand basic GStreamer concepts nevertheless. We will, amongst others, discuss XML, playbin and autopluggers. -Finally in [Appendices](manual-appendices.md), you will find some random +Finally in [Appendices](manual/appendix/index.md), you will find some random information on integrating with GNOME, KDE, OS X or Windows, some debugging help and general tips to improve and simplify GStreamer programming. - diff --git a/manual-intro-basics.md b/markdown/manual/introduction/basics.md similarity index 99% rename from manual-intro-basics.md rename to markdown/manual/introduction/basics.md index 0b69002..e3a3ffe 100644 --- a/manual-intro-basics.md +++ b/markdown/manual/introduction/basics.md @@ -106,4 +106,3 @@ exchange between the *application* and the *pipeline*. ![GStreamer pipeline with different communication flows](images/communication.png "fig:") - diff --git a/manual-gstreamer.md b/markdown/manual/introduction/gstreamer.md similarity index 99% rename from manual-gstreamer.md rename to markdown/manual/introduction/gstreamer.md index 3e51284..3d485a5 100644 --- a/manual-gstreamer.md +++ b/markdown/manual/introduction/gstreamer.md @@ -85,4 +85,3 @@ GStreamer is packaged into encoding - a few others packages - diff --git a/manual-introduction.md b/markdown/manual/introduction/index.md similarity index 99% rename from manual-introduction.md rename to markdown/manual/introduction/index.md index 9bb6a19..70c0af6 100644 --- a/manual-introduction.md +++ b/markdown/manual/introduction/index.md @@ -6,4 +6,3 @@ title: About GStreamer This part gives you an overview of the technologies described in this book. - diff --git a/manual-motivation.md b/markdown/manual/introduction/motivation.md similarity index 99% rename from manual-motivation.md rename to markdown/manual/introduction/motivation.md index bc2a676..21db1c4 100644 --- a/manual-motivation.md +++ b/markdown/manual/introduction/motivation.md @@ -92,4 +92,3 @@ GStreamer also wants to be an easy framework where codec developers can experiment with different algorithms, speeding up the development of open and free multimedia codecs like those developed by the [Xiph.Org Foundation](http://www.xiph.org) (such as Theora and Vorbis). - diff --git a/pwg-allocation.md b/markdown/pwg/advanced/allocation.md similarity index 99% rename from pwg-allocation.md rename to markdown/pwg/advanced/allocation.md index b59b786..5190139 100644 --- a/pwg-allocation.md +++ b/markdown/pwg/advanced/allocation.md @@ -80,7 +80,7 @@ Below is an example of making a `GstMemory` object and using the [...] - + ``` ### Implementing a GstAllocator @@ -165,7 +165,7 @@ Below is an example of how to create a buffer and access its memory. [...] - + ``` ## GstMeta @@ -212,7 +212,7 @@ region for video frames. meta->height = 80; [...] - + ``` An element can then use the metadata on the buffer when rendering the @@ -238,7 +238,7 @@ frame like this: [...] - + ``` ### Implementing new GstMeta @@ -280,7 +280,7 @@ GType my_example_meta_api_get_type (void); #define gst_buffer_get_my_example_meta(b) \ ((MyExampleMeta*)gst_buffer_get_meta((b),MY_EXAMPLE_META_API_TYPE)) - + ``` The metadata API definition consists of the definition of the structure @@ -312,7 +312,7 @@ my_example_meta_api_get_type (void) return type; } - + ``` As you can see, it simply uses the `gst_meta_api_type_register ()` @@ -341,7 +341,7 @@ MyExampleMeta * gst_buffer_add_my_example_meta (GstBuffer *buffer, gint age, const gchar *name); - + ``` Let's have a look at how these functions are implemented in the @@ -418,7 +418,7 @@ gst_buffer_add_my_example_meta (GstBuffer *buffer, return meta; } - + ``` `gst_meta_register ()` registers the implementation details, like the @@ -486,7 +486,7 @@ is not configured will fail. [...] - + ``` The configuration of the bufferpool is maintained in a generic @@ -539,7 +539,7 @@ buffer from the pool, like this: [...] - + ``` It is important to check the return value of the acquire function @@ -639,7 +639,7 @@ Below is an example of the ALLOCATION query. [...] - + ``` This particular implementation will make a custom `GstVideoBufferPool` @@ -661,4 +661,3 @@ influencing the allocation strategy: Implementors of these methods should modify the given `GstQuery` object by updating the pool options and allocation options. - diff --git a/pwg-building-types.md b/markdown/pwg/advanced/building-types.md similarity index 99% rename from pwg-building-types.md rename to markdown/pwg/advanced/building-types.md index 6d6a86e..bd4c863 100644 --- a/pwg-building-types.md +++ b/markdown/pwg/advanced/building-types.md @@ -105,7 +105,7 @@ plugin_init (GstPlugin *plugin) NULL), NULL)) return FALSE; } - + ``` Note that `gst-plugins/gst/typefind/gsttypefindfunctions.c` has some @@ -580,4 +580,3 @@ stream. - diff --git a/pwg-advanced-clock.md b/markdown/pwg/advanced/clock.md similarity index 99% rename from pwg-advanced-clock.md rename to markdown/pwg/advanced/clock.md index d03c699..b20d4b6 100644 --- a/pwg-advanced-clock.md +++ b/markdown/pwg/advanced/clock.md @@ -118,4 +118,3 @@ played exactly when the pipeline clock reaches that running-time + latency. Some elements might use the clock API such as `gst_clock_id_wait()` to perform this action. Other sinks might need to use other means of scheduling timely playback of the data. - diff --git a/pwg-dparams.md b/markdown/pwg/advanced/dparams.md similarity index 99% rename from pwg-dparams.md rename to markdown/pwg/advanced/dparams.md index f3412d0..29bf7ea 100644 --- a/pwg-dparams.md +++ b/markdown/pwg/advanced/dparams.md @@ -22,7 +22,7 @@ library. You need to include the header in your element's source file: #include #include ... - + ``` Even though the `gstcontroller` library may be linked into the host @@ -38,7 +38,7 @@ application, you should make sure it is initialized in your gst_controller_init (NULL, NULL); ... } - + ``` It makes no sense for all GObject parameter to be real-time controlled. @@ -51,7 +51,7 @@ GObject params in the `_class_init` method. g_param_spec_double ("freq", "Frequency", "Frequency of test signal", 0.0, 20000.0, 440.0, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); - + ``` ## The Data Processing Loop @@ -64,7 +64,7 @@ one action: ``` c gst_object_sync_values(element,timestamp); - + ``` This call makes all parameter-changes for the given timestamp active by @@ -90,4 +90,3 @@ makes the control-rate depend on the buffer size. Elements that need a specific control-rate need to break their data processing loop to synchronise every n-samples. - diff --git a/pwg-advanced-events.md b/markdown/pwg/advanced/events.md similarity index 98% rename from pwg-advanced-events.md rename to markdown/pwg/advanced/events.md index 9f1d528..3db3f5c 100644 --- a/pwg-advanced-events.md +++ b/markdown/pwg/advanced/events.md @@ -51,7 +51,7 @@ gst_my_filter_sink_event (GstPad *pad, GstObject * parent, GstEvent * event) case GST_EVENT_FLUSH_STOP: gst_my_filter_clear_temporary_buffers (filter); ret = gst_pad_push_event (filter->src_pad, event); - break; + break; default: ret = gst_pad_event_default (pad, parent, event); break; @@ -60,7 +60,7 @@ gst_my_filter_sink_event (GstPad *pad, GstObject * parent, GstEvent * event) ... return ret; } - + ``` If your element is chain-based, you will almost always have to implement @@ -172,7 +172,7 @@ WRITEME ### Caps The CAPS event contains the format description of the following buffers. -See [Caps negotiation](pwg-negotiation.md) for more information +See [Caps negotiation](pwg/advanced/negotiation.md) for more information about negotiation. ### Segment @@ -215,7 +215,7 @@ Tagging events are being sent downstream to indicate the tags as parsed from the stream data. This is currently used to preserve tags during stream transcoding from one format to the other. Tags are discussed extensively in [Tagging (Metadata and -Streaminfo)](pwg-advanced-tagging.md). Most elements will simply +Streaminfo)](pwg/advanced/tagging.md). Most elements will simply forward the event by calling `gst_pad_event_default ()`. The tag event is created using the function `gst_event_new_tag ()`, but @@ -307,7 +307,7 @@ running\_time is set back to 0. The QOS event contains a report about the current real-time performance of the stream. See more info in [Quality Of Service -(QoS)](pwg-advanced-qos.md). +(QoS)](pwg/advanced/qos.md). ### Seek Request @@ -346,4 +346,3 @@ obtained with `gst_event_get_structure ()`. Check out the navigationtest element in gst-plugins-good for an idea how to extract navigation information from this event. - diff --git a/pwg-advanced.md b/markdown/pwg/advanced/index.md similarity index 99% rename from pwg-advanced.md rename to markdown/pwg/advanced/index.md index c38349b..c01251a 100644 --- a/pwg-advanced.md +++ b/markdown/pwg/advanced/index.md @@ -10,4 +10,3 @@ for. But GStreamer can do much more than only this\! In this chapter, various advanced topics will be discussed, such as scheduling, special pad types, clocking, events, interfaces, tagging and more. These topics are the sugar that makes GStreamer so easy to use for applications. - diff --git a/pwg-advanced-interfaces.md b/markdown/pwg/advanced/interfaces.md similarity index 97% rename from pwg-advanced-interfaces.md rename to markdown/pwg/advanced/interfaces.md index 55a1111..b6ddfe6 100644 --- a/pwg-advanced-interfaces.md +++ b/markdown/pwg/advanced/interfaces.md @@ -5,7 +5,7 @@ title: Interfaces # Interfaces Previously, in the chapter [Adding -Properties](pwg-building-args.md), we have introduced the concept of +Properties](pwg/building/args.md), we have introduced the concept of GObject properties of controlling an element's behaviour. This is very powerful, but it has two big disadvantages: first of all, it is too generic, and second, it isn't dynamic. @@ -62,7 +62,7 @@ GType gst_my_filter_get_type (void) { static GType my_filter_type = 0; - + if (!my_filter_type) { static const GTypeInfo my_filter_info = { sizeof (GstMyFilterClass), @@ -98,7 +98,7 @@ gst_my_filter_some_interface_init (GstSomeInterface *iface) { /* here, you would set virtual function pointers in the interface */ } - + ``` Or more @@ -111,7 +111,7 @@ G_DEFINE_TYPE_WITH_CODE (GstMyFilter, gst_my_filter,GST_TYPE_ELEMENT, G_IMPLEMENT_INTERFACE (GST_TYPE_SOME_INTERFACE, gst_my_filter_some_interface_init)); - + ``` ## URI interface @@ -166,7 +166,7 @@ gst_my_filter_set_window_handle (GstVideoOverlay *overlay, guintptr handle) if (my_filter->window) gst_my_filter_destroy_window (my_filter->window); - + my_filter->window = handle; } @@ -175,7 +175,7 @@ gst_my_filter_xoverlay_init (GstVideoOverlayClass *iface) { iface->set_window_handle = gst_my_filter_set_window_handle; } - + ``` You will also need to use the interface methods to post messages when @@ -203,16 +203,15 @@ gst_my_filter_sink_set_caps (GstMyFilter *my_filter, GstCaps *caps) if (!ret) return FALSE; gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (my_filter)); - + if (!my_filter->window) my_filter->window = gst_my_filter_create_window (my_filter, width, height); ... } - + ``` ## Navigation Interface WRITEME - diff --git a/pwg-negotiation.md b/markdown/pwg/advanced/negotiation.md similarity index 99% rename from pwg-negotiation.md rename to markdown/pwg/advanced/negotiation.md index dc3ae33..b4e55cd 100644 --- a/pwg-negotiation.md +++ b/markdown/pwg/advanced/negotiation.md @@ -99,7 +99,7 @@ are the relevant code snippets for fixed caps source pads. gst_pad_use_fixed_caps (pad); [..] - + ``` The fixed caps can then be set on the pad by calling `gst_pad_set_caps @@ -119,7 +119,7 @@ The fixed caps can then be set on the pad by calling `gst_pad_set_caps } [..] - + ``` These types of elements also don't have a relation between the input @@ -217,7 +217,7 @@ gst_my_filter_sink_event (GstPad *pad, [...] - + ``` ### Dynamic negotiation @@ -345,7 +345,7 @@ gst_my_filter_chain (GstPad *pad, return gst_pad_push (filter->srcpad, out); } - + ``` ## Upstream caps (re)negotiation @@ -458,7 +458,7 @@ gst_my_filter_query (GstPad *pad, GstObject * parent, GstQuery * query) return ret; } - + ``` ## Pull-mode Caps negotiation @@ -470,4 +470,3 @@ Using all the knowledge you've acquired by reading this chapter, you should be able to write an element that does correct caps negotiation. If in doubt, look at other elements of the same type in our git repository to get an idea of how they do what you want to do. - diff --git a/pwg-advanced-qos.md b/markdown/pwg/advanced/qos.md similarity index 99% rename from pwg-advanced-qos.md rename to markdown/pwg/advanced/qos.md index 3c2e068..0e524e0 100644 --- a/pwg-advanced-qos.md +++ b/markdown/pwg/advanced/qos.md @@ -25,7 +25,7 @@ one or more upstream elements. Two types of adjustments can be made: - Short time "emergency" corrections based on latest observation in the sinks. - + Long term rate corrections based on trends observed in the sinks. It is also possible for the application to artificially introduce delay @@ -96,7 +96,7 @@ the example below. Also make sure to pass the QoS event upstream. [...] - + ``` With the QoS values, there are two types of corrections that an element @@ -142,7 +142,7 @@ A possible algorithm typically looks like this: [...] - + ``` ### Long term correction @@ -209,4 +209,3 @@ conditions: (quality). This could include a decoder that decides to drop every B frame to increase its processing speed or an effect element switching to a lower quality algorithm. - diff --git a/pwg-advanced-request.md b/markdown/pwg/advanced/request.md similarity index 99% rename from pwg-advanced-request.md rename to markdown/pwg/advanced/request.md index e383629..1bf779c 100644 --- a/pwg-advanced-request.md +++ b/markdown/pwg/advanced/request.md @@ -33,13 +33,13 @@ The example code below will parse a text file, where the first line is a number (n). The next lines all start with a number (0 to n-1), which is the number of the source pad over which the data should be sent. -``` +``` 3 0: foo 1: bar 0: boo 2: bye - + ``` The code to parse this file and create the dynamic “sometimes” pads, @@ -190,7 +190,7 @@ gst_my_filter_loopfunc (GstElement *element) gst_buffer_unref (buf); } - + ``` Note that we use a lot of checks everywhere to make sure that the @@ -279,6 +279,5 @@ gst_my_filter_release_pad (GstElement *element, } - -``` +``` diff --git a/pwg-scheduling.md b/markdown/pwg/advanced/scheduling.md similarity index 99% rename from pwg-scheduling.md rename to markdown/pwg/advanced/scheduling.md index 9ac7299..336954b 100644 --- a/pwg-scheduling.md +++ b/markdown/pwg/advanced/scheduling.md @@ -61,7 +61,7 @@ use-cases. What follows is an overview of some typical use-cases. data flow in the pipeline. Prerequisites for this mode are that all downstream elements can act in push mode, and that all upstream elements operate in pull-mode (see below). - + Source pads can be activated in PULL mode by a downstream element when they return GST\_PAD\_MODE\_PULL from the GST\_QUERY\_SCHEDULING query. Prerequisites for this scheduling mode @@ -78,7 +78,7 @@ use-cases. What follows is an overview of some typical use-cases. `gst_pad_set_getrange_function ()`. Also, if the element has any sinkpads, all those pads (and thereby their peers) need to operate in PULL access mode, too. - + When a sink element is activated in PULL mode, it should start a task that calls `gst_pad_pull_range ()` on its sinkpad. It can only do this when the upstream SCHEDULING query returns support for the @@ -204,7 +204,7 @@ gst_my_filter_activate_pull (GstPad * pad, } return res; } - + ``` Once started, your task has full control over input and output. The most @@ -215,7 +215,7 @@ far. ``` c #define BLOCKSIZE 2048 - + static void gst_my_filter_loop (GstMyFilter * filter) { @@ -223,41 +223,41 @@ far. guint64 len; GstFormat fmt = GST_FORMAT_BYTES; GstBuffer *buf = NULL; - + if (!gst_pad_query_duration (filter->sinkpad, fmt, &len)) { GST_DEBUG_OBJECT (filter, "failed to query duration, pausing"); goto stop; } - + if (filter->offset >= len) { GST_DEBUG_OBJECT (filter, "at end of input, sending EOS, pausing"); gst_pad_push_event (filter->srcpad, gst_event_new_eos ()); goto stop; } - + /* now, read BLOCKSIZE bytes from byte offset filter->offset */ ret = gst_pad_pull_range (filter->sinkpad, filter->offset, BLOCKSIZE, &buf); - + if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (filter, "pull_range failed: %s", gst_flow_get_name (ret)); goto stop; } - + /* now push buffer downstream */ ret = gst_pad_push (filter->srcpad, buf); - + buf = NULL; /* gst_pad_push() took ownership of buffer */ - + if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (filter, "pad_push failed: %s", gst_flow_get_name (ret)); goto stop; } - + /* everything is fine, increase offset and wait for us to be called again */ filter->offset += BLOCKSIZE; return; - + stop: GST_DEBUG_OBJECT (filter, "pausing task"); gst_pad_pause_task (filter->sinkpad); @@ -298,23 +298,23 @@ The following example will show how a `_get_range guint64 offset, guint length, GstBuffer ** buf); - + G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); - - - + + + static void gst_my_filter_init (GstMyFilter * filter) { - + [..] - + gst_pad_set_getrange_function (filter->srcpad, gst_my_filter_get_range); - + [..] } - + static GstFlowReturn gst_my_filter_get_range (GstPad * pad, GstObject * parent, @@ -322,11 +322,11 @@ The following example will show how a `_get_range guint length, GstBuffer ** buf) { - + GstMyFilter *filter = GST_MY_FILTER (parent); - + [.. here, you would fill *buf ..] - + return GST_FLOW_OK; } @@ -338,4 +338,3 @@ practice, those elements should implement both a `_get_range ()`-function (for filters and parsers) or a `_get_range ()`-function and be prepared to start their own task by providing `_activate_* ()`-functions (for source elements). - diff --git a/pwg-advanced-tagging.md b/markdown/pwg/advanced/tagging.md similarity index 99% rename from pwg-advanced-tagging.md rename to markdown/pwg/advanced/tagging.md index 121e0e4..79b7bf0 100644 --- a/pwg-advanced-tagging.md +++ b/markdown/pwg/advanced/tagging.md @@ -85,7 +85,7 @@ gst_my_filter_class_init (GstMyFilterClass *klass) [..] } - + ``` ## Writing Tags to Streams @@ -218,11 +218,10 @@ gst_my_filter_task_func (GstElement *element) gst_pad_push (filter->srcpad, gst_event_new (GST_EVENT_EOS)); } - + ``` Note that normally, elements would not read the full stream before processing tags. Rather, they would read from each sinkpad until they've received data (since tags usually come in before the first data buffer) and process that. - diff --git a/pwg-checklist-element.md b/markdown/pwg/appendix/checklist-element.md similarity index 98% rename from pwg-checklist-element.md rename to markdown/pwg/appendix/checklist-element.md index dd0ef82..e6504a5 100644 --- a/pwg-checklist-element.md +++ b/markdown/pwg/appendix/checklist-element.md @@ -43,13 +43,13 @@ we will try to explain why those requirements are set. - Ideally, elements should use their own debugging category. Most elements use the following code to do that: - + ``` c GST_DEBUG_CATEGORY_STATIC (myelement_debug); #define GST_CAT_DEFAULT myelement_debug - + [..] - + static void gst_myelement_class_init (GstMyelementClass *klass) { @@ -57,21 +57,21 @@ we will try to explain why those requirements are set. GST_DEBUG_CATEGORY_INIT (myelement_debug, "myelement", 0, "My own element"); } - + ``` - + At runtime, you can turn on debugging using the commandline option `--gst-debug=myelement:5`. - Elements should use GST\_DEBUG\_FUNCPTR when setting pad functions or overriding element class methods, for example: - + ``` c gst_pad_set_event_func (myelement->srcpad, GST_DEBUG_FUNCPTR (my_element_src_event)); - + ``` - + This makes debug output much easier to read later on. - Elements that are aimed for inclusion into one of the GStreamer @@ -124,4 +124,3 @@ we will try to explain why those requirements are set. - Sources and sinks should be prepared to be assigned another clock then the one they expose themselves. Always use the provided clock for synchronization, else you'll get A/V sync issues. - diff --git a/pwg-appendix.md b/markdown/pwg/appendix/index.md similarity index 99% rename from pwg-appendix.md rename to markdown/pwg/appendix/index.md index 22513c5..b61b502 100644 --- a/pwg-appendix.md +++ b/markdown/pwg/appendix/index.md @@ -5,4 +5,3 @@ title: Appendices # Appendices This chapter contains things that don't belong anywhere else. - diff --git a/pwg-licensing-advisory.md b/markdown/pwg/appendix/licensing-advisory.md similarity index 99% rename from pwg-licensing-advisory.md rename to markdown/pwg/appendix/licensing-advisory.md index aa599cf..f726e01 100644 --- a/pwg-licensing-advisory.md +++ b/markdown/pwg/appendix/licensing-advisory.md @@ -35,4 +35,3 @@ unintentionally violating the GPL license of said plugins. This advisory is part of a bigger advisory with a FAQ which you can find on the [GStreamer website](http://gstreamer.freedesktop.org/documentation/licensing.html) - diff --git a/pwg-porting-1_0.md b/markdown/pwg/appendix/porting-1_0.md similarity index 99% rename from pwg-porting-1_0.md rename to markdown/pwg/appendix/porting-1_0.md index e23e6c2..a377015 100644 --- a/pwg-porting-1_0.md +++ b/markdown/pwg/appendix/porting-1_0.md @@ -7,4 +7,3 @@ title: Porting 0.10 plug-ins to 1.0 You can find the list of changes in the [Porting to 1.0](http://cgit.freedesktop.org/gstreamer/gstreamer/tree/docs/random/porting-to-1.0.txt) document. - diff --git a/pwg-porting.md b/markdown/pwg/appendix/porting.md similarity index 95% rename from pwg-porting.md rename to markdown/pwg/appendix/porting.md index fd38396..a7c9686 100644 --- a/pwg-porting.md +++ b/markdown/pwg/appendix/porting.md @@ -26,7 +26,7 @@ also need a rewrite, which will take about the same amount of time. - In 0.10, buffers have caps attached to them. Elements should allocate new buffers with `gst_pad_alloc_buffer ()`. See [Caps - negotiation](pwg-negotiation.md) for more details. + negotiation](pwg/advanced/negotiation.md) for more details. - Most functions returning an object or an object property have been changed to return its own reference rather than a constant reference @@ -46,21 +46,21 @@ also need a rewrite, which will take about the same amount of time. some more work. Pads get assigned a scheduling mode, based on which they can either operate in random access-mode, in pipeline driving mode or in push-mode. all this is documented in detail in [Different - scheduling modes](pwg-scheduling.md). As a result of this, the + scheduling modes](pwg/advanced/scheduling.md). As a result of this, the bytestream object no longer exists. Elements requiring byte-level access should now use random access on their sinkpads. - Negotiation is asynchronous. This means that downstream negotiation is done as data comes in and upstream negotiation is done whenever renegotiation is required. All details are described in [Caps - negotiation](pwg-negotiation.md). + negotiation](pwg/advanced/negotiation.md). - For as far as possible, elements should try to use existing base classes in 0.10. Sink and source elements, for example, could derive from `GstBaseSrc` and `GstBaseSink`. Audio sinks or sources could even derive from audio-specific base classes. All existing base classes have been discussed in [Pre-made base - classes](pwg-other-base.md) and the next few chapters. + classes](pwg/other/base.md) and the next few chapters. - In 0.10, event handling and buffers are separated once again. This means that in order to receive events, one no longer has to set the @@ -88,7 +88,7 @@ also need a rewrite, which will take about the same amount of time. need to be able to accept and process data already in the `GST_STATE_PAUSED` state now (i.e. when prerolling the pipeline). More details can be found in [What are - states?](pwg-statemanage-states.md). + states?](pwg/building/statemanage-states.md). - If your plugin's state change function hasn't been superseded by virtual start() and stop() methods of one of the new base classes, @@ -99,7 +99,7 @@ also need a rewrite, which will take about the same amount of time. class (usually GstElementClass in these cases), and only then handle downwards state changes. See the vorbis decoder plugin in gst-plugins-base for an example. - + The reason for this is that in the case of downwards state changes you don't want to destroy allocated resources while your plugin's chain function (for example) is still accessing those resources in @@ -109,7 +109,7 @@ also need a rewrite, which will take about the same amount of time. handled in the GstElement class's state change function, including proper locking, that's why it is essential to chain up before destroying allocated resources. - + As already mentioned above, you should really rewrite your plugin to derive from one of the new base classes though, so you don't have to worry about these things, as the base class will handle it for you. @@ -125,11 +125,10 @@ also need a rewrite, which will take about the same amount of time. nowadays, which sets a function that is called when the format streaming over a pad changes (so similar to `_set_link_function ()` in GStreamer-0.8). - + If the element is derived from a `GstBase` class, then override the `set_caps ()`. - `gst_pad_use_explicit_caps ()` has been replaced by `gst_pad_use_fixed_caps ()`. You can then set the fixed caps to use on a pad with `gst_pad_set_caps ()`. - diff --git a/pwg-building-args.md b/markdown/pwg/building/args.md similarity index 98% rename from pwg-building-args.md rename to markdown/pwg/building/args.md index a92bed1..d153f75 100644 --- a/pwg-building-args.md +++ b/markdown/pwg/building/args.md @@ -79,7 +79,7 @@ gst_my_filter_get_property (GObject *object, GParamSpec *pspec) { GstMyFilter *filter = GST_MY_FILTER (object); - + switch (prop_id) { case PROP_SILENT: g_value_set_boolean (value, filter->silent); @@ -149,6 +149,5 @@ gst_videotestsrc_class_init (GstvideotestsrcClass *klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); [..] } - -``` +``` diff --git a/pwg-building-boiler.md b/markdown/pwg/building/boiler.md similarity index 98% rename from pwg-building-boiler.md rename to markdown/pwg/building/boiler.md index 808c5db..5dab3bb 100644 --- a/pwg-building-boiler.md +++ b/markdown/pwg/building/boiler.md @@ -27,7 +27,7 @@ are connected to the internet, and type the following commands at a command console: -``` +``` shell $ git clone git://anongit.freedesktop.org/gstreamer/gst-template.git Initialized empty Git repository in /some/path/gst-template/.git/ remote: Counting objects: 373, done. @@ -35,7 +35,7 @@ remote: Compressing objects: 100% (114/114), done. remote: Total 373 (delta 240), reused 373 (delta 240) Receiving objects: 100% (373/373), 75.16 KiB | 78 KiB/s, done. Resolving deltas: 100% (240/240), done. - + ``` This command will check out a series of files and directories into @@ -77,14 +77,14 @@ For example, the following commands create the MyFilter plugin based on the plugin template and put the output files in the `gst-template/gst-plugin/src` directory: -``` +``` shell $ cd gst-template/gst-plugin/src shell $ ../tools/make_element MyFilter - + ``` > **Note** -> +> > Capitalization is important for the name of the plugin. Keep in mind > that under some operating systems, capitalization is also important > when specifying directory and file names in general. @@ -92,7 +92,7 @@ shell $ ../tools/make_element MyFilter The last command creates two files: `gstmyfilter.c` and `gstmyfilter.h`. > **Note** -> +> > It is recommended that you create a copy of the `gst-plugin` directory > before continuing. @@ -102,7 +102,7 @@ environment. After that, the project can be built and installed using the well known `make && sudo make install` commands. > **Note** -> +> > Be aware that by default `autogen.sh` and `configure` would choose > `/usr/local` as a default location. One would need to add > `/usr/local/lib/gstreamer-1.0` to `GST_PLUGIN_PATH` in order to make @@ -110,7 +110,7 @@ the well known `make && sudo make install` commands. > packages. > **Note** -> +> > FIXME: this section is slightly outdated. gst-template is still useful > as an example for a minimal plugin build system skeleton. However, for > creating elements the tool gst-element-maker from gst-plugins-bad is @@ -156,7 +156,7 @@ typedef struct _GstMyFilterClass { /* Standard function returning type information. */ GType gst_my_filter_get_type (void); - + ``` Using this header file, you can use the following macro to setup the @@ -167,7 +167,7 @@ called appropriately: #include "filter.h" G_DEFINE_TYPE (GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT); - + ``` ## Element metadata @@ -195,7 +195,7 @@ gst_element_class_set_static_metadata (klass, "Example/FirstExample", "Shows the basic structure of a plugin", "your name "); - + ``` The element details are registered with the plugin during the @@ -217,7 +217,7 @@ gst_my_filter_class_init (GstMyFilterClass * klass) "your name "); } - + ``` ## GstStaticPadTemplate @@ -247,7 +247,7 @@ GST_STATIC_PAD_TEMPLATE ( ); - + ``` Those pad templates are registered during the `_class_init ()` function @@ -260,17 +260,17 @@ Pads are created from these static templates in the element's `_init ()` function using `gst_pad_new_from_static_template ()`. In order to create a new pad from this template using `gst_pad_new_from_static_template ()`, you will need to declare the pad template as a global variable. -More on this subject in [Specifying the pads](pwg-building-pads.md). +More on this subject in [Specifying the pads](pwg/building/pads.md). static GstStaticPadTemplate sink_factory = [..], src_factory = [..]; - + static void gst_my_filter_class_init (GstMyFilterClass * klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); [..] - + gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); gst_element_class_add_pad_template (element_class, @@ -302,7 +302,7 @@ GST_STATIC_PAD_TEMPLATE ( ) ); - + ``` Values surrounded by curly brackets (“{” and “}”) are lists, values @@ -310,7 +310,7 @@ surrounded by square brackets (“\[” and “\]”) are ranges. Multiple sets of types are supported too, and should be separated by a semicolon (“;”). Later, in the chapter on pads, we will see how to use types to know the exact format of a stream: [Specifying the -pads](pwg-building-pads.md). +pads](pwg/building/pads.md). ## Constructor Functions @@ -353,7 +353,7 @@ GST_PLUGIN_DEFINE ( ) - + ``` Note that the information returned by the plugin\_init() function will @@ -365,4 +365,3 @@ soundcard is not being used by some other process) this must be reflected by the element being unable to enter the READY state if unavailable, rather than the plugin attempting to deny existence of the plugin. - diff --git a/pwg-building-chainfn.md b/markdown/pwg/building/chainfn.md similarity index 98% rename from pwg-building-chainfn.md rename to markdown/pwg/building/chainfn.md index 9252aa5..33db7f6 100644 --- a/pwg-building-chainfn.md +++ b/markdown/pwg/building/chainfn.md @@ -60,16 +60,16 @@ newsegment, tags, etc.). gst_my_filter_sink_event); [..] } - - - + + + static gboolean gst_my_filter_sink_event (GstPad *pad, GstObject *parent, GstEvent *event) { GstMyFilter *filter = GST_MY_FILTER (parent); - + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: /* we should handle the format here */ @@ -81,10 +81,10 @@ newsegment, tags, etc.). default: break; } - + return gst_pad_event_default (pad, parent, event); } - + static GstFlowReturn gst_my_filter_chain (GstPad *pad, GstObject *parent, @@ -92,7 +92,7 @@ newsegment, tags, etc.). { GstMyFilter *filter = GST_MY_FILTER (parent); GstBuffer *outbuf; - + outbuf = gst_my_filter_process_data (filter, buf); gst_buffer_unref (buf); if (!outbuf) { @@ -100,7 +100,7 @@ newsegment, tags, etc.). GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL)); return GST_FLOW_ERROR; } - + return gst_pad_push (filter->srcpad, outbuf); } @@ -110,4 +110,3 @@ so-called *loop-based* element. Source elements (with only source pads) can also be *get-based* elements. These concepts will be explained in the advanced section of this guide, and in the section that specifically discusses source pads. - diff --git a/pwg-building-eventfn.md b/markdown/pwg/building/eventfn.md similarity index 99% rename from pwg-building-eventfn.md rename to markdown/pwg/building/eventfn.md index 0060064..b99b27f 100644 --- a/pwg-building-eventfn.md +++ b/markdown/pwg/building/eventfn.md @@ -60,7 +60,7 @@ gst_my_filter_sink_event (GstPad *pad, return ret; } - + ``` It is a good idea to call the default event handler @@ -68,4 +68,3 @@ It is a good idea to call the default event handler type, the default handler will forward the event or simply unref it. The CAPS event is by default not forwarded so we need to do this in the event handler ourselves. - diff --git a/pwg-building.md b/markdown/pwg/building/index.md similarity index 93% rename from pwg-building.md rename to markdown/pwg/building/index.md index a54cc4e..26f2fce 100644 --- a/pwg-building.md +++ b/markdown/pwg/building/index.md @@ -18,6 +18,5 @@ event data from its sink pad to its source pad without modification. But by the end of this part of the guide, you will learn to add some more interesting functionality, including properties and signal handlers. And after reading the next part of the guide, [Advanced Filter -Concepts](pwg-advanced.md), you will be able to add even more +Concepts](pwg/advanced/index.md), you will be able to add even more functionality to your plugins. - diff --git a/pwg-building-pads.md b/markdown/pwg/building/pads.md similarity index 99% rename from pwg-building-pads.md rename to markdown/pwg/building/pads.md index df3096b..b988c21 100644 --- a/pwg-building-pads.md +++ b/markdown/pwg/building/pads.md @@ -51,6 +51,5 @@ gst_my_filter_init (GstMyFilter *filter) /* properties initial value */ filter->silent = FALSE; } - -``` +``` diff --git a/pwg-building-queryfn.md b/markdown/pwg/building/queryfn.md similarity index 99% rename from pwg-building-queryfn.md rename to markdown/pwg/building/queryfn.md index 41f1ea3..17f40dc 100644 --- a/pwg-building-queryfn.md +++ b/markdown/pwg/building/queryfn.md @@ -61,10 +61,9 @@ gst_my_filter_src_query (GstPad *pad, return ret; } - + ``` It is a good idea to call the default query handler `gst_pad_query_default ()` for unknown queries. Depending on the query type, the default handler will forward the query or simply unref it. - diff --git a/pwg-building-signals.md b/markdown/pwg/building/signals.md similarity index 99% rename from pwg-building-signals.md rename to markdown/pwg/building/signals.md index 30ad318..b44b674 100644 --- a/pwg-building-signals.md +++ b/markdown/pwg/building/signals.md @@ -11,4 +11,3 @@ application-element interaction, signals are probably not what you're looking for. In many cases, however, signals can be very useful. See the [GObject documentation](http://library.gnome.org/devel/gobject/stable/) for all internals about signals. - diff --git a/pwg-statemanage-states.md b/markdown/pwg/building/statemanage-states.md similarity index 98% rename from pwg-statemanage-states.md rename to markdown/pwg/building/statemanage-states.md index 3d4a37d..3862491 100644 --- a/pwg-statemanage-states.md +++ b/markdown/pwg/building/statemanage-states.md @@ -52,7 +52,7 @@ card or render video pictures to an image sink. ## Managing filter state If at all possible, your element should derive from one of the new base -classes ([Pre-made base classes](pwg-other-base.md)). There are +classes ([Pre-made base classes](pwg/other/base.md)). There are ready-made general purpose base classes for different types of sources, sinks and filter/transformation elements. In addition to those, specialised base classes exist for audio and video elements and others. @@ -79,23 +79,23 @@ the GstElement base class. static GstStateChangeReturn gst_my_filter_change_state (GstElement *element, GstStateChange transition); - + static void gst_my_filter_class_init (GstMyFilterClass *klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - + element_class->change_state = gst_my_filter_change_state; } - - - + + + static GstStateChangeReturn gst_my_filter_change_state (GstElement *element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstMyFilter *filter = GST_MY_FILTER (element); - + switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_my_filter_allocate_memory (filter)) @@ -104,11 +104,11 @@ the GstElement base class. default: break; } - + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; - + switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: gst_my_filter_free_memory (filter); @@ -116,7 +116,7 @@ the GstElement base class. default: break; } - + return ret; } @@ -136,4 +136,3 @@ linked to the state of the element. Pad states are handled in the GstElement class's state change function, including proper locking, that's why it is essential to chain up before destroying allocated resources. - diff --git a/pwg-building-testapp.md b/markdown/pwg/building/testapp.md similarity index 99% rename from pwg-building-testapp.md rename to markdown/pwg/building/testapp.md index 12b08eb..b96f20c 100644 --- a/pwg-building-testapp.md +++ b/markdown/pwg/building/testapp.md @@ -198,6 +198,5 @@ main (gint argc, return 0; } - -``` +``` diff --git a/pwg-index.md b/markdown/pwg/index.md similarity index 100% rename from pwg-index.md rename to markdown/pwg/index.md diff --git a/pwg-intro-basics.md b/markdown/pwg/introduction/basics.md similarity index 98% rename from pwg-intro-basics.md rename to markdown/pwg/introduction/basics.md index 311389a..f510e19 100644 --- a/pwg-intro-basics.md +++ b/markdown/pwg/introduction/basics.md @@ -126,7 +126,7 @@ Events may contain several of the following items: - The other contents of the event depend on the specific event type. Events will be discussed extensively in [Events: Seeking, Navigation and -More](pwg-advanced-events.md). Until then, the only event that will +More](pwg/advanced/events.md). Until then, the only event that will be used is the *EOS* event, which is used to indicate the end-of-stream (usually end-of-file). @@ -157,7 +157,7 @@ from a downstream peer through a GstBufferPool or GstAllocator. Elements can ask a GstBufferPool or GstAllocator from the downstream peer element. If downstream is able to provide these objects, upstream can use them to allocate buffers. See more in [Memory -allocation](pwg-allocation.md). +allocation](pwg/advanced/allocation.md). Many sink elements have accelerated methods for copying data to hardware, or have direct access to hardware. It is common for these @@ -183,7 +183,7 @@ for ensuring that the parameters required to fully specify a format match up correctly when linking pads between elements. Each link that is made between elements has a specified type and optionally a set of properties. See more about caps negotiation in [Caps -negotiation](pwg-negotiation.md). +negotiation](pwg/advanced/negotiation.md). ### The Basic Types @@ -192,7 +192,7 @@ of a few of the basic types used for buffers in GStreamer. The table contains the name ("media type") and a description of the type, the properties associated with the type, and the meaning of each property. A full list of supported types is included in [List of Defined -Types](pwg-building-types.md#list-of-defined-types). +Types](pwg/advanced/building-types.md#list-of-defined-types). @@ -265,4 +265,3 @@ Types](pwg-building-types.md#list-of-defined-types).
Table of Example Types
- diff --git a/pwg-introduction.md b/markdown/pwg/introduction/index.md similarity index 99% rename from pwg-introduction.md rename to markdown/pwg/introduction/index.md index d77eabb..25edad4 100644 --- a/pwg-introduction.md +++ b/markdown/pwg/introduction/index.md @@ -18,4 +18,3 @@ development of an example plugin - an audio filter plugin - written in C. However, the later parts of the guide also present some issues involved in writing other types of plugins, and the end of the guide describes some of the Python bindings for GStreamer. - diff --git a/pwg-intro-preface.md b/markdown/pwg/introduction/preface.md similarity index 82% rename from pwg-intro-preface.md rename to markdown/pwg/introduction/preface.md index 7af3117..d2d9e49 100644 --- a/pwg-intro-preface.md +++ b/markdown/pwg/introduction/preface.md @@ -89,35 +89,35 @@ large parts. Each part addresses a particular broad topic concerning GStreamer plugin development. The parts of this guide are laid out in the following order: - - [Building a Plugin](pwg-building.md) - Introduction to the + - [Building a Plugin](pwg/building/index.md) - Introduction to the structure of a plugin, using an example audio filter for illustration. - + This part covers all the basic steps you generally need to perform to build a plugin, such as registering the element with GStreamer and setting up the basics so it can receive data from and send data to neighbour elements. The discussion begins by giving examples of generating the basic structures and registering an element in - [Constructing the Boilerplate](pwg-building-boiler.md). Then, + [Constructing the Boilerplate](pwg/building/boiler.md). Then, you will learn how to write the code to get a basic filter plugin - working in [Specifying the pads](pwg-building-pads.md), [The - chain function](pwg-building-chainfn.md) and [What are - states?](pwg-statemanage-states.md). - + working in [Specifying the pads](pwg/building/pads.md), [The + chain function](pwg/building/chainfn.md) and [What are + states?](pwg/building/statemanage-states.md). + After that, we will show some of the GObject concepts on how to make an element configurable for applications and how to do application-element interaction in [Adding - Properties](pwg-building-args.md) and - [Signals](pwg-building-signals.md). Next, you will learn to + Properties](pwg/building/args.md) and + [Signals](pwg/building/signals.md). Next, you will learn to build a quick test application to test all that you've just learned - in [Building a Test Application](pwg-building-testapp.md). We + in [Building a Test Application](pwg/building/testapp.md). We will just touch upon basics here. For full-blown application development, you should look at [the Application Development Manual](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html). - - [Advanced Filter Concepts](pwg-advanced.md) - Information on + - [Advanced Filter Concepts](pwg/advanced/index.md) - Information on advanced features of GStreamer plugin development. - + After learning about the basic steps, you should be able to create a functional audio or video filter plugin with some nice features. However, GStreamer offers more for plugin writers. This part of the @@ -125,51 +125,51 @@ the following order: media type definitions in GStreamer, clocks, interfaces and tagging. Since these features are purpose-specific, you can read them in any order, most of them don't require knowledge from other sections. - + The first chapter, named [Different scheduling - modes](pwg-scheduling.md), will explain some of the basics of + modes](pwg/advanced/scheduling.md), will explain some of the basics of element scheduling. It is not very in-depth, but is mostly some sort of an introduction on why other things work as they do. Read this chapter if you're interested in GStreamer internals. Next, we will apply this knowledge and discuss another type of data transmission than what you learned in [The chain - function](pwg-building-chainfn.md): [Different scheduling - modes](pwg-scheduling.md). Loop-based elements will give you + function](pwg/building/chainfn.md): [Different scheduling + modes](pwg/advanced/scheduling.md). Loop-based elements will give you more control over input rate. This is useful when writing, for example, muxers or demuxers. - + Next, we will discuss media identification in GStreamer in [Types - and Properties](pwg-building-types.md). You will learn how to + and Properties](pwg/advanced/building-types.md). You will learn how to define new media types and get to know a list of standard media types defined in GStreamer. - + In the next chapter, you will learn the concept of request- and sometimes-pads, which are pads that are created dynamically, either because the application asked for it (request) or because the media stream requires it (sometimes). This will be in [Request and - Sometimes pads](pwg-advanced-request.md). - - The next chapter, [Clocking](pwg-advanced-clock.md), will + Sometimes pads](pwg/advanced/request.md). + + The next chapter, [Clocking](pwg/advanced/clock.md), will explain the concept of clocks in GStreamer. You need this information when you want to know how elements should achieve audio/video synchronization. - + The next few chapters will discuss advanced ways of doing application-element interaction. Previously, we learned on the GObject-ways of doing this in [Adding - Properties](pwg-building-args.md) and - [Signals](pwg-building-signals.md). We will discuss dynamic + Properties](pwg/building/args.md) and + [Signals](pwg/building/signals.md). We will discuss dynamic parameters, which are a way of defining element behaviour over time - in advance, in [Supporting Dynamic Parameters](pwg-dparams.md). + in advance, in [Supporting Dynamic Parameters](pwg/advanced/dparams.md). Next, you will learn about interfaces in - [Interfaces](pwg-advanced-interfaces.md). Interfaces are very + [Interfaces](pwg/advanced/interfaces.md). Interfaces are very target- specific ways of application-element interaction, based on GObject's GInterface. Lastly, you will learn about how metadata is handled in GStreamer in [Tagging (Metadata and - Streaminfo)](pwg-advanced-tagging.md). - + Streaminfo)](pwg/advanced/tagging.md). + The last chapter, [Events: Seeking, Navigation and - More](pwg-advanced-events.md), will discuss the concept of + More](pwg/advanced/events.md), will discuss the concept of events in GStreamer. Events are, on the one hand, another way of doing application-element interaction. It takes care of seeking, for example. On the other hand, it is also a way in which elements @@ -177,9 +177,9 @@ the following order: media stream discontinuities, forwarding tags inside a pipeline and so on. - - [Creating special element types](pwg-other.md) - Explanation of + - [Creating special element types](pwg/other/index.md) - Explanation of writing other plugin types. - + Because the first two parts of the guide use an audio filter as an example, the concepts introduced apply to filter plugins. But many of the concepts apply equally to other plugin types, including @@ -187,15 +187,15 @@ the following order: the issues that arise when working on these more specialized plugin types. The chapter starts with a special focus on elements that can be written using a base-class ([Pre-made base - classes](pwg-other-base.md)), and later also goes into writing + classes](pwg/other/base.md)), and later also goes into writing special types of elements in [Writing a Demuxer or - Parser](pwg-other-oneton.md), [Writing a N-to-1 Element or - Muxer](pwg-other-ntoone.md) and [Writing a - Manager](pwg-other-manager.md). + Parser](pwg/other/oneton.md), [Writing a N-to-1 Element or + Muxer](pwg/other/ntoone.md) and [Writing a + Manager](pwg/other/manager.md). - - [Appendices](pwg-appendix.md) - Further information for plugin + - [Appendices](pwg/appendix/index.md) - Further information for plugin developers. - + The appendices contain some information that stubbornly refuses to fit cleanly in other sections of the guide. Most of this section is not yet finished. @@ -203,14 +203,14 @@ the following order: The remainder of this introductory part of the guide presents a short overview of the basic concepts involved in GStreamer plugin development. Topics covered include [Elements and -Plugins](pwg-intro-basics.md#elements-and-plugins), -[Pads](pwg-intro-basics.md#pads), [GstMiniObject, Buffers and -Events](pwg-intro-basics.md#gstminiobject-buffers-and-events) and +Plugins](pwg/introduction/basics.md#elements-and-plugins), +[Pads](pwg/introduction/basics.md#pads), [GstMiniObject, Buffers and +Events](pwg/introduction/basics.md#gstminiobject-buffers-and-events) and [Media types and -Properties](pwg-intro-basics.md#media-types-and-properties). If you +Properties](pwg/introduction/basics.md#media-types-and-properties). If you are already familiar with this information, you can use this short overview to refresh your memory, or you can skip to [Building a -Plugin](pwg-building.md). +Plugin](pwg/building/index.md). As you can see, there a lot to learn, so let's get started\! @@ -221,4 +221,3 @@ As you can see, there a lot to learn, so let's get started\! - Adding new media types to the registry along with typedetect functions. This will allow your plugin to operate on a completely new media type. - diff --git a/pwg-other-base.md b/markdown/pwg/other/base.md similarity index 99% rename from pwg-other-base.md rename to markdown/pwg/other/base.md index e23c314..ebf5d9f 100644 --- a/pwg-other-base.md +++ b/markdown/pwg/other/base.md @@ -56,7 +56,7 @@ gst_my_sink_class_init (GstMySinkClass * klass) klass->render = [..]; [..] } - + ``` The advantages of deriving from `GstBaseSink` are numerous: @@ -64,7 +64,7 @@ The advantages of deriving from `GstBaseSink` are numerous: - Derived implementations barely need to be aware of preroll, and do not need to know anything about the technical implementation requirements of preroll. The base-class does all the hard work. - + Less code to write in the derived class, shared code (and thus shared bugfixes). @@ -137,7 +137,7 @@ videosink: ## Writing a source In the previous part, particularly [Providing random -access](pwg-scheduling.md#providing-random-access), we have learned +access](pwg/advanced/scheduling.md#providing-random-access), we have learned that some types of elements can provide random access. This applies most definitely to source elements reading from a randomly seekable location, such as file sources. However, other source elements may be better @@ -207,4 +207,3 @@ Since the `GstBaseTransform` is based on the 1-to-1 model for filters, it may not apply well to elements such as decoders, which may have to parse properties from the stream. Also, it will not work for elements requiring more than one sourcepad or sinkpad. - diff --git a/pwg-other.md b/markdown/pwg/other/index.md similarity index 99% rename from pwg-other.md rename to markdown/pwg/other/index.md index 07cf504..c6147eb 100644 --- a/pwg-other.md +++ b/markdown/pwg/other/index.md @@ -14,4 +14,3 @@ transformation elements). We will also look closer at some types of elements that require no specific coding such as scheduling-interaction or data passing, but rather require specific pipeline control (e.g. N-to-1 elements and managers). - diff --git a/pwg-other-manager.md b/markdown/pwg/other/manager.md similarity index 99% rename from pwg-other-manager.md rename to markdown/pwg/other/manager.md index d18a316..db77eee 100644 --- a/pwg-other-manager.md +++ b/markdown/pwg/other/manager.md @@ -28,4 +28,3 @@ Making a manager is about as simple as it gets. You can derive from a `_init ()` already, including setup of ghostpads. If you need any custom data handlers, you can connect signals or embed a second element which you control. - diff --git a/pwg-other-ntoone.md b/markdown/pwg/other/ntoone.md similarity index 87% rename from pwg-other-ntoone.md rename to markdown/pwg/other/ntoone.md index c54eb28..5341e15 100644 --- a/pwg-other-ntoone.md +++ b/markdown/pwg/other/ntoone.md @@ -5,8 +5,8 @@ title: Writing a N-to-1 Element or Muxer # Writing a N-to-1 Element or Muxer N-to-1 elements have been previously mentioned and discussed in both -[Request and Sometimes pads](pwg-advanced-request.md) and in -[Different scheduling modes](pwg-scheduling.md). The main noteworthy +[Request and Sometimes pads](pwg/advanced/request.md) and in +[Different scheduling modes](pwg/advanced/scheduling.md). The main noteworthy thing about N-to-1 elements is that each pad is push-based in its own thread, and the N-to-1 element synchronizes those streams by expected-timestamp-based logic. This means it lets all streams wait @@ -21,4 +21,3 @@ buffer from each input and giving you the one with earliest timestamp. If you need anything more difficult, such as "don't-grab-a-new-buffer until a given timestamp" or something like that, you'll need to do this yourself. - diff --git a/pwg-other-oneton.md b/markdown/pwg/other/oneton.md similarity index 86% rename from pwg-other-oneton.md rename to markdown/pwg/other/oneton.md index 76d4dc4..754ee7d 100644 --- a/pwg-other-oneton.md +++ b/markdown/pwg/other/oneton.md @@ -12,10 +12,10 @@ will be offered. Parsers are demuxers with only one source pad. Also, they only cut the stream into buffers, they don't touch the data otherwise. -As mentioned previously in [Caps negotiation](pwg-negotiation.md), +As mentioned previously in [Caps negotiation](pwg/advanced/negotiation.md), demuxers should use fixed caps, since their data type will not change. -As discussed in [Different scheduling modes](pwg-scheduling.md), +As discussed in [Different scheduling modes](pwg/advanced/scheduling.md), demuxer elements can be written in multiple ways: - They can be the driving force of the pipeline, by running their own @@ -31,6 +31,5 @@ written in random access mode. Although simple playback will mostly work if your element only accepts one mode, it may be required to implement multiple modes to work in combination with all sorts of applications, such as editing. Also, performance may become better if you implement -multiple modes. See [Different scheduling modes](pwg-scheduling.md) +multiple modes. See [Different scheduling modes](pwg/advanced/scheduling.md) to see how an element can accept multiple scheduling modes. - diff --git a/rtp.md b/markdown/rtp.md similarity index 99% rename from rtp.md rename to markdown/rtp.md index 8b07893..5fad3df 100644 --- a/rtp.md +++ b/markdown/rtp.md @@ -88,4 +88,3 @@ Some of the main components are: Note that many RTP elements assume they receive RTP buffers with
GstNetAddressMeta meta data set on them (as udpsrc will produce). - diff --git a/splitup.md b/markdown/splitup.md similarity index 97% rename from splitup.md rename to markdown/splitup.md index 26aa48f..511dfa1 100644 --- a/splitup.md +++ b/markdown/splitup.md @@ -17,7 +17,7 @@ libraries, some essential elements, documentation, and testing. A well-groomed and well-maintained collection of GStreamer plug-ins and elements, spanning the range of possible types of elements one would want -to write for GStreamer. +to write for GStreamer. And introducing, for the first time ever, on the development screen ... @@ -60,7 +60,7 @@ those with a rope around their neck and the people who do the cutting.
That an accusation?
No perfectly groomed moustache or any amount of fine clothing is going to -cover up the truth - these plug-ins are Bad with a capital B. +cover up the truth - these plug-ins are Bad with a capital B. They look fine on the outside, and might even appear to get the job done, but at the end of the day they're a black sheep. Without a golden-haired angel to watch over them, they'll probably land in an unmarked grave at the final @@ -97,7 +97,7 @@ code, correct functionality, our preferred license (LGPL for the plug-in code, LGPL or LGPL-compatible for the supporting library). * We believe distributors can safely ship these plug-ins * People writing elements should base their code on these elements - + ### gst-plugins-ugly a set of plug-ins that have good quality and correct diff --git a/tool-ges-launch.md b/markdown/tools/ges-launch.md similarity index 99% rename from tool-ges-launch.md rename to markdown/tools/ges-launch.md index ffea5ea..2ce6226 100644 --- a/tool-ges-launch.md +++ b/markdown/tools/ges-launch.md @@ -253,7 +253,7 @@ Set an encoding profile on the command line. See ges-launch-1.0 help profile for more information. This will have no effect if no outputuri has been specified. ``` - + __-e --encoding-profile=:__ ``` Set an encoding profile from a preset file. See ges-launch-1.0 help profile diff --git a/tool-gst-inspect.md b/markdown/tools/gst-inspect.md similarity index 100% rename from tool-gst-inspect.md rename to markdown/tools/gst-inspect.md diff --git a/tool-gst-launch.md b/markdown/tools/gst-launch.md similarity index 100% rename from tool-gst-launch.md rename to markdown/tools/gst-launch.md diff --git a/gstreamer-command-line-tools.md b/markdown/tools/index.md similarity index 100% rename from gstreamer-command-line-tools.md rename to markdown/tools/index.md diff --git a/tutorial-android-a-complete-media-player.md b/markdown/tutorials/android/a-complete-media-player.md similarity index 94% rename from tutorial-android-a-complete-media-player.md rename to markdown/tutorials/android/a-complete-media-player.md index 33bcb4c..3f7807d 100644 --- a/tutorial-android-a-complete-media-player.md +++ b/markdown/tutorials/android/a-complete-media-player.md @@ -9,7 +9,7 @@ be done with GStreamer in the Android platform. It is intended to be downloaded in final, compiled, form rather than analyzed for its pedagogical value, since it adds very little GStreamer -knowledge over what has already been shown in [](tutorial-android-media-player.md). +knowledge over what has already been shown in [](tutorials/android/media-player.md). **FIXME: Do we want to provide a binary of the app?** @@ -56,7 +56,7 @@ retrieved and checked for such URI. ## Implementing a file chooser dialog The UI includes a new button ![media-next) which -was not present in [](tutorial-android-media-player.md). It +was not present in [](tutorials/android/media-player.md). It invokes a file chooser dialog (based on the [Android File Dialog](http://code.google.com/p/android-file-dialog/) project) that allows you to choose a local media file, no matter what extension or @@ -88,5 +88,5 @@ Android. It has been a pleasure having you here, and see you soon! - [screenshot]: images/tutorial-android-a-complete-media-player-screenshot.png + [screenshot]: images/tutorials/android-a-complete-media-player-screenshot.png [media-next]: images/media-next.png diff --git a/tutorial-android-a-running-pipeline.md b/markdown/tutorials/android/a-running-pipeline.md similarity index 99% rename from tutorial-android-a-running-pipeline.md rename to markdown/tutorials/android/a-running-pipeline.md index e4fc1ff..0f6d672 100644 --- a/tutorial-android-a-running-pipeline.md +++ b/markdown/tutorials/android/a-running-pipeline.md @@ -4,8 +4,8 @@ ![screenshot] -The tutorials seen in the [Basic](tutorials-basic.md) and -[Playback](tutorials-playback.md) sections are intended for Desktop +The tutorials seen in the [Basic](tutorials/basic/index.md) and +[Playback](tutorials/playback/index.md) sections are intended for Desktop platforms and, therefore, their main thread is allowed to block (using `gst_bus_pop_filtered()`) or relinquish control to a GLib main loop. On Android this would lead to the application being tagged as @@ -966,9 +966,9 @@ static void set_ui_message (const gchar *message, CustomData *data) { } ``` - -This is the other method (besides `check_initialization_complete()`) + +This is the other method (besides `check_initialization_complete()`) that needs to call a Java function from a thread which never received an `JNIEnv` pointer directly. Notice how all the complexities of attaching the thread to the JavaVM and storing the JNI environment in the TLS are @@ -1047,4 +1047,4 @@ tutorials with minimal modifications, so better get used to them\! As usual, it has been a pleasure having you here, and see you soon\! - [screenshot]: images/tutorial-android-a-running-pipeline-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/android-a-running-pipeline-screenshot.png \ No newline at end of file diff --git a/tutorials-android.md b/markdown/tutorials/android/index.md similarity index 79% rename from tutorials-android.md rename to markdown/tutorials/android/index.md index b0cd57f..0978732 100644 --- a/tutorials-android.md +++ b/markdown/tutorials/android/index.md @@ -4,18 +4,18 @@ These tutorials describe Android-specific topics. General GStreamer concepts will not be explained in these tutorials, so the -[](tutorials-basic.md) should be reviewed first. The reader should +[](tutorials/basic/index.md) should be reviewed first. The reader should also be familiar with basic Android programming techniques. Each Android tutorial builds on top of the previous one and adds progressively more functionality, until a working media player -application is obtained in [](tutorial-android-a-complete-media-player.md). +application is obtained in [](tutorials/android/a-complete-media-player.md). This is the same media player application used to advertise GStreamer on Android, and the download link can be found in -the [](tutorial-android-a-complete-media-player.md) page. +the [](tutorials/android/a-complete-media-player.md) page. Make sure to have read the instructions in -[](installing-for-android-development.md) before jumping into the +[](installing/for-android-development.md) before jumping into the Android tutorials. ### A note on the documentation diff --git a/tutorial-android-link-against-gstreamer.md b/markdown/tutorials/android/link-against-gstreamer.md similarity index 98% rename from tutorial-android-link-against-gstreamer.md rename to markdown/tutorials/android/link-against-gstreamer.md index c2e9eb6..3eb420f 100644 --- a/tutorial-android-link-against-gstreamer.md +++ b/markdown/tutorials/android/link-against-gstreamer.md @@ -7,7 +7,7 @@ This first Android tutorial is extremely simple: it just retrieves the GStreamer version and displays it on the screen. It exemplifies how to access GStreamer C code from Java and verifies that there have been no -linkage problems. +linkage problems. ## Hello GStreamer \[Java code\] @@ -15,7 +15,7 @@ The tutorial code is in the [gst-docs](https://cgit.freedesktop.org/gstreamer/gs a `jni` folder for the C code and a `res` folder for UI resources. We recommend that you open this project in Eclipse (as explained -in [](installing-for-android-development.md)) so you can +in [](installing/for-android-development.md)) so you can easily see how all the pieces fit together. Let’s first introduce the Java code, then the C code and finally the @@ -182,7 +182,7 @@ JNIEnv *env = NULL; if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) { __android_log_print (ANDROID_LOG_ERROR, "tutorial-1", "Could not retrieve JNIEnv"); return 0; -} +} ``` And then locate the class containing the UI part of this tutorial using @@ -278,4 +278,4 @@ taken when developing specifically for the Android platform. As usual, it has been a pleasure having you here, and see you soon\! - [screenshot]: images/tutorial-android-link-against-gstreamer-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/android-link-against-gstreamer-screenshot.png \ No newline at end of file diff --git a/tutorial-android-media-player.md b/markdown/tutorials/android/media-player.md similarity index 99% rename from tutorial-android-media-player.md rename to markdown/tutorials/android/media-player.md index 7340a6b..6930173 100644 --- a/tutorial-android-media-player.md +++ b/markdown/tutorials/android/media-player.md @@ -14,7 +14,7 @@ Android device. It shows: Bar](http://developer.android.com/reference/android/widget/SeekBar.html) - How to report the media size to adapt the display surface -It also uses the knowledge gathered in the [](tutorials-basic.md) regarding: +It also uses the knowledge gathered in the [](tutorials/basic/index.md) regarding: - How to use `playbin` to play any kind of media - How to handle network resilience problems @@ -26,7 +26,7 @@ to build a media player. The most complex part is assembling a pipeline which retrieves, decodes and displays the media, but we already know that the `playbin` element can take care of all that for us. We only need to replace the manual pipeline we used in -[](tutorial-android-video.md) with a single-element +[](tutorials/android/video.md) with a single-element `playbin` pipeline and we are good to go! However, we can do better than. We will add a [Seek @@ -344,14 +344,14 @@ charge of displaying the media, and ask the Android layout to be recalculated. Eventually, the `onMeasure()` method in GStreamerSurfaceView will be called and the new size will be taken into account. As we have already seen in -[](tutorial-android-a-running-pipeline.md), methods which change +[](tutorials/android/a-running-pipeline.md), methods which change the UI must be called from the main thread, and we are now in a callback from some GStreamer internal thread. Hence, the usage of [runOnUiThread()](http://developer.android.com/reference/android/app/Activity.html#runOnUiThread\(java.lang.Runnable\)). ### Refreshing the Seek Bar -[](tutorial-basic-toolkit-integration.md) +[](tutorials/basic/toolkit-integration.md) has already shown how to implement a [Seek Bar](http://developer.android.com/reference/android/widget/SeekBar.html) using the GTK+ toolkit. The implementation on Android is very similar. @@ -433,7 +433,7 @@ the user: ``` java public void onStartTrackingTouch(SeekBar sb) { nativePause(); -} +} ``` [onStartTrackingTouch()](http://developer.android.com/reference/android/widget/SeekBar.OnSeekBarChangeListener.html#onStartTrackingTouch\(android.widget.SeekBar\)) @@ -449,7 +449,7 @@ public void onProgressChanged(SeekBar sb, int progress, boolean fromUser) { // If this is a local file, allow scrub seeking, this is, seek soon as the slider is moved. if (is_local_media) nativeSetPosition(desired_position); updateTimeWidget(); -} +} ``` [onProgressChanged()](http://developer.android.com/reference/android/widget/SeekBar.OnSeekBarChangeListener.html#onProgressChanged\(android.widget.SeekBar,%20int,%20boolean\)) is @@ -1162,7 +1162,7 @@ before entering the main loop: timeout_source = g_timeout_source_new (250); g_source_set_callback (timeout_source, (GSourceFunc)refresh_ui, data, NULL); g_source_attach (timeout_source, data->context); -g_source_unref (timeout_source); +g_source_unref (timeout_source); ``` Then, in the refresh\_ui method: @@ -1193,13 +1193,13 @@ static gboolean refresh_ui (CustomData *data) { ``` If it is unknown, the clip duration is retrieved, as explained in -[](tutorial-basic-time-management.md). The current position is +[](tutorials/basic/time-management.md). The current position is retrieved next, and the UI is informed of both through its `setCurrentPosition()` callback. Bear in mind that all time-related measures returned by GStreamer are in nanoseconds, whereas, for simplicity, we decided to make the UI code -work in milliseconds. +work in milliseconds. ### Seeking with the Seek Bar @@ -1231,7 +1231,7 @@ void gst_native_set_position (JNIEnv* env, jobject thiz, int milliseconds) { GST_DEBUG ("Scheduling seek to %" GST_TIME_FORMAT " for later", GST_TIME_ARGS (desired_position)); data->desired_position = desired_position; } -} +} ``` If we are already in the correct state for seeking, execute it right @@ -1333,7 +1333,7 @@ The one-shot timer calls `delayed_seek_cb()`, which simply calls ### Network resilience -[](tutorial-basic-streaming.md) has already +[](tutorials/basic/streaming.md) has already shown how to adapt to the variable nature of the network bandwidth by using buffering. The same procedure is used here, by listening to the buffering @@ -1408,5 +1408,5 @@ here into an acceptable Android media player. As usual, it has been a pleasure having you here, and see you soon! - [screenshot]: images/tutorial-android-media-player-screenshot.png + [screenshot]: images/tutorials/android-media-player-screenshot.png [information]: images/icons/emoticons/information.png \ No newline at end of file diff --git a/tutorial-android-video.md b/markdown/tutorials/android/video.md similarity index 99% rename from tutorial-android-video.md rename to markdown/tutorials/android/video.md index 75e85ea..fa02fa6 100644 --- a/tutorial-android-video.md +++ b/markdown/tutorials/android/video.md @@ -4,7 +4,7 @@ ![screenshot] -Except for [](tutorial-basic-toolkit-integration.md), +Except for [](tutorials/basic/toolkit-integration.md), which embedded a video window on a GTK application, all tutorials so far relied on GStreamer video sinks to create a window to display their contents. The video sink on Android is not capable of creating its own @@ -21,7 +21,7 @@ Since Android does not provide a windowing system, a GStreamer video sink cannot create pop-up windows as it would do on a Desktop platform. Fortunately, the `VideoOverlay` interface allows providing video sinks with an already created window onto which they can draw, as we have seen in -[](tutorial-basic-toolkit-integration.md). +[](tutorials/basic/toolkit-integration.md). In this tutorial, a [SurfaceView](http://developer.android.com/reference/android/view/SurfaceView.html) @@ -650,7 +650,7 @@ ask for it immediately. The `gst_bin_get_by_interface()` method will examine the whole pipeline and return a pointer to an element which supports the requested interface. We are asking for the `VideoOverlay` interface, explained in -[](tutorial-basic-toolkit-integration.md), +[](tutorials/basic/toolkit-integration.md), which controls how to perform rendering into foreign (non-GStreamer) windows. The internal video sink instantiated by `autovideosink` is the only element in this pipeline implementing it, so it will be returned. @@ -910,4 +910,4 @@ to this tutorial in order to build a simple media player. It has been a pleasure having you here, and see you soon\! - [screenshot]: images/tutorial-android-video-screenshot.png + [screenshot]: images/tutorials/android-video-screenshot.png diff --git a/tutorial-basic-concepts.md b/markdown/tutorials/basic/concepts.md similarity index 93% rename from tutorial-basic-concepts.md rename to markdown/tutorials/basic/concepts.md index af1f7aa..51ac1fe 100644 --- a/tutorial-basic-concepts.md +++ b/markdown/tutorials/basic/concepts.md @@ -104,11 +104,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > `` gcc basic-tutorial-2.c -o basic-tutorial-2 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > >This tutorial opens a window and displays a test pattern, without audio > @@ -121,7 +121,7 @@ process the data as it flows *downstream* from the source elements (the producers of data) to the sink elements (the consumers of data), passing through filter elements. -![](attachments/figure-1.png) +![](images/figure-1.png) **Figure 1**. Example pipeline @@ -139,9 +139,9 @@ sink = gst_element_factory_make ("autovideosink", "sink"); As seen in this code, new elements can be created with `gst_element_factory_make()`. The first parameter is the type of element to create ([Basic tutorial 14: Handy -elements](tutorial-basic-handy-elements.md) shows a +elements](tutorials/basic/handy-elements.md) shows a few common types, and [Basic tutorial 10: GStreamer -tools](tutorial-basic-gstreamer-tools.md) shows how to +tools](tutorials/basic/gstreamer-tools.md) shows how to obtain the list of all available types). The second parameter is the name we want to give to this particular instance. Naming your elements is useful to retrieve them later if you didn't keep a pointer (and for @@ -225,7 +225,7 @@ values! The names and possible values of all the properties an element exposes can be found using the gst-inspect-1.0 tool described in [Basic tutorial 10: -GStreamer tools](tutorial-basic-gstreamer-tools.md). +GStreamer tools](tutorials/basic/gstreamer-tools.md). ### Error checking @@ -246,7 +246,7 @@ if (ret == GST_STATE_CHANGE_FAILURE) { We call `gst_element_set_state()`, but this time we check its return value for errors. Changing states is a delicate process and a few more details are given in [Basic tutorial 3: Dynamic -pipelines](tutorial-basic-dynamic-pipelines.md). +pipelines](tutorials/basic/dynamic-pipelines.md). ``` c /* Wait until error or EOS */ @@ -311,7 +311,7 @@ playback-related issues. The rest of the code is the cleanup sequence, which is the same as in [Basic tutorial 1: Hello -world!](tutorial-basic-hello-world.md). +world!](tutorials/basic/hello-world.md). ## Exercise @@ -324,11 +324,11 @@ Depending on your platform and available plugins, you might get a “negotiation” error, because the sink does not understand what the filter is producing (more about negotiation in [Basic tutorial 6: Media formats and Pad -Capabilities](tutorial-basic-media-formats-and-pad-capabilities.md)). +Capabilities](tutorials/basic/media-formats-and-pad-capabilities.md)). In this case, try to add an element called `videoconvert` after the filter (this is, build a pipeline of 4 elements. More on `videoconvert` in [Basic tutorial 14: Handy -elements](tutorial-basic-handy-elements.md)). +elements](tutorials/basic/handy-elements.md)). ## Conclusion diff --git a/tutorial-basic-debugging-tools.md b/markdown/tutorials/basic/debugging-tools.md similarity index 100% rename from tutorial-basic-debugging-tools.md rename to markdown/tutorials/basic/debugging-tools.md diff --git a/tutorial-basic-dynamic-pipelines.md b/markdown/tutorials/basic/dynamic-pipelines.md similarity index 95% rename from tutorial-basic-dynamic-pipelines.md rename to markdown/tutorials/basic/dynamic-pipelines.md index afb86cf..69f6383 100644 --- a/tutorial-basic-dynamic-pipelines.md +++ b/markdown/tutorials/basic/dynamic-pipelines.md @@ -8,7 +8,7 @@ information becomes available, instead of having a monolithic pipeline defined at the beginning of your application. After this tutorial, you will have the necessary knowledge to start the -[Playback tutorials](tutorials-playback.md). The points reviewed +[Playback tutorials](tutorials/playback/index.md). The points reviewed here will be: - How to attain finer control when linking elements. @@ -43,14 +43,14 @@ It follows naturally that source elements only contain source pads, sink elements only contain sink pads, and filter elements contain both. -![](attachments/src-element.png) ![](attachments/filter-element.png) ![](attachments/sink-element.png) +![](images/src-element.png) ![](images/filter-element.png) ![](images/sink-element.png) **Figure 1**. GStreamer elements with their pads. A demuxer contains one sink pad, through which the muxed data arrives, and multiple source pads, one for each stream found in the container: -![](attachments/filter-element-multi.png) +![](images/filter-element-multi.png) **Figure 2**. A demuxer with two source pads. @@ -58,7 +58,7 @@ For completeness, here you have a simplified pipeline containing a demuxer and two branches, one for audio and one for video. This is **NOT** the pipeline that will be built in this example: -![](attachments/simple-player.png) +![](images/simple-player.png) **Figure 3**. Example pipeline with two branches. @@ -240,10 +240,10 @@ exit: > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > ``gcc basic-tutorial-3.c -o basic-tutorial-3 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial only plays audio. The media is fetched from the Internet, so it might take a few seconds to start, depending on your connection speed. > @@ -338,7 +338,7 @@ for this purpose. The signals that a `GstElement` generates can be found in its documentation or using the `gst-inspect-1.0` tool as described in [Basic tutorial 10: GStreamer -tools](tutorial-basic-gstreamer-tools.md). +tools](tutorials/basic/gstreamer-tools.md). We are now ready to go! Just set the pipeline to the PLAYING state and start listening to the bus for interesting messages (like ERROR or EOS), @@ -493,10 +493,10 @@ front) and link it to the demuxer when the right pad appears. Hint: You are already printing on screen the type of the video pads. You should now see (and hear) the same movie as in [Basic tutorial 1: -Hello world!](tutorial-basic-hello-world.md). In +Hello world!](tutorials/basic/hello-world.md). In that tutorial you used `playbin`, which is a handy element that automatically takes care of all the demuxing and pad linking for you. -Most of the [Playback tutorials](tutorials-playback.md) are devoted +Most of the [Playback tutorials](tutorials/playback/index.md) are devoted to `playbin`. ## Conclusion @@ -513,8 +513,8 @@ media was available. You can now continue with the basic tutorials and learn about performing seeks and time-related queries in [Basic tutorial 4: Time -management](tutorial-basic-time-management.md) or move -to the [Playback tutorials](tutorials-playback.md), and gain more +management](tutorials/basic/time-management.md) or move +to the [Playback tutorials](tutorials/playback/index.md), and gain more insight about the `playbin` element. Remember that attached to this page you should find the complete source diff --git a/tutorial-basic-gstreamer-tools.md b/markdown/tutorials/basic/gstreamer-tools.md similarity index 96% rename from tutorial-basic-gstreamer-tools.md rename to markdown/tutorials/basic/gstreamer-tools.md index 83d6f05..5cb5470 100644 --- a/tutorial-basic-gstreamer-tools.md +++ b/markdown/tutorials/basic/gstreamer-tools.md @@ -21,7 +21,7 @@ polluting it too much). Just open a terminal (or console window) and go to the `bin` directory of your GStreamer installation (Read again the [Installing -GStreamer](installing.md) section to find our where this is), +GStreamer](installing/index.md) section to find our where this is), and you are ready to start typing the commands given in this tutorial. @@ -63,7 +63,7 @@ descriptions resemble black magic. Fear not, for everyone learns the The command line for gst-launch-1.0 consists of a list of options followed by a PIPELINE-DESCRIPTION. Some simplified instructions are given next, -se the complete documentation at [the reference page](tool-gst-launch.md) +se the complete documentation at [the reference page](tools/gst-launch.md) for `gst-launch-1.0`. ### Elements @@ -122,14 +122,14 @@ If you see only one, try to move it, since it is probably on top of the second window. This example instantiates a `videotestsrc`, linked to a -`videoconvert`, linked to a `tee` (Remember from [](tutorial-basic-multithreading-and-pad-availability.md) that +`videoconvert`, linked to a `tee` (Remember from [](tutorials/basic/multithreading-and-pad-availability.md) that a `tee` copies to each of its output pads everything coming through its input pad). The `tee` is named simply ‘t’ (using the `name` property) and then linked to a `queue` and an `autovideosink`. The same `tee` is referred to using ‘t.’ (mind the dot) and then linked to a second `queue` and a second `autovideosink`. -To learn why the queues are necessary read [](tutorial-basic-multithreading-and-pad-availability.md). +To learn why the queues are necessary read [](tutorials/basic/multithreading-and-pad-availability.md). ### Pads @@ -148,7 +148,7 @@ gst-launch-1.0 souphttpsrc location=https://www.freedesktop.org/software/gstream ``` This fetches a media file from the internet using `souphttpsrc`, which -is in webm format (a special kind of Matroska container, see [](tutorial-basic-concepts.md)). We +is in webm format (a special kind of Matroska container, see [](tutorials/basic/concepts.md)). We then open the container using `matroskademux`. This media contains both audio and video, so `matroskademux` will create two output Pads, named `video_00` and `audio_00`. We link `video_00` to a `matroskamux` element @@ -219,7 +219,7 @@ producing for a particular pipeline, run `gst-launch-1.0` as usual, with the ### Examples -Play a media file using `playbin` (as in [](tutorial-basic-hello-world.md)): +Play a media file using `playbin` (as in [](tutorials/basic/hello-world.md)): ``` gst-launch-1.0 playbin uri=https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm @@ -254,7 +254,7 @@ gst-launch-1.0 uridecodebin uri=https://www.freedesktop.org/software/gstreamer-s This short description of `gst-launch-1.0` should be enough to get you started. Remember that you have the [complete documentation available -here](tool-gst-launch.md). +here](tools/gst-launch.md). ## `gst-inspect-1.0` @@ -348,13 +348,13 @@ Element Properties: (0x00000400): mfqe - Multi-frame quality enhancement deblocking-level : Deblocking level flags: readable, writable - Unsigned Integer. Range: 0 - 16 Default: 4 + Unsigned Integer. Range: 0 - 16 Default: 4 noise-level : Noise level flags: readable, writable - Unsigned Integer. Range: 0 - 16 Default: 0 + Unsigned Integer. Range: 0 - 16 Default: 0 threads : Maximum number of decoding threads flags: readable, writable - Unsigned Integer. Range: 1 - 16 Default: 0 + Unsigned Integer. Range: 1 - 16 Default: 0 ``` The most relevant sections are: @@ -369,11 +369,11 @@ The most relevant sections are: element, along with their type and accepted values. For more information, you can check the [documentation -page](tool-gst-inspect.md) of `gst-inspect-1.0`. +page](tools/gst-inspect.md) of `gst-inspect-1.0`. ## `gst-discoverer-1.0` -This tool is a wrapper around the `GstDiscoverer` object shown in [](tutorial-basic-media-information-gathering.md). +This tool is a wrapper around the `GstDiscoverer` object shown in [](tutorials/basic/media-information-gathering.md). It accepts a URI from the command line and prints all information regarding the media that GStreamer can extract. It is useful to find out what container and codecs have been used to produce the media, and diff --git a/tutorial-basic-handy-elements.md b/markdown/tutorials/basic/handy-elements.md similarity index 95% rename from tutorial-basic-handy-elements.md rename to markdown/tutorials/basic/handy-elements.md index fa8ecc9..a0661c7 100644 --- a/tutorial-basic-handy-elements.md +++ b/markdown/tutorials/basic/handy-elements.md @@ -9,7 +9,7 @@ elements which are extremely useful when debugging. For simplicity, the following examples are given using the `gst-launch-1.0` tool (Learn about it in -[](tutorial-basic-gstreamer-tools.md)). Use the `-v` command line +[](tutorials/basic/gstreamer-tools.md)). Use the `-v` command line parameter if you want to see the Pad Caps that are being negotiated. ## Bins @@ -23,7 +23,7 @@ their task. This element has been extensively used throughout the tutorials. It manages all aspects of media playback, from source to display, passing through demuxing and decoding. It is so flexible and has so many options -that a whole set of tutorials are devoted to it. See the [](tutorials-playback.md) for more details. +that a whole set of tutorials are devoted to it. See the [](tutorials/playback/index.md) for more details. ### `uridecodebin` @@ -228,7 +228,7 @@ Most of the time, `audiorate` is not what you want. ### `queue` -Queues have been explained in [](tutorial-basic-multithreading-and-pad-availability.md). Basically, a queue performs two tasks: +Queues have been explained in [](tutorials/basic/multithreading-and-pad-availability.md). Basically, a queue performs two tasks: - Data is queued until a selected limit is reached. Any attempt to push more buffers into the queue blocks the pushing thread until @@ -242,7 +242,7 @@ instructed to drop buffers instead of blocking when it is full. As a rule of thumb, prefer the simpler `queue` element over `queue2` whenever network buffering is not a concern to you. -See [](tutorial-basic-multithreading-and-pad-availability.md) +See [](tutorials/basic/multithreading-and-pad-availability.md) for an example. ### `queue2` @@ -256,10 +256,10 @@ queue is the best choice. additionally, is able to store the received data (or part of it) on a disk file, for later retrieval. It also replaces the signals with the more general and convenient buffering messages described in -[](tutorial-basic-streaming.md). +[](tutorials/basic/streaming.md). As a rule of thumb, prefer `queue2` over `queue` whenever network -buffering is a concern to you. See [](tutorial-basic-streaming.md) +buffering is a concern to you. See [](tutorials/basic/streaming.md) for an example (`queue2` is hidden inside `playbin`). ### `multiqueue` @@ -277,7 +277,7 @@ application. ### `tee` -[](tutorial-basic-multithreading-and-pad-availability.md) already +[](tutorials/basic/multithreading-and-pad-availability.md) already showed how to use a `tee` element, which splits data to multiple pads. Splitting the data flow is useful, for example, when capturing a video where the video is shown on the screen and also encoded and written to a @@ -296,7 +296,7 @@ gst-launch-1.0 audiotestsrc ! tee name=t ! queue ! audioconvert ! autoaudiosink ## Capabilities ### `capsfilter` -[](tutorial-basic-gstreamer-tools.md) already +[](tutorials/basic/gstreamer-tools.md) already explained how to use Caps filters with `gst-launch-1.0`. When building a pipeline programmatically, Caps filters are implemented with the `capsfilter` element. This element does not modify data as such, @@ -316,7 +316,7 @@ the `have-type` signal. It is instantiated internally by `decodebin`, and you can use it too to find the media type, although you can normally use the `GstDiscoverer` which provides more information (as seen in -[](tutorial-basic-media-information-gathering.md)). +[](tutorials/basic/media-information-gathering.md)). ## Debugging diff --git a/tutorial-basic-hello-world.md b/markdown/tutorials/basic/hello-world.md similarity index 91% rename from tutorial-basic-hello-world.md rename to markdown/tutorials/basic/hello-world.md index 7509db7..ef07b82 100644 --- a/tutorial-basic-hello-world.md +++ b/markdown/tutorials/basic/hello-world.md @@ -221,17 +221,17 @@ and show you how to build a pipeline manually. It has been a pleasure having you here, and see you soon! - [Installing on Linux]: installing-on-linux.md - [Installing on Mac OS X]: installing-on-mac-osx.md - [Installing on Windows]: installing-on-windows.md + [Installing on Linux]: installing/on-linux.md + [Installing on Mac OS X]: installing/on-mac-osx.md + [Installing on Windows]: installing/on-windows.md [Information]: images/icons/emoticons/information.png - [Linux]: installing-on-linux.md#InstallingonLinux-Build - [Mac OS X]: installing-on-mac-osx.md#InstallingonMacOSX-Build - [Windows]: installing-on-windows.md#InstallingonWindows-Build - [1]: installing-on-linux.md#InstallingonLinux-Run - [2]: installing-on-mac-osx.md#InstallingonMacOSX-Run - [3]: installing-on-windows.md#InstallingonWindows-Run - [Basic tutorial 12: Streaming]: tutorial-basic-streaming.md - [Basic tutorial 10: GStreamer tools]: tutorial-basic-gstreamer-tools.md - [Basic tutorial 2: GStreamer concepts]: tutorial-basic-concepts.md - [Basic tutorial 3: Dynamic pipelines]: tutorial-basic-dynamic-pipelines.md + [Linux]: installing/on-linux.md#InstallingonLinux-Build + [Mac OS X]: installing/on-mac-osx.md#InstallingonMacOSX-Build + [Windows]: installing/on-windows.md#InstallingonWindows-Build + [1]: installing/on-linux.md#InstallingonLinux-Run + [2]: installing/on-mac-osx.md#InstallingonMacOSX-Run + [3]: installing/on-windows.md#InstallingonWindows-Run + [Basic tutorial 12: Streaming]: tutorials/basic/streaming.md + [Basic tutorial 10: GStreamer tools]: tutorials/basic/gstreamer-tools.md + [Basic tutorial 2: GStreamer concepts]: tutorials/basic/concepts.md + [Basic tutorial 3: Dynamic pipelines]: tutorials/basic/dynamic-pipelines.md diff --git a/tutorials-basic.md b/markdown/tutorials/basic/index.md similarity index 100% rename from tutorials-basic.md rename to markdown/tutorials/basic/index.md diff --git a/tutorial-basic-media-formats-and-pad-capabilities.md b/markdown/tutorials/basic/media-formats-and-pad-capabilities.md similarity index 97% rename from tutorial-basic-media-formats-and-pad-capabilities.md rename to markdown/tutorials/basic/media-formats-and-pad-capabilities.md index 9472213..9b22f38 100644 --- a/tutorial-basic-media-formats-and-pad-capabilities.md +++ b/markdown/tutorials/basic/media-formats-and-pad-capabilities.md @@ -100,7 +100,7 @@ indicate different packing and subsampling of the image planes. ### Last remarks You can use the `gst-inspect-1.0` tool described in [Basic tutorial 10: -GStreamer tools](tutorial-basic-gstreamer-tools.md) to +GStreamer tools](tutorials/basic/gstreamer-tools.md) to learn about the Caps of any GStreamer element. Bear in mind that some elements query the underlying hardware for @@ -335,11 +335,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > `` gcc basic-tutorial-6.c -o basic-tutorial-6 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial simply displays information regarding the Pad Capabilities in different time instants. > @@ -466,7 +466,7 @@ This tutorial has shown: - That Pad Caps can be found using the `gst-inspect-1.0` tool described in [Basic tutorial 10: GStreamer - tools](tutorial-basic-gstreamer-tools.md). + tools](tutorials/basic/gstreamer-tools.md). Next tutorial shows how data can be manually injected into and extracted from the GStreamer pipeline. diff --git a/tutorial-basic-media-information-gathering.md b/markdown/tutorials/basic/media-information-gathering.md similarity index 97% rename from tutorial-basic-media-information-gathering.md rename to markdown/tutorials/basic/media-information-gathering.md index 2330459..5a9ab66 100644 --- a/tutorial-basic-media-information-gathering.md +++ b/markdown/tutorials/basic/media-information-gathering.md @@ -66,7 +66,7 @@ command line, and outputs the retrieved information (If no URI is provided it uses a default one). This is a simplified version of what the `gst-discoverer-1.0` tool does -([](tutorial-basic-gstreamer-tools.md)), which is +([](tutorials/basic/gstreamer-tools.md)), which is an application that only displays data, but does not perform any playback. @@ -300,11 +300,11 @@ int main (int argc, char **argv) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > ``gcc basic-tutorial-9.c -o basic-tutorial-9 `pkg-config --cflags --libs gstreamer-1.0 gstreamer-pbutils-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial opens the URI passed as the first parameter in the command line (or a default URI if none is provided) and outputs information about it on the screen. If the media is located on the Internet, the application might take a bit to react depending on your connection speed. > diff --git a/tutorial-basic-multithreading-and-pad-availability.md b/markdown/tutorials/basic/multithreading-and-pad-availability.md similarity index 96% rename from tutorial-basic-multithreading-and-pad-availability.md rename to markdown/tutorials/basic/multithreading-and-pad-availability.md index 5cdb3cb..537403b 100644 --- a/tutorial-basic-multithreading-and-pad-availability.md +++ b/markdown/tutorials/basic/multithreading-and-pad-availability.md @@ -39,7 +39,7 @@ of the queue can be controlled through properties. This example builds the following pipeline: -![](attachments/basic-tutorial-7.png) +![](images/tutorials/basic-tutorial-7.png) The source is a synthetic audio signal (a continuous tone) which is split using a `tee` element (it sends through its source pads everything @@ -56,7 +56,7 @@ there is only one thread, being blocked by the first sink. ### Request pads In [Basic tutorial 3: Dynamic -pipelines](tutorial-basic-dynamic-pipelines.md) we saw +pipelines](tutorials/basic/dynamic-pipelines.md) we saw an element (`uridecodebin`) which had no pads to begin with, and they appeared as data started to flow and the element learned about the media. These are called **Sometimes Pads**, and contrast with the @@ -179,11 +179,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > ``gcc basic-tutorial-7.c -o basic-tutorial-7 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial plays an audible tone through the audio card and opens a window with a waveform representation of the tone. The waveform should be a sinusoid, but due to the refreshing of the window might not appear so. > @@ -231,7 +231,7 @@ Small adjustments for better demonstration: The “freq” property of appear almost stationary in the window), and this style and shader for `wavescope` make the wave continuous. Use the `gst-inspect-1.0` tool described in [Basic tutorial 10: GStreamer -tools](tutorial-basic-gstreamer-tools.md) to learn all +tools](tutorials/basic/gstreamer-tools.md) to learn all the properties of these elements. diff --git a/tutorial-basic-platform-specific-elements.md b/markdown/tutorials/basic/platform-specific-elements.md similarity index 98% rename from tutorial-basic-platform-specific-elements.md rename to markdown/tutorials/basic/platform-specific-elements.md index 8b60cb4..d4742f2 100644 --- a/tutorial-basic-platform-specific-elements.md +++ b/markdown/tutorials/basic/platform-specific-elements.md @@ -51,7 +51,7 @@ This audio sink outputs to the sound card via Architecture). This sink is available on almost every Linux platform. It is often seen as a “low level” interface to the sound card, and can be complicated to configure (See the comment on -[](tutorial-playback-digital-audio-pass-through.md)). +[](tutorials/playback/digital-audio-pass-through.md)). ### `pulsesink` @@ -117,7 +117,7 @@ that their pipelines cannot be interconnected. However, through this element, GStreamer can benefit from the decoding elements present in Direct Show. `dshowdecwrapper` wraps multiple Direct Show decoders so they can be embedded in a GStreamer pipeline. Use the `gst-inspect-1.0` tool -(see [](tutorial-basic-gstreamer-tools.md)) to see the +(see [](tutorials/basic/gstreamer-tools.md)) to see the available decoders. ## Android diff --git a/tutorial-basic-playback-speed.md b/markdown/tutorials/basic/playback-speed.md similarity index 96% rename from tutorial-basic-playback-speed.md rename to markdown/tutorials/basic/playback-speed.md index d92a3c9..192f67a 100644 --- a/tutorial-basic-playback-speed.md +++ b/markdown/tutorials/basic/playback-speed.md @@ -30,7 +30,7 @@ media besides changing the subsequent playback rate (only to positive values). Seek Events, additionally, allow jumping to any position in the stream and set positive and negative playback rates. -In [](tutorial-basic-time-management.md) seek +In [](tutorials/basic/time-management.md) seek events have already been shown, using a helper function to hide their complexity. This tutorial explains a bit more how to use these events. @@ -216,11 +216,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > `` gcc basic-tutorial-13.c -o basic-tutorial-13 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial opens a window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. The console shows the available commands, composed of a single upper-case or lower-case letter, which you should input followed by the Enter key. > diff --git a/tutorial-basic-short-cutting-the-pipeline.md b/markdown/tutorials/basic/short-cutting-the-pipeline.md similarity index 96% rename from tutorial-basic-short-cutting-the-pipeline.md rename to markdown/tutorials/basic/short-cutting-the-pipeline.md index 512a97c..c730220 100644 --- a/tutorial-basic-short-cutting-the-pipeline.md +++ b/markdown/tutorials/basic/short-cutting-the-pipeline.md @@ -12,7 +12,7 @@ any time, in a variety of ways. This tutorial shows: - How to access and manipulate this data. -[](tutorial-playback-short-cutting-the-pipeline.md) explains +[](tutorials/playback/short-cutting-the-pipeline.md) explains how to achieve the same goals in a playbin-based pipeline. ## Introduction @@ -68,7 +68,7 @@ this simplified vision should suffice for now. As an example, a `filesrc` (a GStreamer element that reads files) produces buffers with the “ANY” caps and no time-stamping information. -After demuxing (see [](tutorial-basic-dynamic-pipelines.md)) +After demuxing (see [](tutorials/basic/dynamic-pipelines.md)) buffers can have some specific caps, for example “video/x-h264”. After decoding, each buffer will contain a single video frame with raw caps (for example, “video/x-raw-yuv”) and very precise time stamps indicating @@ -76,7 +76,7 @@ when should that frame be displayed. ### This tutorial -This tutorial expands [](tutorial-basic-multithreading-and-pad-availability.md) in +This tutorial expands [](tutorials/basic/multithreading-and-pad-availability.md) in two ways: firstly, the `audiotestsrc` is replaced by an `appsrc` that will generate the audio data. Secondly, a new branch is added to the `tee` so data going into the audio sink and the wave display is also @@ -84,7 +84,7 @@ replicated into an `appsink`. The `appsink` uploads the information back into the application, which then just notifies the user that data has been received, but it could obviously perform more complex tasks. -![](attachments/basic-tutorial-8.png.png) +![](images/tutorials/basic-tutorial-8.png) ## A crude waveform generator @@ -332,11 +332,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > `` gcc basic-tutorial-8.c -o basic-tutorial-8 `pkg-config --cflags --libs gstreamer-1.0 gst-audio-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial plays an audible tone for varying frequency through the audio card and opens a window with a waveform representation of the tone. The waveform should be a sinusoid, but due to the refreshing of the window might not appear so. > @@ -346,7 +346,7 @@ int main(int argc, char *argv[]) { The code to create the pipeline (Lines 131 to 205) is an enlarged version of [Basic tutorial 7: Multithreading and Pad -Availability](tutorial-basic-multithreading-and-pad-availability.md). +Availability](tutorials/basic/multithreading-and-pad-availability.md). It involves instantiating all the elements, link the elements with Always Pads, and manually link the Request Pads of the `tee` element. @@ -495,7 +495,7 @@ gst_buffer_unref (buffer); ``` Once we have the buffer ready, we pass it to `appsrc` with the -`push-buffer` action signal (see information box at the end of [](tutorial-playback-playbin-usage.md)), and then +`push-buffer` action signal (see information box at the end of [](tutorials/playback/playbin-usage.md)), and then `gst_buffer_unref()` it since we no longer need it. ``` c @@ -534,7 +534,7 @@ This tutorial has shown how applications can: - Manipulate this data by accessing the `GstBuffer`. In a playbin-based pipeline, the same goals are achieved in a slightly -different way. [](tutorial-playback-short-cutting-the-pipeline.md) shows +different way. [](tutorials/playback/short-cutting-the-pipeline.md) shows how to do it. It has been a pleasure having you here, and see you soon\! diff --git a/tutorial-basic-streaming.md b/markdown/tutorials/basic/streaming.md similarity index 95% rename from tutorial-basic-streaming.md rename to markdown/tutorials/basic/streaming.md index f6d1d5c..da5072d 100644 --- a/tutorial-basic-streaming.md +++ b/markdown/tutorials/basic/streaming.md @@ -156,11 +156,11 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > `` gcc basic-tutorial-12.c -o basic-tutorial-12 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial opens a window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. In the console window, you should see a buffering message, and playback should only start when the buffering reaches 100%. This percentage might not change at all if your connection is fast enough and buffering is not required. > diff --git a/tutorial-basic-time-management.md b/markdown/tutorials/basic/time-management.md similarity index 97% rename from tutorial-basic-time-management.md rename to markdown/tutorials/basic/time-management.md index 87d4f69..99d9ed1 100644 --- a/tutorial-basic-time-management.md +++ b/markdown/tutorials/basic/time-management.md @@ -197,11 +197,11 @@ static void handle_message (CustomData *data, GstMessage *msg) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > ``gcc basic-tutorial-4.c -o basic-tutorial-4 `pkg-config --cflags --libs gstreamer-1.0` `` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial opens a window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. 10 seconds into the movie it skips to a new position > @@ -231,7 +231,7 @@ move the message handling code to its own function We would then build a pipeline composed of a single element, a `playbin`, which we already saw in [Basic tutorial 1: Hello -world!](tutorial-basic-hello-world.md). However, +world!](tutorials/basic/hello-world.md). However, `playbin` is in itself a pipeline, and in this case it is the only element in the pipeline, so we use directly the `playbin` element. We will skip the details: the URI of the clip is given to `playbin` via diff --git a/tutorial-basic-toolkit-integration.md b/markdown/tutorials/basic/toolkit-integration.md similarity index 98% rename from tutorial-basic-toolkit-integration.md rename to markdown/tutorials/basic/toolkit-integration.md index b203776..99c992c 100644 --- a/tutorial-basic-toolkit-integration.md +++ b/markdown/tutorials/basic/toolkit-integration.md @@ -456,16 +456,16 @@ int main(int argc, char *argv[]) { > ![Information](images/icons/emoticons/information.png) > Need help? > -> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Build), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing-on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: +> If you need help to compile this code, refer to the **Building the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Build), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Build) or [Windows](installing/on-windows.md#InstallingonWindows-Build), or use this specific command on Linux: > > ``gcc basic-tutorial-5.c -o basic-tutorial-5 `pkg-config --cflags --libs gstreamer-interfaces-1.0 gtk+-3.0 gstreamer-1.0`` > ->If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing-on-linux.md#InstallingonLinux-Run), [Mac OS X](installing-on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing-on-windows.md#InstallingonWindows-Run). +>If you need help to run this code, refer to the **Running the tutorials** section for your platform: [Linux](installing/on-linux.md#InstallingonLinux-Run), [Mac OS X](installing/on-mac-osx.md#InstallingonMacOSX-Run) or [Windows](installing/on-windows.md#InstallingonWindows-Run). > > This tutorial opens a GTK+ window and displays a movie, with accompanying audio. The media is fetched from the Internet, so the window might take a few seconds to appear, depending on your connection speed. The Window has some GTK+ buttons to Pause, Stop and Play the movie, and a slider to show the current position of the stream, which can be dragged to change it. Also, information about the stream is shown on a column at the right edge of the window. > > -> Bear in mind that there is no latency management (buffering), so on slow connections, the movie might stop after a few seconds. See how [](tutorial-basic-streaming.md) solves this issue. +> Bear in mind that there is no latency management (buffering), so on slow connections, the movie might stop after a few seconds. See how [](tutorials/basic/streaming.md) solves this issue. > > Required libraries: `gstreamer-video-1.0 gtk+-3.0 gstreamer-1.0` @@ -562,7 +562,7 @@ g_signal_connect (G_OBJECT (bus), "message::application", (GCallback)application gst_object_unref (bus); ``` -In [](tutorial-playback-playbin-usage.md), `gst_bus_add_watch()` is +In [](tutorials/playback/playbin-usage.md), `gst_bus_add_watch()` is used to register a function that receives every message posted to the GStreamer bus. We can achieve a finer granularity by using signals instead, which allow us to register only to the messages we are @@ -718,7 +718,7 @@ slider that allows seeking) can be very easily implemented thanks to GStreamer and GTK+ collaborating. If the slider has been dragged to a new position, tell GStreamer to seek to that position with `gst_element_seek_simple()` (as seen in [Basic tutorial 4: Time -management](tutorial-basic-time-management.md)). The +management](tutorials/basic/time-management.md)). The slider has been setup so its value represents seconds. It is worth mentioning that some performance (and responsiveness) can be @@ -835,7 +835,7 @@ static void application_cb (GstBus *bus, GstMessage *msg, CustomData *data) { ``` Once me made sure it is the `tags-changed` message, we call the -`analyze_streams` function, which is also used in [](tutorial-playback-playbin-usage.md) and is +`analyze_streams` function, which is also used in [](tutorials/playback/playbin-usage.md) and is more detailed there. It basically recovers the tags from the stream and writes them in a text widget in the GUI. @@ -848,7 +848,7 @@ but the required concepts are few and easy. If you have followed the previous tutorials and have a little knowledge of GTK, you probably understood this one can now enjoy your very own media player! -![](attachments/basic-tutorial-5.png) +![](images/tutorials/basic-tutorial-5.png) ## Exercise @@ -856,7 +856,7 @@ If this media player is not good enough for you, try to change the text widget that displays the information about the streams into a proper list view (or tree view). Then, when the user selects a different stream, make GStreamer switch streams! To switch streams, you will need -to read [](tutorial-playback-playbin-usage.md). +to read [](tutorials/playback/playbin-usage.md). ## Conclusion diff --git a/tutorials.md b/markdown/tutorials/index.md similarity index 91% rename from tutorials.md rename to markdown/tutorials/index.md index bbd113a..75b4248 100644 --- a/tutorials.md +++ b/markdown/tutorials/index.md @@ -77,11 +77,11 @@ purposes. - [Sintel, the Durian Open Movie Project] - [installing GStreamer]: installing.md + [installing GStreamer]: installing/index.md [GStreamer documentation]: http://gstreamer.freedesktop.org/documentation/ - [Basic tutorials]: tutorials-basic.md - [Playback tutorials]: tutorials-playback.md - [Android tutorials]: tutorials-android.md - [iOS tutorials]: tutorials-ios.md - [Table of Concepts]: table-of-concepts.md + [Basic tutorials]: tutorials/basic/index.md + [Playback tutorials]: tutorials/playback/index.md + [Android tutorials]: tutorials/android/index.md + [iOS tutorials]: tutorials/ios/index.md + [Table of Concepts]: tutorials/table-of-concepts.md [Sintel, the Durian Open Movie Project]: http://www.sintel.org/ diff --git a/tutorial-ios-a-basic-media-player.md b/markdown/tutorials/ios/a-basic-media-player.md similarity index 98% rename from tutorial-ios-a-basic-media-player.md rename to markdown/tutorials/ios/a-basic-media-player.md index 09eb9e2..c83ebe2 100644 --- a/tutorial-ios-a-basic-media-player.md +++ b/markdown/tutorials/ios/a-basic-media-player.md @@ -14,7 +14,7 @@ iOS device. It shows: Slider](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UISlider_Class/Reference/Reference.html) - How to report the media size to adapt the display surface -It also uses the knowledge gathered in the [](tutorials-basic.md) regarding: +It also uses the knowledge gathered in the [](tutorials/basic/index.md) regarding: - How to use `playbin` to play any kind of media - How to handle network resilience problems @@ -26,7 +26,7 @@ pieces to build a media player. The most complex part is assembling a pipeline which retrieves, decodes and displays the media, but we already know that the `playbin` element can take care of all that for us. We only need to replace the manual pipeline we used in -[](tutorial-ios-video.md) with a single-element `playbin` pipeline +[](tutorials/ios/video.md) with a single-element `playbin` pipeline and we are good to go! However, we can do better than. We will add a [Time @@ -344,7 +344,7 @@ for some kind of streams), or when it is first detected, ``` Here we simply store the new size and ask the layout to be recalculated. -As we have already seen in [](tutorial-ios-a-running-pipeline.md), +As we have already seen in [](tutorials/ios/a-running-pipeline.md), methods which change the UI must be called from the main thread, and we are now in a callback from some GStreamer internal thread. Hence, the usage @@ -352,7 +352,7 @@ of `dispatch_async()`[.](http://developer.android.com/reference/android/app/Acti ### Refreshing the Time Slider -[](tutorial-basic-toolkit-integration.md) has +[](tutorials/basic/toolkit-integration.md) has already shown how to implement a Seek Bar (or [Time Slider](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UISlider_Class/Reference/Reference.html) in this tutorial) using the GTK+ toolkit. The implementation on iOS is @@ -1005,13 +1005,13 @@ static gboolean refresh_ui (GStreamerBackend *self) { ``` If it is unknown, the clip duration is retrieved, as explained in -[](tutorial-basic-time-management.md). The current position is +[](tutorials/basic/time-management.md). The current position is retrieved next, and the UI is informed of both through its `setCurrentUIPosition` callback. Bear in mind that all time-related measures returned by GStreamer are in nanoseconds, whereas, for simplicity, we decided to make the UI code -work in milliseconds. +work in milliseconds. ### Seeking with the Seek Bar @@ -1144,7 +1144,7 @@ calls `execute_seek()` again. ### Network resilience -[](tutorial-basic-streaming.md) has already +[](tutorials/basic/streaming.md) has already shown how to adapt to the variable nature of the network bandwidth by using buffering. The same procedure is used here, by listening to the buffering @@ -1158,7 +1158,7 @@ And pausing the pipeline until buffering is complete (unless this is a live source): - + ``` /* Called when buffering messages are received. We inform the UI about the current buffering level and @@ -1207,4 +1207,4 @@ The next tutorial adds the missing bits to turn the application built here into an acceptable iOS media player. [information]: images/icons/emoticons/information.png - [screenshot]: images/tutorial-ios-a-basic-media-player-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/ios-a-basic-media-player-screenshot.png \ No newline at end of file diff --git a/tutorial-ios-a-complete-media-player.md b/markdown/tutorials/ios/a-complete-media-player.md similarity index 88% rename from tutorial-ios-a-complete-media-player.md rename to markdown/tutorials/ios/a-complete-media-player.md index f13a8a3..68d8014 100644 --- a/tutorial-ios-a-complete-media-player.md +++ b/markdown/tutorials/ios/a-complete-media-player.md @@ -10,7 +10,7 @@ be done with GStreamer on the iOS platform. It is intended to be built and run, rather than analyzed for its pedagogical value, since it adds very little GStreamer knowledge over -what has already been shown in [](tutorial-ios-a-basic-media-player.md). +what has already been shown in [](tutorials/ios/a-basic-media-player.md). It demonstrates the main functionality that a conventional media player has, but it is not a complete application yet, therefore it has not been @@ -31,7 +31,7 @@ are given here. A new `UIView` has been added, derived from `UITableViewController` which shows a list of clips. When one is selected, the -`VideoViewController` from [](tutorial-ios-a-basic-media-player.md) appears +`VideoViewController` from [](tutorials/ios/a-basic-media-player.md) appears and its URI property is set to the URI of the selected clip. The list of clips is populated from three sources: Media from the @@ -60,5 +60,5 @@ already be used to showcase the integration of GStreamer and iOS. It has been a pleasure having you here, and see you soon! - [screenshot0]: images/tutorial-ios-a-complete-media-player-screenshot-0.png - [screenshot1]: images/tutorial-ios-a-complete-media-player-screenshot-1.png + [screenshot0]: images/tutorials/ios-a-complete-media-player-screenshot-0.png + [screenshot1]: images/tutorials/ios-a-complete-media-player-screenshot-1.png diff --git a/tutorial-ios-a-running-pipeline.md b/markdown/tutorials/ios/a-running-pipeline.md similarity index 98% rename from tutorial-ios-a-running-pipeline.md rename to markdown/tutorials/ios/a-running-pipeline.md index 706e6d2..d4edda4 100644 --- a/tutorial-ios-a-running-pipeline.md +++ b/markdown/tutorials/ios/a-running-pipeline.md @@ -4,8 +4,8 @@ ![screenshot] -As seen in the [Basic](tutorials-basic.md) and -[Playback](tutorials-playback.md) tutorials, GStreamer integrates +As seen in the [Basic](tutorials/basic/index.md) and +[Playback](tutorials/playback/index.md) tutorials, GStreamer integrates nicely with GLib’s main loops, so pipeline operation and user interface can be monitored simultaneously in a very simple way. However, platforms like iOS or Android do not use GLib and therefore extra care must be @@ -400,7 +400,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se @end ``` - + #### Interface methods: @@ -522,7 +522,7 @@ static void state_changed_cb (GstBus *bus, GstMessage *msg, GStreamerBackend *se The `error_cb()` and `state_changed_cb()` are callbacks registered to the `error` and `state-changed` events in GStreamer, and their goal is to inform the user about these events. These callbacks have been widely -used in the [Basic tutorials](tutorials-basic.md) and their +used in the [Basic tutorials](tutorials/basic/index.md) and their implementation is very similar, except for two points: Firstly, the messages are conveyed to the user through the @@ -605,7 +605,7 @@ elements. These lines create a bus signal watch and connect to some interesting signals, just like we have been doing in the [Basic -tutorials](tutorials-basic.md). The creation of the watch is done +tutorials](tutorials/basic/index.md). The creation of the watch is done step by step instead of using `gst_bus_add_signal_watch()` to exemplify how to use a custom GLib context. The interesting bit here is the usage of a @@ -656,4 +656,4 @@ to them! It has been a pleasure having you here, and see you soon! - [screenshot]: images/tutorial-ios-a-running-pipeline-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/ios-a-running-pipeline-screenshot.png \ No newline at end of file diff --git a/tutorials-ios.md b/markdown/tutorials/ios/index.md similarity index 81% rename from tutorials-ios.md rename to markdown/tutorials/ios/index.md index a45d3f5..4267a48 100644 --- a/tutorials-ios.md +++ b/markdown/tutorials/ios/index.md @@ -4,17 +4,17 @@ These tutorials describe iOS-specific topics. General GStreamer concepts will not be explained in these tutorials, so the -[](tutorials-basic.md) should be reviewed first. The reader should +[](tutorials/basic/index.md) should be reviewed first. The reader should also be familiar with basic iOS programming techniques. The iOS tutorials have the same structure as the -[](tutorials-android.md): Each one builds on top of the previous +[](tutorials/android/index.md): Each one builds on top of the previous one and adds progressively more functionality, until a working media player application is obtained in -[](tutorial-ios-a-complete-media-player.md). +[](tutorials/ios/a-complete-media-player.md). Make sure to have read the instructions in -[](installing-for-ios-development.md) before jumping into the iOS +[](installing/for-ios-development.md) before jumping into the iOS tutorials. All iOS tutorials are split into the following classes: diff --git a/tutorial-ios-link-against-gstreamer.md b/markdown/tutorials/ios/link-against-gstreamer.md similarity index 97% rename from tutorial-ios-link-against-gstreamer.md rename to markdown/tutorials/ios/link-against-gstreamer.md index 24a8da8..9bb958b 100644 --- a/tutorial-ios-link-against-gstreamer.md +++ b/markdown/tutorials/ios/link-against-gstreamer.md @@ -28,7 +28,7 @@ The UI uses storyboards and contains a single `View` with a centered ``` #import - + @interface ViewController : UIViewController { IBOutlet UILabel *label; } @@ -49,7 +49,7 @@ few C-to-Objective-C conversions that might be necessary (like `char *` to `NSString *`, for example). This eases the usage of this class by the UI code, which is typically made in pure Objective-C. `GStreamerBackend` serves exactly the same purpose as the JNI code in -the [](tutorials-android.md). +the [](tutorials/android/index.md). **GStreamerBackend.m** @@ -133,4 +133,4 @@ taken when developing specifically for the iOS platform. It has been a pleasure having you here, and see you soon! - [screenshot]: images/tutorial-ios-link-against-gstreamer-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/ios-link-against-gstreamer-screenshot.png \ No newline at end of file diff --git a/tutorial-ios-video.md b/markdown/tutorials/ios/video.md similarity index 98% rename from tutorial-ios-video.md rename to markdown/tutorials/ios/video.md index d01c725..6cd8d0d 100644 --- a/tutorial-ios-video.md +++ b/markdown/tutorials/ios/video.md @@ -4,7 +4,7 @@ ![screenshot] -Except for [](tutorial-basic-toolkit-integration.md), +Except for [](tutorials/basic/toolkit-integration.md), which embedded a video window on a GTK application, all tutorials so far relied on GStreamer video sinks to create a window to display their contents. The video sink on iOS is not capable of creating its own @@ -20,7 +20,7 @@ Since iOS does not provide a windowing system, a GStreamer video sink cannot create pop-up windows as it would do on a Desktop platform. Fortunately, the `VideoOverlay` interface allows providing video sinks with an already created window onto which they can draw, as we have seen -in [](tutorial-basic-toolkit-integration.md). +in [](tutorials/basic/toolkit-integration.md). In this tutorial, a `UIView` widget (actually, a subclass of it) is placed on the main storyboard. In the `viewDidLoad` method of the @@ -516,7 +516,7 @@ ask for it immediately. The `gst_bin_get_by_interface()` method will examine the whole pipeline and return a pointer to an element which supports the requested interface. We are asking for the `VideoOverlay` interface, explained in -[](tutorial-basic-toolkit-integration.md), +[](tutorials/basic/toolkit-integration.md), which controls how to perform rendering into foreign (non-GStreamer) windows. The internal video sink instantiated by `autovideosink` is the only element in this pipeline implementing it, so it will be returned. @@ -575,4 +575,4 @@ to this tutorial in order to build a simple media player. It has been a pleasure having you here, and see you soon! - [screenshot]: images/tutorial-ios-video-screenshot.png \ No newline at end of file + [screenshot]: images/tutorials/ios-video-screenshot.png \ No newline at end of file diff --git a/tutorial-playback-audio-visualization.md b/markdown/tutorials/playback/audio-visualization.md similarity index 95% rename from tutorial-playback-audio-visualization.md rename to markdown/tutorials/playback/audio-visualization.md index f9c8167..86f950b 100644 --- a/tutorial-playback-audio-visualization.md +++ b/markdown/tutorials/playback/audio-visualization.md @@ -240,15 +240,15 @@ This tutorial has shown: - How to enable Audio Visualization in `playbin` with the `GST_PLAY_FLAG_VIS` flag - How to enforce one particular visualization element with the - `vis-plugin` `playbin` property + `vis-plugin` `playbin` property It has been a pleasure having you here, and see you soon\! [information]: images/icons/emoticons/information.png - [Mac]: installing-on-mac-osx.md - [Windows]: installing-on-windows.md - [Mac OS X]: installing-on-mac-osx.md#building-the-tutorials - [1]: installing-on-windows.md#running-the-tutorials - [iOS]: installing-for-ios-development.md#building-the-tutorials - [android]: installing-for-android-development.md#building-the-tutorials + [Mac]: installing/on-mac-osx.md + [Windows]: installing/on-windows.md + [Mac OS X]: installing/on-mac-osx.md#building-the-tutorials + [1]: installing/on-windows.md#running-the-tutorials + [iOS]: installing/for-ios-development.md#building-the-tutorials + [android]: installing/for-android-development.md#building-the-tutorials [warning]: images/icons/emoticons/warning.png diff --git a/tutorial-playback-color-balance.md b/markdown/tutorials/playback/color-balance.md similarity index 96% rename from tutorial-playback-color-balance.md rename to markdown/tutorials/playback/color-balance.md index 262f7e3..03725e8 100644 --- a/tutorial-playback-color-balance.md +++ b/markdown/tutorials/playback/color-balance.md @@ -10,7 +10,7 @@ This tutorial shows: - How to change them ## Introduction -[](tutorial-basic-toolkit-integration.md) has +[](tutorials/basic/toolkit-integration.md) has already explained the concept of GObject interfaces: applications use them to find out if certain functionality is available, regardless of the actual element which implements it. @@ -298,10 +298,10 @@ It has been a pleasure having you here, and see you soon\! [information]: images/icons/emoticons/information.png - [Mac]: installing-on-mac-osx.md - [Windows]: installing-on-windows.md - [Mac OS X]: installing-on-mac-osx.md#building-the-tutorials - [1]: installing-on-windows.md#running-the-tutorials - [iOS]: installing-for-ios-development.md#building-the-tutorials - [android]: installing-for-android-development.md#building-the-tutorials + [Mac]: installing/on-mac-osx.md + [Windows]: installing/on-windows.md + [Mac OS X]: installing/on-mac-osx.md#building-the-tutorials + [1]: installing/on-windows.md#running-the-tutorials + [iOS]: installing/for-ios-development.md#building-the-tutorials + [android]: installing/for-android-development.md#building-the-tutorials [warning]: images/icons/emoticons/warning.png diff --git a/tutorial-playback-custom-playbin-sinks.md b/markdown/tutorials/playback/custom-playbin-sinks.md similarity index 95% rename from tutorial-playback-custom-playbin-sinks.md rename to markdown/tutorials/playback/custom-playbin-sinks.md index d648922..c591f1f 100644 --- a/tutorial-playback-custom-playbin-sinks.md +++ b/markdown/tutorials/playback/custom-playbin-sinks.md @@ -156,7 +156,7 @@ Now we need to create a Ghost Pad so this partial pipeline inside the Bin can be connected to the outside. This Ghost Pad will be connected to a Pad in one of the internal Elements (the sink pad of the equalizer), so we retrieve this Pad with `gst_element_get_static_pad()`. Remember -from [](tutorial-basic-multithreading-and-pad-availability.md) that +from [](tutorials/basic/multithreading-and-pad-availability.md) that if this was a Request Pad instead of an Always Pad, we would need to use `gst_element_request_pad()`. @@ -212,10 +212,10 @@ This tutorial has shown: It has been a pleasure having you here, and see you soon\! [information]: images/icons/emoticons/information.png - [Mac]: installing-on-mac-osx.md - [Windows]: installing-on-windows.md - [Mac OS X]: installing-on-mac-osx.md#building-the-tutorials - [1]: installing-on-windows.md#running-the-tutorials - [iOS]: installing-for-ios-development.md#building-the-tutorials - [android]: installing-for-android-development.md#building-the-tutorials + [Mac]: installing/on-mac-osx.md + [Windows]: installing/on-windows.md + [Mac OS X]: installing/on-mac-osx.md#building-the-tutorials + [1]: installing/on-windows.md#running-the-tutorials + [iOS]: installing/for-ios-development.md#building-the-tutorials + [android]: installing/for-android-development.md#building-the-tutorials [warning]: images/icons/emoticons/warning.png diff --git a/tutorial-playback-digital-audio-pass-through.md b/markdown/tutorials/playback/digital-audio-pass-through.md similarity index 97% rename from tutorial-playback-digital-audio-pass-through.md rename to markdown/tutorials/playback/digital-audio-pass-through.md index 93927c0..b1317d5 100644 --- a/tutorial-playback-digital-audio-pass-through.md +++ b/markdown/tutorials/playback/digital-audio-pass-through.md @@ -77,8 +77,8 @@ enabled, but, unfortunately, this option is not available in all audio drivers. Another solution involves, using a custom sinkbin (see -[](tutorial-playback-custom-playbin-sinks.md)) which includes a -`capsfilter` element (see [](tutorial-basic-handy-elements.md)) +[](tutorials/playback/custom-playbin-sinks.md)) which includes a +`capsfilter` element (see [](tutorials/basic/handy-elements.md)) and an audio sink. The caps that the external decoder supports are then set in the capsfiler so the wrong format is not output. This allows the application to enforce the appropriate format instead of diff --git a/tutorial-playback-hardware-accelerated-video-decoding.md b/markdown/tutorials/playback/hardware-accelerated-video-decoding.md similarity index 100% rename from tutorial-playback-hardware-accelerated-video-decoding.md rename to markdown/tutorials/playback/hardware-accelerated-video-decoding.md diff --git a/tutorials-playback.md b/markdown/tutorials/playback/index.md similarity index 100% rename from tutorials-playback.md rename to markdown/tutorials/playback/index.md diff --git a/tutorial-playback-playbin-usage.md b/markdown/tutorials/playback/playbin-usage.md similarity index 98% rename from tutorial-playback-playbin-usage.md rename to markdown/tutorials/playback/playbin-usage.md index e747687..61a66c1 100644 --- a/tutorial-playback-playbin-usage.md +++ b/markdown/tutorials/playback/playbin-usage.md @@ -509,7 +509,7 @@ g_object_get (data->playbin, "current-text", &data->current_text, NULL); Once we have extracted all the metadata we want, we get the streams that are currently selected through 3 more properties of `playbin`: -`current-video`, `current-audio` and `current-text`. +`current-video`, `current-audio` and `current-text`. It is interesting to always check the currently selected streams and never make any assumption. Multiple internal conditions can make @@ -579,11 +579,11 @@ code of the tutorial and any accessory files needed to build it. It has been a pleasure having you here, and see you soon! - [Playback tutorial 2: Subtitle management]: tutorial-playback-subtitle-management.md + [Playback tutorial 2: Subtitle management]: tutorials/playback/subtitle-management.md [information]: images/icons/emoticons/information.png - [Mac]: installing-on-mac-osx.md - [Windows]: installing-on-windows.md - [Mac OS X]: installing-on-mac-osx.md#building-the-tutorials - [1]: installing-on-windows.md#running-the-tutorials - [iOS]: installing-for-ios-development.md#building-the-tutorials - [android]: installing-for-android-development.md#building-the-tutorials + [Mac]: installing/on-mac-osx.md + [Windows]: installing/on-windows.md + [Mac OS X]: installing/on-mac-osx.md#building-the-tutorials + [1]: installing/on-windows.md#running-the-tutorials + [iOS]: installing/for-ios-development.md#building-the-tutorials + [android]: installing/for-android-development.md#building-the-tutorials diff --git a/tutorial-playback-progressive-streaming.md b/markdown/tutorials/playback/progressive-streaming.md similarity index 95% rename from tutorial-playback-progressive-streaming.md rename to markdown/tutorials/playback/progressive-streaming.md index 75723a7..ea3b16f 100644 --- a/tutorial-playback-progressive-streaming.md +++ b/markdown/tutorials/playback/progressive-streaming.md @@ -2,10 +2,10 @@ ## Goal -[](tutorial-basic-streaming.md) showed how to +[](tutorials/basic/streaming.md) showed how to enhance the user experience in poor network conditions, by taking buffering into account. This tutorial further expands -[](tutorial-basic-streaming.md) by enabling +[](tutorials/basic/streaming.md) by enabling the local storage of the streamed media, and describes the advantages of this technique. In particular, it shows: @@ -18,7 +18,7 @@ this technique. In particular, it shows: When streaming, data is fetched from the network and a small buffer of future-data is kept to ensure smooth playback (see -[](tutorial-basic-streaming.md)). However, data +[](tutorials/basic/streaming.md)). However, data is discarded as soon as it is displayed or rendered (there is no past-data buffer). This means, that if a user wants to jump back and continue playback from a point in the past, data needs to be @@ -240,7 +240,7 @@ int main(int argc, char *argv[]) { ## Walkthrough -This code is based on that of [](tutorial-basic-streaming.md). Let’s review +This code is based on that of [](tutorials/basic/streaming.md). Let’s review only the differences. ### Setup @@ -322,7 +322,7 @@ static gboolean refresh_ui (CustomData *data) { The first thing we do in `refresh_ui` is construct a new Buffering `GstQuery` with `gst_query_new_buffering()` and pass it to the pipeline -(`playbin`) with `gst_element_query()`. In [](tutorial-basic-time-management.md) we have +(`playbin`) with `gst_element_query()`. In [](tutorials/basic/time-management.md) we have already seen how to perform simple queries like Position and Duration using specific methods. More complex queries, like Buffering, need to use the more general `gst_element_query()`. @@ -419,10 +419,10 @@ This tutorial has shown: It has been a pleasure having you here, and see you soon! [information]: images/icons/emoticons/information.png - [Mac]: installing-on-mac-osx.md - [Windows]: installing-on-windows.md - [Mac OS X]: installing-on-mac-osx.md#building-the-tutorials - [1]: installing-on-windows.md#running-the-tutorials - [iOS]: installing-for-ios-development.md#building-the-tutorials - [android]: installing-for-android-development.md#building-the-tutorials + [Mac]: installing/on-mac-osx.md + [Windows]: installing/on-windows.md + [Mac OS X]: installing/on-mac-osx.md#building-the-tutorials + [1]: installing/on-windows.md#running-the-tutorials + [iOS]: installing/for-ios-development.md#building-the-tutorials + [android]: installing/for-android-development.md#building-the-tutorials [warning]: images/icons/emoticons/warning.png diff --git a/tutorial-playback-short-cutting-the-pipeline.md b/markdown/tutorials/playback/short-cutting-the-pipeline.md similarity index 95% rename from tutorial-playback-short-cutting-the-pipeline.md rename to markdown/tutorials/playback/short-cutting-the-pipeline.md index 7aa4a2f..be7e41e 100644 --- a/tutorial-playback-short-cutting-the-pipeline.md +++ b/markdown/tutorials/playback/short-cutting-the-pipeline.md @@ -2,11 +2,11 @@ ## Goal -[](tutorial-basic-short-cutting-the-pipeline.md) showed +[](tutorials/basic/short-cutting-the-pipeline.md) showed how an application can manually extract or inject data into a pipeline by using two special elements called `appsrc` and `appsink`. `playbin` allows using these elements too, but the method to connect -them is different. To connect an `appsink` to `playbin` see [](tutorial-playback-custom-playbin-sinks.md). +them is different. To connect an `appsink` to `playbin` see [](tutorials/playback/custom-playbin-sinks.md). This tutorial shows: - How to connect `appsrc` with `playbin` @@ -219,10 +219,10 @@ static void source_setup (GstElement *pipeline, GstElement *source, CustomData * ``` The configuration of the `appsrc` is exactly the same as in -[](tutorial-basic-short-cutting-the-pipeline.md): +[](tutorials/basic/short-cutting-the-pipeline.md): the caps are set to `audio/x-raw`, and two callbacks are registered, so the element can tell the application when it needs to start and stop -pushing data. See [](tutorial-basic-short-cutting-the-pipeline.md) +pushing data. See [](tutorials/basic/short-cutting-the-pipeline.md) for more details. From this point onwards, `playbin` takes care of the rest of the @@ -230,12 +230,12 @@ pipeline, and the application only needs to worry about generating more data when told so. To learn how data can be extracted from `playbin` using the -`appsink` element, see [](tutorial-playback-custom-playbin-sinks.md). +`appsink` element, see [](tutorials/playback/custom-playbin-sinks.md). ## Conclusion This tutorial applies the concepts shown in -[](tutorial-basic-short-cutting-the-pipeline.md) to +[](tutorials/basic/short-cutting-the-pipeline.md) to `playbin`. In particular, it has shown: - How to connect `appsrc` with `playbin` using the special diff --git a/tutorial-playback-subtitle-management.md b/markdown/tutorials/playback/subtitle-management.md similarity index 98% rename from tutorial-playback-subtitle-management.md rename to markdown/tutorials/playback/subtitle-management.md index 9dc5872..6c0db31 100644 --- a/tutorial-playback-subtitle-management.md +++ b/markdown/tutorials/playback/subtitle-management.md @@ -286,14 +286,14 @@ static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomDa > page._ Bear in mind that > there is no latency management (buffering), so on slow connections, > the movie might stop after a few seconds. See how -> [](tutorial-basic-streaming.md) solves this issue. +> [](tutorials/basic/streaming.md) solves this issue. > > Required libraries: `gstreamer-1.0` ## Walkthrough This tutorial is copied from -[](tutorial-playback-playbin-usage.md) with some changes, so let's +[](tutorials/playback/playbin-usage.md) with some changes, so let's review only the changes. ``` c @@ -348,7 +348,7 @@ The available stretch styles are: Ultra-Condensed, Extra-Condensed, Condensed, Semi-Condensed, Normal, Semi-Expanded, Expanded, Extra-Expanded, Ultra-Expanded - + ``` c /* Set flags to show Audio, Video and Subtitles */ @@ -359,7 +359,7 @@ g_object_set (data.playbin, "flags", flags, NULL); We set the `flags` property to allow Audio, Video and Text (Subtitles). -The rest of the tutorial is the same as [](tutorial-playback-playbin-usage.md), except +The rest of the tutorial is the same as [](tutorials/playback/playbin-usage.md), except that the keyboard input changes the `current-text` property instead of the `current-audio`. As before, keep in mind that stream changes are not immediate, since there is a lot of information flowing through the diff --git a/tutorial-qt-tutorials.md b/markdown/tutorials/qt-tutorials.md similarity index 80% rename from tutorial-qt-tutorials.md rename to markdown/tutorials/qt-tutorials.md index e88c60c..fedc8ae 100644 --- a/tutorial-qt-tutorials.md +++ b/markdown/tutorials/qt-tutorials.md @@ -4,11 +4,11 @@ These tutorials describe Qt-specific topics. General GStreamer concepts will not be explained in these tutorials, so the [Basic -tutorials](tutorials-basic.md) should +tutorials](tutorials/basic/index.md) should be reviewed first. The reader should also be familiar with basic Qt programming techniques. The Qt tutorials have the same structure as the [Android -tutorials](tutorials-android.md): Each one builds on top of the +tutorials](tutorials/android/index.md): Each one builds on top of the previous one and adds progressively more functionality, until a working media player application is obtained in \#FIXME\# diff --git a/table-of-concepts.md b/markdown/tutorials/table-of-concepts.md similarity index 62% rename from table-of-concepts.md rename to markdown/tutorials/table-of-concepts.md index a84c242..10d7074 100644 --- a/table-of-concepts.md +++ b/markdown/tutorials/table-of-concepts.md @@ -28,16 +28,16 @@ concepts is discussed. - Tools: [Basic tutorial 10: GStreamer tools] - Threads: [Basic tutorial 7: Multithreading and Pad Availability] - [Playback tutorial 1: Playbin usage]: tutorial-playback-playbin-usage.md - [Basic tutorial 8: Short-cutting the pipeline]: tutorial-basic-short-cutting-the-pipeline.md - [Basic tutorial 2: GStreamer concepts]: tutorial-basic-concepts.md - [Basic tutorial 6: Media formats and Pad Capabilities]: tutorial-basic-media-formats-and-pad-capabilities.md - [Basic tutorial 11: Debugging tools]: tutorial-basic-debugging-tools.md - [Basic tutorial 9: Media information gathering]: tutorial-basic-media-information-gathering.md - [Basic tutorial 10: GStreamer tools]: tutorial-basic-gstreamer-tools.md - [gst-launch-1.0]: tool-gst-launch.md - [Basic tutorial 5: GUI toolkit integration]: tutorial-basic-toolkit-integration.md - [Basic tutorial 3: Dynamic pipelines]: tutorial-basic-dynamic-pipelines.md - [Basic tutorial 7: Multithreading and Pad Availability]: tutorial-basic-multithreading-and-pad-availability.md - [Basic tutorial 4: Time management]: tutorial-basic-time-management.md - [Playback tutorial 2: Subtitle management]: tutorial-playback-subtitle-management.md + [Playback tutorial 1: Playbin usage]: tutorials/playback/playbin-usage.md + [Basic tutorial 8: Short-cutting the pipeline]: tutorials/basic/short-cutting-the-pipeline.md + [Basic tutorial 2: GStreamer concepts]: tutorials/basic/concepts.md + [Basic tutorial 6: Media formats and Pad Capabilities]: tutorials/basic/media-formats-and-pad-capabilities.md + [Basic tutorial 11: Debugging tools]: tutorials/basic/debugging-tools.md + [Basic tutorial 9: Media information gathering]: tutorials/basic/media-information-gathering.md + [Basic tutorial 10: GStreamer tools]: tutorials/basic/gstreamer-tools.md + [gst-launch-1.0]: tools/gst-launch.md + [Basic tutorial 5: GUI toolkit integration]: tutorials/basic/toolkit-integration.md + [Basic tutorial 3: Dynamic pipelines]: tutorials/basic/dynamic-pipelines.md + [Basic tutorial 7: Multithreading and Pad Availability]: tutorials/basic/multithreading-and-pad-availability.md + [Basic tutorial 4: Time management]: tutorials/basic/time-management.md + [Playback tutorial 2: Subtitle management]: tutorials/playback/subtitle-management.md diff --git a/sitemap.txt b/sitemap.txt index a12ca27..77b107a 100644 --- a/sitemap.txt +++ b/sitemap.txt @@ -1,128 +1,128 @@ index.md - installing.md - installing-for-android-development.md - installing-for-ios-development.md - installing-on-mac-osx.md - installing-on-windows.md - installing-on-linux.md - building-from-source-using-cerbero.md - manual-index.md - manual-introduction.md - manual-gstreamer.md - manual-motivation.md - manual-intro-basics.md - manual-building.md - manual-init.md - manual-elements.md - manual-bins.md - manual-bus.md - manual-pads.md - manual-data.md - manual-helloworld.md - manual-advanced.md - manual-queryevents.md - manual-metadata.md - manual-interfaces.md - manual-clocks.md - manual-buffering.md - manual-dparams.md - manual-threads.md - manual-autoplugging.md - manual-dataaccess.md - manual-highlevel.md - manual-playback-components.md - manual-appendices.md - manual-programs.md - manual-compiling.md - manual-checklist-element.md - manual-porting.md - manual-porting-1.0.md - manual-integration.md - manual-licensing.md - manual-quotes.md - tutorials.md - tutorials-basic.md - tutorial-basic-hello-world.md - tutorial-basic-concepts.md - tutorial-basic-dynamic-pipelines.md - tutorial-basic-time-management.md - tutorial-basic-toolkit-integration.md - tutorial-basic-media-formats-and-pad-capabilities.md - tutorial-basic-multithreading-and-pad-availability.md - tutorial-basic-short-cutting-the-pipeline.md - tutorial-basic-media-information-gathering.md - tutorial-basic-gstreamer-tools.md - tutorial-basic-debugging-tools.md - tutorial-basic-streaming.md - tutorial-basic-playback-speed.md - tutorial-basic-handy-elements.md - tutorial-basic-platform-specific-elements.md - tutorials-playback.md - tutorial-playback-playbin-usage.md - tutorial-playback-subtitle-management.md - tutorial-playback-short-cutting-the-pipeline.md - tutorial-playback-progressive-streaming.md - tutorial-playback-color-balance.md - tutorial-playback-audio-visualization.md - tutorial-playback-custom-playbin-sinks.md - tutorial-playback-hardware-accelerated-video-decoding.md - tutorial-playback-digital-audio-pass-through.md - tutorials-android.md - tutorial-android-link-against-gstreamer.md - tutorial-android-a-running-pipeline.md - tutorial-android-video.md - tutorial-android-media-player.md - tutorial-android-a-complete-media-player.md - tutorials-ios.md - tutorial-ios-link-against-gstreamer.md - tutorial-ios-a-running-pipeline.md - tutorial-ios-video.md - tutorial-ios-a-basic-media-player.md - tutorial-ios-a-complete-media-player.md - table-of-concepts.md - deploying-your-application.md - deploying-mac-osx.md - deploying-windows.md - deploying-multiplatform-using-cerbero.md - gstreamer-command-line-tools.md - tool-gst-inspect.md - tool-gst-launch.md - tool-ges-launch.md - pwg-index.md - pwg-introduction.md - pwg-intro-preface.md - pwg-intro-basics.md - pwg-building.md - pwg-building-boiler.md - pwg-building-pads.md - pwg-building-chainfn.md - pwg-building-eventfn.md - pwg-building-queryfn.md - pwg-statemanage-states.md - pwg-building-args.md - pwg-building-signals.md - pwg-building-testapp.md - pwg-advanced.md - pwg-advanced-request.md - pwg-scheduling.md - pwg-negotiation.md - pwg-allocation.md - pwg-building-types.md - pwg-advanced-events.md - pwg-advanced-clock.md - pwg-advanced-qos.md - pwg-dparams.md - pwg-advanced-interfaces.md - pwg-advanced-tagging.md - pwg-other.md - pwg-other-base.md - pwg-other-oneton.md - pwg-other-ntoone.md - pwg-other-manager.md - pwg-appendix.md - pwg-checklist-element.md - pwg-porting.md - pwg-porting-1_0.md - pwg-licensing-advisory.md + installing/index.md + installing/for-android-development.md + installing/for-ios-development.md + installing/on-mac-osx.md + installing/on-windows.md + installing/on-linux.md + installing/building-from-source-using-cerbero.md + manual/index.md + manual/introduction/index.md + manual/introduction/gstreamer.md + manual/introduction/motivation.md + manual/introduction/basics.md + manual/building/index.md + manual/building/init.md + manual/building/elements.md + manual/building/bins.md + manual/building/bus.md + manual/building/pads.md + manual/building/data.md + manual/building/helloworld.md + manual/advanced/index.md + manual/advanced/queryevents.md + manual/advanced/metadata.md + manual/advanced/interfaces.md + manual/advanced/clocks.md + manual/advanced/buffering.md + manual/advanced/dparams.md + manual/advanced/threads.md + manual/advanced/autoplugging.md + manual/advanced/dataaccess.md + manual/highlevel/index.md + manual/highlevel/playback-components.md + manual/appendix/index.md + manual/appendix/programs.md + manual/appendix/compiling.md + manual/appendix/checklist-element.md + manual/appendix/porting.md + manual/appendix/porting-1.0.md + manual/appendix/integration.md + manual/appendix/licensing.md + manual/appendix/quotes.md + tutorials/index.md + tutorials/basic/index.md + tutorials/basic/hello-world.md + tutorials/basic/concepts.md + tutorials/basic/dynamic-pipelines.md + tutorials/basic/time-management.md + tutorials/basic/toolkit-integration.md + tutorials/basic/media-formats-and-pad-capabilities.md + tutorials/basic/multithreading-and-pad-availability.md + tutorials/basic/short-cutting-the-pipeline.md + tutorials/basic/media-information-gathering.md + tutorials/basic/gstreamer-tools.md + tutorials/basic/debugging-tools.md + tutorials/basic/streaming.md + tutorials/basic/playback-speed.md + tutorials/basic/handy-elements.md + tutorials/basic/platform-specific-elements.md + tutorials/playback/index.md + tutorials/playback/playbin-usage.md + tutorials/playback/subtitle-management.md + tutorials/playback/short-cutting-the-pipeline.md + tutorials/playback/progressive-streaming.md + tutorials/playback/color-balance.md + tutorials/playback/audio-visualization.md + tutorials/playback/custom-playbin-sinks.md + tutorials/playback/hardware-accelerated-video-decoding.md + tutorials/playback/digital-audio-pass-through.md + tutorials/android/index.md + tutorials/android/link-against-gstreamer.md + tutorials/android/a-running-pipeline.md + tutorials/android/video.md + tutorials/android/media-player.md + tutorials/android/a-complete-media-player.md + tutorials/ios/index.md + tutorials/ios/link-against-gstreamer.md + tutorials/ios/a-running-pipeline.md + tutorials/ios/video.md + tutorials/ios/a-basic-media-player.md + tutorials/ios/a-complete-media-player.md + tutorials/table-of-concepts.md + deploying/index.md + deploying/mac-osx.md + deploying/windows.md + deploying/multiplatform-using-cerbero.md + tools/index.md + tools/gst-inspect.md + tools/gst-launch.md + tools/ges-launch.md + pwg/index.md + pwg/introduction/index.md + pwg/introduction/preface.md + pwg/introduction/basics.md + pwg/building/index.md + pwg/building/boiler.md + pwg/building/pads.md + pwg/building/chainfn.md + pwg/building/eventfn.md + pwg/building/queryfn.md + pwg/building/statemanage-states.md + pwg/building/args.md + pwg/building/signals.md + pwg/building/testapp.md + pwg/advanced/index.md + pwg/advanced/request.md + pwg/advanced/scheduling.md + pwg/advanced/negotiation.md + pwg/advanced/allocation.md + pwg/advanced/building-types.md + pwg/advanced/events.md + pwg/advanced/clock.md + pwg/advanced/qos.md + pwg/advanced/dparams.md + pwg/advanced/interfaces.md + pwg/advanced/tagging.md + pwg/other/index.md + pwg/other/base.md + pwg/other/oneton.md + pwg/other/ntoone.md + pwg/other/manager.md + pwg/appendix/index.md + pwg/appendix/checklist-element.md + pwg/appendix/porting.md + pwg/appendix/porting-1_0.md + pwg/appendix/licensing-advisory.md splitup.md rtp.md diff --git a/extra_theme/images/favicon.png b/theme/extra/images/favicon.png similarity index 100% rename from extra_theme/images/favicon.png rename to theme/extra/images/favicon.png diff --git a/extra_theme/images/gstreamer-logo.svg b/theme/extra/images/gstreamer-logo.svg similarity index 100% rename from extra_theme/images/gstreamer-logo.svg rename to theme/extra/images/gstreamer-logo.svg diff --git a/extra_theme/templates/extra_head.html b/theme/extra/templates/extra_head.html similarity index 100% rename from extra_theme/templates/extra_head.html rename to theme/extra/templates/extra_head.html diff --git a/extra_theme/templates/navbar.html b/theme/extra/templates/navbar.html similarity index 100% rename from extra_theme/templates/navbar.html rename to theme/extra/templates/navbar.html diff --git a/hotdoc_bootstrap_theme b/theme/hotdoc_bootstrap_theme similarity index 100% rename from hotdoc_bootstrap_theme rename to theme/hotdoc_bootstrap_theme diff --git a/less/variables.less b/theme/less/variables.less similarity index 100% rename from less/variables.less rename to theme/less/variables.less diff --git a/tutorials/android-tutorial-5/jni/Application.mk b/tutorials/android-tutorial-5/jni/Application.mk deleted file mode 100644 index 8e7b0ef..0000000 --- a/tutorials/android-tutorial-5/jni/Application.mk +++ /dev/null @@ -1,2 +0,0 @@ -APP_ABI = armeabi armeabi-v7a arm64-v8a x86 x86_64 - diff --git a/tutorials/xcode iOS/Tutorial 5/AppDelegate.m b/tutorials/xcode iOS/Tutorial 5/AppDelegate.m deleted file mode 100644 index 31ef04e..0000000 --- a/tutorials/xcode iOS/Tutorial 5/AppDelegate.m +++ /dev/null @@ -1,38 +0,0 @@ -#import "AppDelegate.h" - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ - // Override point for customization after application launch. - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application -{ - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application -{ - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application -{ - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application -{ - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - -@end diff --git a/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings b/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings deleted file mode 100644 index 477b28f..0000000 --- a/tutorials/xcode iOS/Tutorial 5/en.lproj/InfoPlist.strings +++ /dev/null @@ -1,2 +0,0 @@ -/* Localized versions of Info.plist keys */ - diff --git a/tutorials/xcode iOS/Tutorial 5/fonts.conf b/tutorials/xcode iOS/Tutorial 5/fonts.conf deleted file mode 100644 index 6b780ea..0000000 --- a/tutorials/xcode iOS/Tutorial 5/fonts.conf +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - mono - - - monospace - - - - - - - sans serif - - - sans-serif - - - - - - - sans - - - sans-serif - - - - - - - 0x0020 - 0x00A0 - 0x00AD - 0x034F - 0x0600 - 0x0601 - 0x0602 - 0x0603 - 0x06DD - 0x070F - 0x115F - 0x1160 - 0x1680 - 0x17B4 - 0x17B5 - 0x180E - 0x2000 - 0x2001 - 0x2002 - 0x2003 - 0x2004 - 0x2005 - 0x2006 - 0x2007 - 0x2008 - 0x2009 - 0x200A - 0x200B - 0x200C - 0x200D - 0x200E - 0x200F - 0x2028 - 0x2029 - 0x202A - 0x202B - 0x202C - 0x202D - 0x202E - 0x202F - 0x205F - 0x2060 - 0x2061 - 0x2062 - 0x2063 - 0x206A - 0x206B - 0x206C - 0x206D - 0x206E - 0x206F - 0x2800 - 0x3000 - 0x3164 - 0xFEFF - 0xFFA0 - 0xFFF9 - 0xFFFA - 0xFFFB - - - - 30 - - - - - -- 2.7.4