├── .gitignore
├── LICENSE
├── README.md
├── app
├── build.gradle
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wass08
│ │ └── vlcsimpleplayer
│ │ └── ApplicationTest.java
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ ├── com
│ │ └── wass08
│ │ │ └── vlcsimpleplayer
│ │ │ ├── FullscreenVlcPlayer.java
│ │ │ ├── MediaSelector.java
│ │ │ └── util
│ │ │ ├── SystemUiHider.java
│ │ │ ├── SystemUiHiderBase.java
│ │ │ └── SystemUiHiderHoneycomb.java
│ └── org
│ │ └── videolan
│ │ └── libvlc
│ │ ├── Aout.java
│ │ ├── EventHandler.java
│ │ ├── IVideoPlayer.java
│ │ ├── LibVLC.java
│ │ ├── LibVlcException.java
│ │ ├── LibVlcUtil.java
│ │ ├── Media.java
│ │ ├── MediaList.java
│ │ └── TrackInfo.java
│ ├── jniLibs
│ └── armeabi-v7a
│ │ ├── libiomx-gingerbread.so
│ │ ├── libiomx-hc.so
│ │ ├── libiomx-ics.so
│ │ └── libvlcjni.so
│ └── res
│ ├── drawable-hdpi
│ ├── ic_action_pause_over_video.png
│ ├── ic_action_play_over_video.png
│ └── ic_launcher.png
│ ├── drawable-mdpi
│ └── ic_launcher.png
│ ├── drawable-xhdpi
│ └── ic_launcher.png
│ ├── drawable-xxhdpi
│ └── ic_launcher.png
│ ├── layout
│ ├── activity_fullscreen_vlc_player.xml
│ └── activity_media_selector.xml
│ ├── menu
│ └── menu_media_selector.xml
│ ├── values-v11
│ └── styles.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ └── gradle-wrapper.properties
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 |
19 | # Local configuration file (sdk path, etc)
20 | local.properties
21 |
22 | # Proguard folder generated by Eclipse
23 | proguard/
24 |
25 | # Log Files
26 | *.log
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Wassim SAMAD
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | VLC-Simple-Player-Android
2 | =========================
3 |
4 | **Basic Movie Player for Android using VLC Library**
5 |
6 | *The project was created with Android Studio*
7 |
8 | ##What is it ?
9 |
10 | This project is to understand how to implement VLC Library in your Android Project.
11 |
12 | It works with direct URL for streaming or you can directly put local movie path.
13 |
14 | 
15 | 
16 | 
17 |
18 | ##Improvements ?
19 |
20 | You are free to do whatever you want with it. It's very basic.
21 |
22 | Improve the UI to your needs, add functionnalities and make your powerful player.
23 |
24 |
25 | # Thank you !
26 | ### For more tutorials : [Visit my blog here ](http://www.wassimsamad.fr/blog)
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 20
5 | buildToolsVersion "20.0.0"
6 |
7 | defaultConfig {
8 | applicationId "com.wass08.vlcsimpleplayer"
9 | minSdkVersion 12
10 | targetSdkVersion 20
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | runProguard false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/wass08/vlcsimpleplayer/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
13 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wass08/vlcsimpleplayer/FullscreenVlcPlayer.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer;
2 |
3 | import com.wass08.vlcsimpleplayer.util.SystemUiHider;
4 |
5 | import android.annotation.TargetApi;
6 | import android.app.Activity;
7 | import android.content.pm.ActivityInfo;
8 | import android.content.res.Configuration;
9 | import android.graphics.PixelFormat;
10 | import android.os.Build;
11 | import android.os.Bundle;
12 | import android.os.Handler;
13 | import android.os.Message;
14 | import android.util.DisplayMetrics;
15 | import android.util.Log;
16 | import android.view.Gravity;
17 | import android.view.MotionEvent;
18 | import android.view.SurfaceHolder;
19 | import android.view.SurfaceView;
20 | import android.view.View;
21 | import android.view.ViewGroup;
22 | import android.view.Window;
23 | import android.view.WindowManager;
24 | import android.widget.FrameLayout;
25 | import android.widget.ImageView;
26 | import android.widget.LinearLayout;
27 | import android.widget.ScrollView;
28 | import android.widget.SeekBar;
29 | import android.widget.TextView;
30 | import android.widget.Toast;
31 |
32 | import org.videolan.libvlc.EventHandler;
33 | import org.videolan.libvlc.IVideoPlayer;
34 | import org.videolan.libvlc.LibVLC;
35 | import org.videolan.libvlc.Media;
36 | import org.videolan.libvlc.MediaList;
37 |
38 | import java.lang.ref.WeakReference;
39 |
40 |
41 | /**
42 | * An example full-screen activity that shows and hides the system UI (i.e.
43 | * status bar and navigation/system bar) with user interaction.
44 | *
45 | * @see SystemUiHider
46 | */
47 | public class FullscreenVlcPlayer extends Activity implements SurfaceHolder.Callback, IVideoPlayer {
48 |
49 | private String urlToStream;
50 |
51 | // Display Surface
52 | private LinearLayout vlcContainer;
53 | private SurfaceView mSurface;
54 | private SurfaceHolder holder;
55 |
56 | // Overlay / Controls
57 |
58 | private FrameLayout vlcOverlay;
59 | private ImageView vlcButtonPlayPause;
60 | private Handler handlerOverlay;
61 | private Runnable runnableOverlay;
62 | private Handler handlerSeekbar;
63 | private Runnable runnableSeekbar;
64 | private SeekBar vlcSeekbar;
65 | private TextView vlcDuration;
66 | private TextView overlayTitle;
67 |
68 | // media player
69 | private LibVLC libvlc;
70 | private int mVideoWidth;
71 | private int mVideoHeight;
72 | private final static int VideoSizeChanged = -1;
73 |
74 | @Override
75 | protected void onCreate(Bundle savedInstanceState) {
76 | super.onCreate(savedInstanceState);
77 |
78 | // Retrieve our url
79 | Bundle b = getIntent().getExtras();
80 | urlToStream = b.getString("url", null);
81 |
82 |
83 | // HIDE THE ACTION BAR
84 | getActionBar().hide();
85 |
86 | // SETUP THE UI
87 | setContentView(R.layout.activity_fullscreen_vlc_player);
88 |
89 | // VLC
90 | vlcContainer = (LinearLayout) findViewById(R.id.vlc_container);
91 | mSurface = (SurfaceView) findViewById(R.id.vlc_surface);
92 |
93 |
94 | // OVERLAY / CONTROLS
95 | vlcOverlay = (FrameLayout) findViewById(R.id.vlc_overlay);
96 | vlcButtonPlayPause = (ImageView) findViewById(R.id.vlc_button_play_pause);
97 | vlcSeekbar = (SeekBar) findViewById(R.id.vlc_seekbar);
98 | vlcDuration = (TextView) findViewById(R.id.vlc_duration);
99 |
100 | overlayTitle = (TextView) findViewById(R.id.vlc_overlay_title);
101 | overlayTitle.setText(urlToStream);
102 |
103 | // AUTOSTART
104 | playMovie();
105 |
106 | }
107 |
108 | private void showOverlay() {
109 | vlcOverlay.setVisibility(View.VISIBLE);
110 | }
111 |
112 | private void hideOverlay() {
113 | vlcOverlay.setVisibility(View.GONE);
114 | }
115 |
116 | private void setupControls() {
117 | getActionBar().hide();
118 | // PLAY PAUSE
119 | vlcButtonPlayPause.setOnClickListener(new View.OnClickListener() {
120 | @Override
121 | public void onClick(View view) {
122 | if (libvlc.isPlaying()) {
123 | libvlc.pause();
124 | vlcButtonPlayPause.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_play_over_video));
125 | } else {
126 | libvlc.play();
127 | vlcButtonPlayPause.setImageDrawable(getResources().getDrawable(R.drawable.ic_action_pause_over_video));
128 | }
129 | }
130 | });
131 |
132 | // SEEKBAR
133 | handlerSeekbar = new Handler();
134 | runnableSeekbar = new Runnable() {
135 | @Override
136 | public void run() {
137 | if (libvlc != null) {
138 | long curTime = libvlc.getTime();
139 | long totalTime = (long) (curTime / libvlc.getPosition());
140 | int minutes = (int) (curTime / (60 * 1000));
141 | int seconds = (int) ((curTime / 1000) % 60);
142 | int endMinutes = (int) (totalTime / (60 * 1000));
143 | int endSeconds = (int) ((totalTime / 1000) % 60);
144 | String duration = String.format("%02d:%02d / %02d:%02d", minutes, seconds, endMinutes, endSeconds);
145 | vlcSeekbar.setProgress((int) (libvlc.getPosition() * 100));
146 | vlcDuration.setText(duration);
147 | }
148 | handlerSeekbar.postDelayed(runnableSeekbar, 1000);
149 | }
150 | };
151 |
152 | runnableSeekbar.run();
153 | vlcSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
154 | @Override
155 | public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
156 | Log.v("NEW POS", "pos is : " + i);
157 | //if (i != 0)
158 | // libvlc.setPosition(((float) i / 100.0f));
159 | }
160 |
161 | @Override
162 | public void onStartTrackingTouch(SeekBar seekBar) {
163 |
164 | }
165 |
166 | @Override
167 | public void onStopTrackingTouch(SeekBar seekBar) {
168 |
169 | }
170 | });
171 |
172 | // OVERLAY
173 | handlerOverlay = new Handler();
174 | runnableOverlay = new Runnable() {
175 | @Override
176 | public void run() {
177 | vlcOverlay.setVisibility(View.GONE);
178 | toggleFullscreen(true);
179 | }
180 | };
181 | final long timeToDisappear = 3000;
182 | handlerOverlay.postDelayed(runnableOverlay, timeToDisappear);
183 | vlcContainer.setOnClickListener(new View.OnClickListener() {
184 | @Override
185 | public void onClick(View view) {
186 | vlcOverlay.setVisibility(View.VISIBLE);
187 |
188 | handlerOverlay.removeCallbacks(runnableOverlay);
189 | handlerOverlay.postDelayed(runnableOverlay, timeToDisappear);
190 | }
191 | });
192 | }
193 |
194 | public void playMovie() {
195 | if (libvlc != null && libvlc.isPlaying())
196 | return ;
197 | vlcContainer.setVisibility(View.VISIBLE);
198 | holder = mSurface.getHolder();
199 | holder.addCallback(this);
200 | createPlayer(urlToStream);
201 | }
202 |
203 |
204 | private void toggleFullscreen(boolean fullscreen)
205 | {
206 | WindowManager.LayoutParams attrs = getWindow().getAttributes();
207 | if (fullscreen)
208 | {
209 | attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
210 | vlcContainer.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
211 | | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
212 | | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
213 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
214 | | View.SYSTEM_UI_FLAG_FULLSCREEN
215 | | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
216 | }
217 | else
218 | {
219 | attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN;
220 | }
221 | getWindow().setAttributes(attrs);
222 | }
223 |
224 | @Override
225 | public void onConfigurationChanged(Configuration newConfig) {
226 | super.onConfigurationChanged(newConfig);
227 | setSize(mVideoWidth, mVideoHeight);
228 | }
229 |
230 | @Override
231 | protected void onResume() {
232 | super.onResume();
233 | }
234 |
235 | @Override
236 | protected void onPause() {
237 | super.onPause();
238 | //releasePlayer();
239 | }
240 |
241 | @Override
242 | protected void onDestroy() {
243 | super.onDestroy();
244 | releasePlayer();
245 | }
246 |
247 | /**
248 | * **********
249 | * Surface
250 | * ***********
251 | */
252 |
253 | public void surfaceCreated(SurfaceHolder holder) {
254 | }
255 |
256 | public void surfaceChanged(SurfaceHolder surfaceholder, int format,
257 | int width, int height) {
258 | if (libvlc != null)
259 | libvlc.attachSurface(surfaceholder.getSurface(), this);
260 | }
261 |
262 | public void surfaceDestroyed(SurfaceHolder surfaceholder) {
263 | }
264 |
265 | private void setSize(int width, int height) {
266 | mVideoWidth = width;
267 | mVideoHeight = height;
268 | if (mVideoWidth * mVideoHeight <= 1)
269 | return;
270 |
271 | // get screen size
272 | int w = getWindow().getDecorView().getWidth();
273 | int h = getWindow().getDecorView().getHeight();
274 |
275 | // getWindow().getDecorView() doesn't always take orientation into
276 | // account, we have to correct the values
277 | boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
278 | if (w > h && isPortrait || w < h && !isPortrait) {
279 | int i = w;
280 | w = h;
281 | h = i;
282 | }
283 |
284 | float videoAR = (float) mVideoWidth / (float) mVideoHeight;
285 | float screenAR = (float) w / (float) h;
286 |
287 | if (screenAR < videoAR)
288 | h = (int) (w / videoAR);
289 | else
290 | w = (int) (h * videoAR);
291 |
292 | // force surface buffer size
293 | if (holder != null)
294 | holder.setFixedSize(mVideoWidth, mVideoHeight);
295 |
296 | // set display size
297 | ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
298 | lp.width = w;
299 | lp.height = h;
300 | mSurface.setLayoutParams(lp);
301 | mSurface.invalidate();
302 | }
303 |
304 | @Override
305 | public void setSurfaceSize(int width, int height, int visible_width,
306 | int visible_height, int sar_num, int sar_den) {
307 | Message msg = Message.obtain(mHandler, VideoSizeChanged, width, height);
308 | msg.sendToTarget();
309 | }
310 |
311 | /**
312 | * **********
313 | * Player
314 | * ***********
315 | */
316 |
317 | private void createPlayer(String media) {
318 | releasePlayer();
319 | setupControls();
320 | try {
321 | if (media.length() > 0) {
322 | Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
323 | toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
324 | 0);
325 | toast.show();
326 | }
327 |
328 | // Create a new media player
329 | libvlc = LibVLC.getInstance();
330 | libvlc.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
331 | libvlc.eventVideoPlayerActivityCreated(true);
332 | libvlc.setSubtitlesEncoding("");
333 | libvlc.setAout(LibVLC.AOUT_OPENSLES);
334 | libvlc.setTimeStretching(true);
335 | libvlc.setChroma("RV32");
336 | libvlc.setVerboseMode(true);
337 | LibVLC.restart(this);
338 | EventHandler.getInstance().addHandler(mHandler);
339 | holder.setFormat(PixelFormat.RGBX_8888);
340 | holder.setKeepScreenOn(true);
341 | MediaList list = libvlc.getMediaList();
342 | list.clear();
343 | list.add(new Media(libvlc, LibVLC.PathToURI(media)), false);
344 | libvlc.playIndex(0);
345 | } catch (Exception e) {
346 | Toast.makeText(this, "Could not create Vlc Player", Toast.LENGTH_LONG).show();
347 | }
348 | }
349 |
350 | private void releasePlayer() {
351 | if (handlerSeekbar != null && runnableSeekbar != null)
352 | handlerSeekbar.removeCallbacks(runnableSeekbar);
353 | EventHandler.getInstance().removeHandler(mHandler);
354 | if (libvlc == null)
355 | return;
356 | libvlc.stop();
357 | libvlc.detachSurface();
358 | holder = null;
359 | libvlc.closeAout();
360 |
361 | mVideoWidth = 0;
362 | mVideoHeight = 0;
363 | }
364 |
365 | /**
366 | * **********
367 | * Events
368 | * ***********
369 | */
370 |
371 | private Handler mHandler = new MyHandler(this);
372 |
373 | private static class MyHandler extends Handler {
374 | private WeakReference mOwner;
375 |
376 | public MyHandler(FullscreenVlcPlayer owner) {
377 | mOwner = new WeakReference(owner);
378 | }
379 |
380 | @Override
381 | public void handleMessage(Message msg) {
382 | FullscreenVlcPlayer player = mOwner.get();
383 |
384 | // Player events
385 | if (msg.what == VideoSizeChanged) {
386 | player.setSize(msg.arg1, msg.arg2);
387 | return;
388 | }
389 |
390 | // Libvlc events
391 | Bundle b = msg.getData();
392 | switch (b.getInt("event")) {
393 | case EventHandler.MediaPlayerEndReached:
394 | player.releasePlayer();
395 | break;
396 | case EventHandler.MediaPlayerPlaying:
397 | case EventHandler.MediaPlayerPaused:
398 | case EventHandler.MediaPlayerStopped:
399 | default:
400 | break;
401 | }
402 | }
403 | }
404 |
405 | }
406 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wass08/vlcsimpleplayer/MediaSelector.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.widget.EditText;
10 | import android.widget.TextView;
11 |
12 |
13 | public class MediaSelector extends Activity {
14 |
15 | private EditText urlGetter;
16 | private TextView buttonStart;
17 |
18 | @Override
19 | protected void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_media_selector);
22 | urlGetter = (EditText)findViewById(R.id.url_getter);
23 | buttonStart = (TextView)findViewById(R.id.button_start);
24 | buttonStart.setOnClickListener(new View.OnClickListener() {
25 | @Override
26 | public void onClick(View view) {
27 | Intent toFullscreen = new Intent(MediaSelector.this, FullscreenVlcPlayer.class);
28 | Bundle b = new Bundle();
29 |
30 | // Pass the url from the input to the player
31 | b.putString("url", urlGetter.getText().toString());
32 | toFullscreen.putExtras(b); //Put your id to your next Intent
33 | startActivity(toFullscreen);
34 | }
35 | });
36 | }
37 |
38 |
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wass08/vlcsimpleplayer/util/SystemUiHider.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer.util;
2 |
3 | import android.app.Activity;
4 | import android.os.Build;
5 | import android.view.View;
6 |
7 | /**
8 | * A utility class that helps with showing and hiding system UI such as the
9 | * status bar and navigation/system bar. This class uses backward-compatibility
10 | * techniques described in
12 | * Creating Backward-Compatible UIs to ensure that devices running any
13 | * version of ndroid OS are supported. More specifically, there are separate
14 | * implementations of this abstract class: for newer devices,
15 | * {@link #getInstance} will return a {@link SystemUiHiderHoneycomb} instance,
16 | * while on older devices {@link #getInstance} will return a
17 | * {@link SystemUiHiderBase} instance.
18 | *
19 | * For more on system bars, see System Bars.
22 | *
23 | * @see android.view.View#setSystemUiVisibility(int)
24 | * @see android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
25 | */
26 | public abstract class SystemUiHider {
27 | /**
28 | * When this flag is set, the
29 | * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}
30 | * flag will be set on older devices, making the status bar "float" on top
31 | * of the activity layout. This is most useful when there are no controls at
32 | * the top of the activity layout.
33 | *
34 | * This flag isn't used on newer devices because the action
36 | * bar, the most important structural element of an Android app, should
37 | * be visible and not obscured by the system UI.
38 | */
39 | public static final int FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES = 0x1;
40 |
41 | /**
42 | * When this flag is set, {@link #show()} and {@link #hide()} will toggle
43 | * the visibility of the status bar. If there is a navigation bar, show and
44 | * hide will toggle low profile mode.
45 | */
46 | public static final int FLAG_FULLSCREEN = 0x2;
47 |
48 | /**
49 | * When this flag is set, {@link #show()} and {@link #hide()} will toggle
50 | * the visibility of the navigation bar, if it's present on the device and
51 | * the device allows hiding it. In cases where the navigation bar is present
52 | * but cannot be hidden, show and hide will toggle low profile mode.
53 | */
54 | public static final int FLAG_HIDE_NAVIGATION = FLAG_FULLSCREEN | 0x4;
55 |
56 | /**
57 | * The activity associated with this UI hider object.
58 | */
59 | protected Activity mActivity;
60 |
61 | /**
62 | * The view on which {@link View#setSystemUiVisibility(int)} will be called.
63 | */
64 | protected View mAnchorView;
65 |
66 | /**
67 | * The current UI hider flags.
68 | *
69 | * @see #FLAG_FULLSCREEN
70 | * @see #FLAG_HIDE_NAVIGATION
71 | * @see #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES
72 | */
73 | protected int mFlags;
74 |
75 | /**
76 | * The current visibility callback.
77 | */
78 | protected OnVisibilityChangeListener mOnVisibilityChangeListener = sDummyListener;
79 |
80 | /**
81 | * Creates and returns an instance of {@link SystemUiHider} that is
82 | * appropriate for this device. The object will be either a
83 | * {@link SystemUiHiderBase} or {@link SystemUiHiderHoneycomb} depending on
84 | * the device.
85 | *
86 | * @param activity The activity whose window's system UI should be
87 | * controlled by this class.
88 | * @param anchorView The view on which
89 | * {@link View#setSystemUiVisibility(int)} will be called.
90 | * @param flags Either 0 or any combination of {@link #FLAG_FULLSCREEN},
91 | * {@link #FLAG_HIDE_NAVIGATION}, and
92 | * {@link #FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES}.
93 | */
94 | public static SystemUiHider getInstance(Activity activity, View anchorView, int flags) {
95 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
96 | return new SystemUiHiderHoneycomb(activity, anchorView, flags);
97 | } else {
98 | return new SystemUiHiderBase(activity, anchorView, flags);
99 | }
100 | }
101 |
102 | protected SystemUiHider(Activity activity, View anchorView, int flags) {
103 | mActivity = activity;
104 | mAnchorView = anchorView;
105 | mFlags = flags;
106 | }
107 |
108 | /**
109 | * Sets up the system UI hider. Should be called from
110 | * {@link Activity#onCreate}.
111 | */
112 | public abstract void setup();
113 |
114 | /**
115 | * Returns whether or not the system UI is visible.
116 | */
117 | public abstract boolean isVisible();
118 |
119 | /**
120 | * Hide the system UI.
121 | */
122 | public abstract void hide();
123 |
124 | /**
125 | * Show the system UI.
126 | */
127 | public abstract void show();
128 |
129 | /**
130 | * Toggle the visibility of the system UI.
131 | */
132 | public void toggle() {
133 | if (isVisible()) {
134 | hide();
135 | } else {
136 | show();
137 | }
138 | }
139 |
140 | /**
141 | * Registers a callback, to be triggered when the system UI visibility
142 | * changes.
143 | */
144 | public void setOnVisibilityChangeListener(OnVisibilityChangeListener listener) {
145 | if (listener == null) {
146 | listener = sDummyListener;
147 | }
148 |
149 | mOnVisibilityChangeListener = listener;
150 | }
151 |
152 | /**
153 | * A dummy no-op callback for use when there is no other listener set.
154 | */
155 | private static OnVisibilityChangeListener sDummyListener = new OnVisibilityChangeListener() {
156 | @Override
157 | public void onVisibilityChange(boolean visible) {
158 | }
159 | };
160 |
161 | /**
162 | * A callback interface used to listen for system UI visibility changes.
163 | */
164 | public interface OnVisibilityChangeListener {
165 | /**
166 | * Called when the system UI visibility has changed.
167 | *
168 | * @param visible True if the system UI is visible.
169 | */
170 | public void onVisibilityChange(boolean visible);
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wass08/vlcsimpleplayer/util/SystemUiHiderBase.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer.util;
2 |
3 | import android.app.Activity;
4 | import android.view.View;
5 | import android.view.WindowManager;
6 |
7 | /**
8 | * A base implementation of {@link SystemUiHider}. Uses APIs available in all
9 | * API levels to show and hide the status bar.
10 | */
11 | public class SystemUiHiderBase extends SystemUiHider {
12 | /**
13 | * Whether or not the system UI is currently visible. This is a cached value
14 | * from calls to {@link #hide()} and {@link #show()}.
15 | */
16 | private boolean mVisible = true;
17 |
18 | /**
19 | * Constructor not intended to be called by clients. Use
20 | * {@link SystemUiHider#getInstance} to obtain an instance.
21 | */
22 | protected SystemUiHiderBase(Activity activity, View anchorView, int flags) {
23 | super(activity, anchorView, flags);
24 | }
25 |
26 | @Override
27 | public void setup() {
28 | if ((mFlags & FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES) == 0) {
29 | mActivity.getWindow().setFlags(
30 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
31 | | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
32 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
33 | | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
34 | }
35 | }
36 |
37 | @Override
38 | public boolean isVisible() {
39 | return mVisible;
40 | }
41 |
42 | @Override
43 | public void hide() {
44 | if ((mFlags & FLAG_FULLSCREEN) != 0) {
45 | mActivity.getWindow().setFlags(
46 | WindowManager.LayoutParams.FLAG_FULLSCREEN,
47 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
48 | }
49 | mOnVisibilityChangeListener.onVisibilityChange(false);
50 | mVisible = false;
51 | }
52 |
53 | @Override
54 | public void show() {
55 | if ((mFlags & FLAG_FULLSCREEN) != 0) {
56 | mActivity.getWindow().setFlags(
57 | 0,
58 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
59 | }
60 | mOnVisibilityChangeListener.onVisibilityChange(true);
61 | mVisible = true;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wass08/vlcsimpleplayer/util/SystemUiHiderHoneycomb.java:
--------------------------------------------------------------------------------
1 | package com.wass08.vlcsimpleplayer.util;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.os.Build;
6 | import android.view.View;
7 | import android.view.WindowManager;
8 |
9 | /**
10 | * An API 11+ implementation of {@link SystemUiHider}. Uses APIs available in
11 | * Honeycomb and later (specifically {@link View#setSystemUiVisibility(int)}) to
12 | * show and hide the system UI.
13 | */
14 | @TargetApi(Build.VERSION_CODES.HONEYCOMB)
15 | public class SystemUiHiderHoneycomb extends SystemUiHiderBase {
16 | /**
17 | * Flags for {@link View#setSystemUiVisibility(int)} to use when showing the
18 | * system UI.
19 | */
20 | private int mShowFlags;
21 |
22 | /**
23 | * Flags for {@link View#setSystemUiVisibility(int)} to use when hiding the
24 | * system UI.
25 | */
26 | private int mHideFlags;
27 |
28 | /**
29 | * Flags to test against the first parameter in
30 | * {@link android.view.View.OnSystemUiVisibilityChangeListener#onSystemUiVisibilityChange(int)}
31 | * to determine the system UI visibility state.
32 | */
33 | private int mTestFlags;
34 |
35 | /**
36 | * Whether or not the system UI is currently visible. This is cached from
37 | * {@link android.view.View.OnSystemUiVisibilityChangeListener}.
38 | */
39 | private boolean mVisible = true;
40 |
41 | /**
42 | * Constructor not intended to be called by clients. Use
43 | * {@link SystemUiHider#getInstance} to obtain an instance.
44 | */
45 | protected SystemUiHiderHoneycomb(Activity activity, View anchorView, int flags) {
46 | super(activity, anchorView, flags);
47 |
48 | mShowFlags = View.SYSTEM_UI_FLAG_VISIBLE;
49 | mHideFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
50 | mTestFlags = View.SYSTEM_UI_FLAG_LOW_PROFILE;
51 |
52 | if ((mFlags & FLAG_FULLSCREEN) != 0) {
53 | // If the client requested fullscreen, add flags relevant to hiding
54 | // the status bar. Note that some of these constants are new as of
55 | // API 16 (Jelly Bean). It is safe to use them, as they are inlined
56 | // at compile-time and do nothing on pre-Jelly Bean devices.
57 | mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
58 | mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
59 | | View.SYSTEM_UI_FLAG_FULLSCREEN;
60 | }
61 |
62 | if ((mFlags & FLAG_HIDE_NAVIGATION) != 0) {
63 | // If the client requested hiding navigation, add relevant flags.
64 | mShowFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
65 | mHideFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
66 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
67 | mTestFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
68 | }
69 | }
70 |
71 | /**
72 | * {@inheritDoc}
73 | */
74 | @Override
75 | public void setup() {
76 | mAnchorView.setOnSystemUiVisibilityChangeListener(mSystemUiVisibilityChangeListener);
77 | }
78 |
79 | /**
80 | * {@inheritDoc}
81 | */
82 | @Override
83 | public void hide() {
84 | mAnchorView.setSystemUiVisibility(mHideFlags);
85 | }
86 |
87 | /**
88 | * {@inheritDoc}
89 | */
90 | @Override
91 | public void show() {
92 | mAnchorView.setSystemUiVisibility(mShowFlags);
93 | }
94 |
95 | /**
96 | * {@inheritDoc}
97 | */
98 | @Override
99 | public boolean isVisible() {
100 | return mVisible;
101 | }
102 |
103 | private View.OnSystemUiVisibilityChangeListener mSystemUiVisibilityChangeListener
104 | = new View.OnSystemUiVisibilityChangeListener() {
105 | @Override
106 | public void onSystemUiVisibilityChange(int vis) {
107 | // Test against mTestFlags to see if the system UI is visible.
108 | if ((vis & mTestFlags) != 0) {
109 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
110 | // Pre-Jelly Bean, we must manually hide the action bar
111 | // and use the old window flags API.
112 | mActivity.getActionBar().hide();
113 | mActivity.getWindow().setFlags(
114 | WindowManager.LayoutParams.FLAG_FULLSCREEN,
115 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
116 | }
117 |
118 | // Trigger the registered listener and cache the visibility
119 | // state.
120 | mOnVisibilityChangeListener.onVisibilityChange(false);
121 | mVisible = false;
122 |
123 | } else {
124 | mAnchorView.setSystemUiVisibility(mShowFlags);
125 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
126 | // Pre-Jelly Bean, we must manually show the action bar
127 | // and use the old window flags API.
128 | mActivity.getActionBar().show();
129 | mActivity.getWindow().setFlags(
130 | 0,
131 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
132 | }
133 |
134 | // Trigger the registered listener and cache the visibility
135 | // state.
136 | mOnVisibilityChangeListener.onVisibilityChange(true);
137 | mVisible = true;
138 | }
139 | }
140 | };
141 | }
142 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/Aout.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * Aout.java
3 | *****************************************************************************
4 | * Copyright © 2011-2012 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | import android.media.AudioFormat;
24 | import android.media.AudioManager;
25 | import android.media.AudioTrack;
26 | import android.util.Log;
27 |
28 | public class Aout {
29 | /**
30 | * Java side of the audio output module for Android.
31 | * Uses an AudioTrack to play decoded audio buffers.
32 | *
33 | * TODO Use MODE_STATIC instead of MODE_STREAM with a MemoryFile (ashmem)
34 | */
35 |
36 | public Aout() {
37 | }
38 |
39 | private AudioTrack mAudioTrack;
40 | private static final String TAG = "LibVLC/aout";
41 |
42 | public void init(int sampleRateInHz, int channels, int samples) {
43 | Log.d(TAG, sampleRateInHz + ", " + channels + ", " + samples + "=>" + channels * samples);
44 | int minBufferSize = AudioTrack.getMinBufferSize(sampleRateInHz,
45 | AudioFormat.CHANNEL_OUT_STEREO,
46 | AudioFormat.ENCODING_PCM_16BIT);
47 | mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
48 | sampleRateInHz,
49 | AudioFormat.CHANNEL_OUT_STEREO,
50 | AudioFormat.ENCODING_PCM_16BIT,
51 | Math.max(minBufferSize, channels * samples * 2),
52 | AudioTrack.MODE_STREAM);
53 | }
54 |
55 | public void release() {
56 | if (mAudioTrack != null) {
57 | mAudioTrack.release();
58 | }
59 | mAudioTrack = null;
60 | }
61 |
62 | public void playBuffer(byte[] audioData, int bufferSize) {
63 | if (mAudioTrack.getState() == AudioTrack.STATE_UNINITIALIZED)
64 | return;
65 | if (mAudioTrack.write(audioData, 0, bufferSize) != bufferSize) {
66 | Log.w(TAG, "Could not write all the samples to the audio device");
67 | }
68 | mAudioTrack.play();
69 | }
70 |
71 | public void pause() {
72 | mAudioTrack.pause();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/EventHandler.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * EventHandler.java
3 | *****************************************************************************
4 | * Copyright © 2011-2014 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | import java.util.ArrayList;
24 |
25 | import android.os.Bundle;
26 | import android.os.Handler;
27 | import android.os.Message;
28 |
29 | public class EventHandler {
30 |
31 | /*
32 | * Be sure to subscribe to events you need in the JNI too.
33 | */
34 |
35 | //public static final int MediaMetaChanged = 0;
36 | //public static final int MediaSubItemAdded = 1;
37 | //public static final int MediaDurationChanged = 2;
38 | public static final int MediaParsedChanged = 3;
39 | //public static final int MediaFreed = 4;
40 | //public static final int MediaStateChanged = 5;
41 |
42 | //public static final int MediaPlayerMediaChanged = 0x100;
43 | //public static final int MediaPlayerNothingSpecial = 0x101;
44 | //public static final int MediaPlayerOpening = 0x102;
45 | //public static final int MediaPlayerBuffering = 0x103;
46 | public static final int MediaPlayerPlaying = 0x104;
47 | public static final int MediaPlayerPaused = 0x105;
48 | public static final int MediaPlayerStopped = 0x106;
49 | //public static final int MediaPlayerForward = 0x107;
50 | //public static final int MediaPlayerBackward = 0x108;
51 | public static final int MediaPlayerEndReached = 0x109;
52 | public static final int MediaPlayerEncounteredError = 0x10a;
53 | //public static final int MediaPlayerTimeChanged = 0x10b;
54 | public static final int MediaPlayerPositionChanged = 0x10c;
55 | //public static final int MediaPlayerSeekableChanged = 0x10d;
56 | //public static final int MediaPlayerPausableChanged = 0x10e;
57 | //public static final int MediaPlayerTitleChanged = 0x10f;
58 | //public static final int MediaPlayerSnapshotTaken = 0x110;
59 | //public static final int MediaPlayerLengthChanged = 0x111;
60 | public static final int MediaPlayerVout = 0x112;
61 |
62 | //public static final int MediaListItemAdded = 0x200;
63 | //public static final int MediaListWillAddItem = 0x201;
64 | //public static final int MediaListItemDeleted = 0x202;
65 | //public static final int MediaListWillDeleteItem = 0x203;
66 |
67 | //public static final int MediaListViewItemAdded = 0x300;
68 | //public static final int MediaListViewWillAddItem = 0x301;
69 | //public static final int MediaListViewItemDeleted = 0x302;
70 | //public static final int MediaListViewWillDeleteItem = 0x303;
71 |
72 | //public static final int MediaListPlayerPlayed = 0x400;
73 | //public static final int MediaListPlayerNextItemSet = 0x401;
74 | //public static final int MediaListPlayerStopped = 0x402;
75 |
76 | //public static final int MediaDiscovererStarted = 0x500;
77 | //public static final int MediaDiscovererEnded = 0x501;
78 |
79 | //public static final int VlmMediaAdded = 0x600;
80 | //public static final int VlmMediaRemoved = 0x601;
81 | //public static final int VlmMediaChanged = 0x602;
82 | //public static final int VlmMediaInstanceStarted = 0x603;
83 | //public static final int VlmMediaInstanceStopped = 0x604;
84 | //public static final int VlmMediaInstanceStatusInit = 0x605;
85 | //public static final int VlmMediaInstanceStatusOpening = 0x606;
86 | //public static final int VlmMediaInstanceStatusPlaying = 0x607;
87 | //public static final int VlmMediaInstanceStatusPause = 0x608;
88 | //public static final int VlmMediaInstanceStatusEnd = 0x609;
89 | //public static final int VlmMediaInstanceStatusError = 0x60a;
90 |
91 | public static final int CustomMediaListExpanding = 0x2000;
92 | public static final int CustomMediaListExpandingEnd = 0x2001;
93 | public static final int CustomMediaListItemAdded = 0x2002;
94 | public static final int CustomMediaListItemDeleted = 0x2003;
95 | public static final int CustomMediaListItemMoved = 0x2004;
96 |
97 | public static final int HardwareAccelerationError = 0x3000;
98 |
99 | private ArrayList mEventHandler;
100 | private static EventHandler mInstance;
101 |
102 | EventHandler() {
103 | mEventHandler = new ArrayList();
104 | }
105 |
106 | public static EventHandler getInstance() {
107 | if (mInstance == null) {
108 | mInstance = new EventHandler();
109 | }
110 | return mInstance;
111 | }
112 |
113 | public void addHandler(Handler handler) {
114 | if (!mEventHandler.contains(handler))
115 | mEventHandler.add(handler);
116 | }
117 |
118 | public void removeHandler(Handler handler) {
119 | mEventHandler.remove(handler);
120 | }
121 |
122 | /** This method is called by a native thread **/
123 | public void callback(int event, Bundle b) {
124 | b.putInt("event", event);
125 | for (int i = 0; i < mEventHandler.size(); i++) {
126 | Message msg = Message.obtain();
127 | msg.setData(b);
128 | mEventHandler.get(i).sendMessage(msg);
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/IVideoPlayer.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * IVideoPlayer.java
3 | *****************************************************************************
4 | * Copyright © 2010-2013 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | public interface IVideoPlayer {
24 | /**
25 | * This method is called by native vout to request a surface resize when frame size doesn't match surface size.
26 | * @param width Frame width
27 | * @param height Frame height
28 | * @param visible_width Visible frame width
29 | * @param visible_height Visible frame height
30 | * @param sar_num Surface aspect ratio numerator
31 | * @param sar_den Surface aspect ratio denominator
32 | */
33 | void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den);
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/LibVLC.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * LibVLC.java
3 | *****************************************************************************
4 | * Copyright © 2010-2013 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | import java.util.ArrayList;
24 | import java.util.Map;
25 |
26 | import android.content.Context;
27 | import android.os.Build;
28 | import android.util.Log;
29 | import android.view.Surface;
30 |
31 | public class LibVLC {
32 | private static final String TAG = "VLC/LibVLC";
33 | public static final int AOUT_AUDIOTRACK_JAVA = 0;
34 | public static final int AOUT_AUDIOTRACK = 1;
35 | public static final int AOUT_OPENSLES = 2;
36 |
37 | public static final int VOUT_ANDROID_SURFACE = 0;
38 | public static final int VOUT_OPEGLES2 = 1;
39 |
40 | public static final int HW_ACCELERATION_AUTOMATIC = -1;
41 | public static final int HW_ACCELERATION_DISABLED = 0;
42 | public static final int HW_ACCELERATION_DECODING = 1;
43 | public static final int HW_ACCELERATION_FULL = 2;
44 |
45 | private static LibVLC sInstance;
46 |
47 | /** libVLC instance C pointer */
48 | private long mLibVlcInstance = 0; // Read-only, reserved for JNI
49 | /** libvlc_media_player pointer and index */
50 | private int mInternalMediaPlayerIndex = 0; // Read-only, reserved for JNI
51 | private long mInternalMediaPlayerInstance = 0; // Read-only, reserved for JNI
52 |
53 | private MediaList mMediaList; // Pointer to media list being followed
54 | private MediaList mPrimaryList; // Primary/default media list; see getPrimaryMediaList()
55 |
56 | /** Buffer for VLC messages */
57 | private StringBuffer mDebugLogBuffer;
58 | private boolean mIsBufferingLog = false;
59 |
60 | private Aout mAout;
61 |
62 | /** Keep screen bright */
63 | //private WakeLock mWakeLock;
64 |
65 | /** Settings */
66 | private int hardwareAcceleration = HW_ACCELERATION_AUTOMATIC;
67 | private String subtitlesEncoding = "";
68 | private int aout = LibVlcUtil.isGingerbreadOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
69 | private int vout = VOUT_ANDROID_SURFACE;
70 | private boolean timeStretching = false;
71 | private int deblocking = -1;
72 | private String chroma = "";
73 | private boolean verboseMode = true;
74 | private float[] equalizer = null;
75 | private boolean frameSkip = false;
76 | private int networkCaching = 0;
77 |
78 | /** Native crash handler */
79 | private OnNativeCrashListener mOnNativeCrashListener;
80 |
81 | /** Check in libVLC already initialized otherwise crash */
82 | private boolean mIsInitialized = false;
83 | public native void attachSurface(Surface surface, IVideoPlayer player);
84 |
85 | public native void detachSurface();
86 |
87 | public native void attachSubtitlesSurface(Surface surface);
88 | public native void detachSubtitlesSurface();
89 |
90 | public native void eventVideoPlayerActivityCreated(boolean created);
91 |
92 | /* Load library before object instantiation */
93 | static {
94 | try {
95 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
96 | System.loadLibrary("iomx-gingerbread");
97 | else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2)
98 | System.loadLibrary("iomx-hc");
99 | else if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2)
100 | System.loadLibrary("iomx-ics");
101 | } catch (Throwable t) {
102 | Log.w(TAG, "Unable to load the iomx library: " + t);
103 | }
104 | try {
105 | System.loadLibrary("vlcjni");
106 | } catch (UnsatisfiedLinkError ule) {
107 | Log.e(TAG, "Can't load vlcjni library: " + ule);
108 | /// FIXME Alert user
109 | System.exit(1);
110 | } catch (SecurityException se) {
111 | Log.e(TAG, "Encountered a security issue when loading vlcjni library: " + se);
112 | /// FIXME Alert user
113 | System.exit(1);
114 | }
115 | }
116 |
117 | /**
118 | * Singleton constructor of libVLC Without surface and vout to create the
119 | * thumbnail and get information e.g. on the MediaLibraryActivity
120 | *
121 | * @return libVLC instance
122 | * @throws LibVlcException
123 | */
124 | public static LibVLC getInstance() throws LibVlcException {
125 | synchronized (LibVLC.class) {
126 | if (sInstance == null) {
127 | /* First call */
128 | sInstance = new LibVLC();
129 | }
130 | }
131 |
132 | return sInstance;
133 | }
134 |
135 | /**
136 | * Return an existing instance of libVLC Call it when it is NOT important
137 | * that this fails
138 | *
139 | * @return libVLC instance OR null
140 | */
141 | public static LibVLC getExistingInstance() {
142 | synchronized (LibVLC.class) {
143 | return sInstance;
144 | }
145 | }
146 |
147 | /**
148 | * Constructor
149 | * It is private because this class is a singleton.
150 | */
151 | private LibVLC() {
152 | mAout = new Aout();
153 | }
154 |
155 | /**
156 | * Destructor:
157 | * It is bad practice to rely on them, so please don't forget to call
158 | * destroy() before exiting.
159 | */
160 | @Override
161 | public void finalize() {
162 | if (mLibVlcInstance != 0) {
163 | Log.d(TAG, "LibVLC is was destroyed yet before finalize()");
164 | destroy();
165 | }
166 | }
167 |
168 | /**
169 | * Get the media list that LibVLC is following right now.
170 | *
171 | * @return The media list object being followed
172 | */
173 | public MediaList getMediaList() {
174 | return mMediaList;
175 | }
176 |
177 | /**
178 | * Set the media list for LibVLC to follow.
179 | *
180 | * @param mediaList The media list object to follow
181 | */
182 | public void setMediaList(MediaList mediaList) {
183 | mMediaList = mediaList;
184 | }
185 |
186 | /**
187 | * Sets LibVLC to follow the default media list (see below)
188 | */
189 | public void setMediaList() {
190 | mMediaList = mPrimaryList;
191 | }
192 |
193 | /**
194 | * Gets the primary media list, or the "currently playing" list.
195 | * Not to be confused with the media list pointer from above, which
196 | * refers the the MediaList object that libVLC is currently following.
197 | * This list is just one out of many lists that it can be pointed towards.
198 | *
199 | * This list will be used for lists of songs that are not user-defined.
200 | * For example: selecting a song from the Songs list, or from the list
201 | * displayed after selecting an album.
202 | *
203 | * It is loaded as the default list.
204 | *
205 | * @return The primary media list
206 | */
207 | public MediaList getPrimaryMediaList() {
208 | return mPrimaryList;
209 | }
210 |
211 | /**
212 | * Give to LibVLC the surface to draw the video.
213 | * @param f the surface to draw
214 | */
215 | public native void setSurface(Surface f);
216 |
217 | public static synchronized void restart(Context context) {
218 | if (sInstance != null) {
219 | try {
220 | sInstance.destroy();
221 | sInstance.init(context);
222 | } catch (LibVlcException lve) {
223 | Log.e(TAG, "Unable to reinit libvlc: " + lve);
224 | }
225 | }
226 | }
227 |
228 | /**
229 | * those get/is* are called from native code to get settings values.
230 | */
231 |
232 | public int getHardwareAcceleration() {
233 | return this.hardwareAcceleration;
234 | }
235 |
236 | public void setHardwareAcceleration(int hardwareAcceleration) {
237 | if (hardwareAcceleration < 0) {
238 | // Automatic mode: activate MediaCodec opaque direct rendering for 4.3 and above.
239 | if (LibVlcUtil.isJellyBeanMR2OrLater())
240 | this.hardwareAcceleration = HW_ACCELERATION_FULL;
241 | else
242 | this.hardwareAcceleration = HW_ACCELERATION_DISABLED;
243 | }
244 | else
245 | this.hardwareAcceleration = hardwareAcceleration;
246 | }
247 |
248 | public String getSubtitlesEncoding() {
249 | return subtitlesEncoding;
250 | }
251 |
252 | public void setSubtitlesEncoding(String subtitlesEncoding) {
253 | this.subtitlesEncoding = subtitlesEncoding;
254 | }
255 |
256 | public int getAout() {
257 | return aout;
258 | }
259 |
260 | public void setAout(int aout) {
261 | if (aout < 0)
262 | this.aout = LibVlcUtil.isICSOrLater() ? AOUT_OPENSLES : AOUT_AUDIOTRACK_JAVA;
263 | else
264 | this.aout = aout;
265 | }
266 |
267 | public int getVout() {
268 | return vout;
269 | }
270 |
271 | public void setVout(int vout) {
272 | if (vout < 0)
273 | this.vout = VOUT_ANDROID_SURFACE;
274 | else
275 | this.vout = vout;
276 | }
277 |
278 | public boolean timeStretchingEnabled() {
279 | return timeStretching;
280 | }
281 |
282 | public void setTimeStretching(boolean timeStretching) {
283 | this.timeStretching = timeStretching;
284 | }
285 |
286 | public int getDeblocking() {
287 | int ret = deblocking;
288 | if(deblocking < 0) {
289 | /**
290 | * Set some reasonable deblocking defaults:
291 | *
292 | * Skip all (4) for armv6 and MIPS by default
293 | * Skip non-ref (1) for all armv7 more than 1.2 Ghz and more than 2 cores
294 | * Skip non-key (3) for all devices that don't meet anything above
295 | */
296 | LibVlcUtil.MachineSpecs m = LibVlcUtil.getMachineSpecs();
297 | if( (m.hasArmV6 && !(m.hasArmV7)) || m.hasMips )
298 | ret = 4;
299 | else if(m.bogoMIPS > 1200 && m.processors > 2)
300 | ret = 1;
301 | else
302 | ret = 3;
303 | } else if(deblocking > 4) { // sanity check
304 | ret = 3;
305 | }
306 | return ret;
307 | }
308 |
309 | public void setDeblocking(int deblocking) {
310 | this.deblocking = deblocking;
311 | }
312 |
313 | public String getChroma() {
314 | return chroma;
315 | }
316 |
317 | public void setChroma(String chroma) {
318 | this.chroma = chroma.equals("YV12") && !LibVlcUtil.isGingerbreadOrLater() ? "" : chroma;
319 | }
320 |
321 | public boolean isVerboseMode() {
322 | return verboseMode;
323 | }
324 |
325 | public void setVerboseMode(boolean verboseMode) {
326 | this.verboseMode = verboseMode;
327 | }
328 |
329 | public float[] getEqualizer()
330 | {
331 | return equalizer;
332 | }
333 |
334 | public void setEqualizer(float[] equalizer)
335 | {
336 | this.equalizer = equalizer;
337 | applyEqualizer();
338 | }
339 |
340 | private void applyEqualizer()
341 | {
342 | setNativeEqualizer(mInternalMediaPlayerInstance, this.equalizer);
343 | }
344 | private native int setNativeEqualizer(long mediaPlayer, float[] bands);
345 |
346 | public boolean frameSkipEnabled() {
347 | return frameSkip;
348 | }
349 |
350 | public void setFrameSkip(boolean frameskip) {
351 | this.frameSkip = frameskip;
352 | }
353 |
354 | public int getNetworkCaching() {
355 | return this.networkCaching;
356 | }
357 |
358 | public void setNetworkCaching(int networkcaching) {
359 | this.networkCaching = networkcaching;
360 | }
361 |
362 | /**
363 | * Initialize the libVLC class.
364 | *
365 | * This function must be called before using any libVLC functions.
366 | *
367 | * @throws LibVlcException
368 | */
369 | public void init(Context context) throws LibVlcException {
370 | Log.v(TAG, "Initializing LibVLC");
371 | mDebugLogBuffer = new StringBuffer();
372 | if (!mIsInitialized) {
373 | if(!LibVlcUtil.hasCompatibleCPU(context)) {
374 | Log.e(TAG, LibVlcUtil.getErrorMsg());
375 | throw new LibVlcException();
376 | }
377 | nativeInit();
378 | mMediaList = mPrimaryList = new MediaList(this);
379 | setEventHandler(EventHandler.getInstance());
380 | mIsInitialized = true;
381 | }
382 | }
383 |
384 | /**
385 | * Destroy this libVLC instance
386 | * @note You must call it before exiting
387 | */
388 | public void destroy() {
389 | Log.v(TAG, "Destroying LibVLC instance");
390 | nativeDestroy();
391 | detachEventHandler();
392 | mIsInitialized = false;
393 | }
394 |
395 | /**
396 | * Open the Java audio output.
397 | * This function is called by the native code
398 | */
399 | public void initAout(int sampleRateInHz, int channels, int samples) {
400 | Log.d(TAG, "Opening the java audio output");
401 | mAout.init(sampleRateInHz, channels, samples);
402 | }
403 |
404 | /**
405 | * Play an audio buffer taken from the native code
406 | * This function is called by the native code
407 | */
408 | public void playAudio(byte[] audioData, int bufferSize) {
409 | mAout.playBuffer(audioData, bufferSize);
410 | }
411 |
412 | /**
413 | * Pause the Java audio output
414 | * This function is called by the native code
415 | */
416 | public void pauseAout() {
417 | Log.d(TAG, "Pausing the java audio output");
418 | mAout.pause();
419 | }
420 |
421 | /**
422 | * Close the Java audio output
423 | * This function is called by the native code
424 | */
425 | public void closeAout() {
426 | Log.d(TAG, "Closing the java audio output");
427 | mAout.release();
428 | }
429 |
430 | /**
431 | * Play a media from the media list (playlist)
432 | *
433 | * @param position The index of the media
434 | */
435 | public void playIndex(int position) {
436 | String mrl = mMediaList.getMRL(position);
437 | if (mrl == null)
438 | return;
439 | String[] options = mMediaList.getMediaOptions(position);
440 | mInternalMediaPlayerIndex = position;
441 | playMRL(mLibVlcInstance, mrl, options);
442 | }
443 |
444 | /**
445 | * Play an MRL directly.
446 | *
447 | * @param mrl MRL of the media to play.
448 | */
449 | public void playMRL(String mrl) {
450 | // index=-1 will return options from libvlc instance without relying on MediaList
451 | String[] options = mMediaList.getMediaOptions(-1);
452 | mInternalMediaPlayerIndex = 0;
453 | playMRL(mLibVlcInstance, mrl, options);
454 | }
455 |
456 | public TrackInfo[] readTracksInfo(String mrl) {
457 | return readTracksInfo(mLibVlcInstance, mrl);
458 | }
459 |
460 | /**
461 | * Get a media thumbnail.
462 | */
463 | public byte[] getThumbnail(String mrl, int i_width, int i_height) {
464 | return getThumbnail(mLibVlcInstance, mrl, i_width, i_height);
465 | }
466 |
467 | /**
468 | * Return true if there is a video track in the file
469 | */
470 | public boolean hasVideoTrack(String mrl) throws java.io.IOException {
471 | return hasVideoTrack(mLibVlcInstance, mrl);
472 | }
473 |
474 | /**
475 | * Sets the speed of playback (1 being normal speed, 2 being twice as fast)
476 | *
477 | * @param rate
478 | */
479 | public native void setRate(float rate);
480 |
481 | /**
482 | * Get the current playback speed
483 | */
484 | public native float getRate();
485 |
486 | /**
487 | * Initialize the libvlc C library
488 | * @return a pointer to the libvlc instance
489 | */
490 | private native void nativeInit() throws LibVlcException;
491 |
492 | /**
493 | * Close the libvlc C library
494 | * @note mLibVlcInstance should be 0 after a call to destroy()
495 | */
496 | private native void nativeDestroy();
497 |
498 | /**
499 | * Start buffering to the mDebugLogBuffer.
500 | */
501 | public native void startDebugBuffer();
502 | public native void stopDebugBuffer();
503 | public String getBufferContent() {
504 | return mDebugLogBuffer.toString();
505 | }
506 |
507 | public void clearBuffer() {
508 | mDebugLogBuffer.setLength(0);
509 | }
510 |
511 | public boolean isDebugBuffering() {
512 | return mIsBufferingLog;
513 | }
514 |
515 | /**
516 | * Play an mrl
517 | */
518 | private native void playMRL(long instance, String mrl, String[] mediaOptions);
519 |
520 | /**
521 | * Returns true if any media is playing
522 | */
523 | public native boolean isPlaying();
524 |
525 | /**
526 | * Returns true if any media is seekable
527 | */
528 | public native boolean isSeekable();
529 |
530 | /**
531 | * Plays any loaded media
532 | */
533 | public native void play();
534 |
535 | /**
536 | * Pauses any playing media
537 | */
538 | public native void pause();
539 |
540 | /**
541 | * Stops any playing media
542 | */
543 | public native void stop();
544 |
545 | /**
546 | * Gets volume as integer
547 | */
548 | public native int getVolume();
549 |
550 | /**
551 | * Sets volume as integer
552 | * @param volume: Volume level passed as integer
553 | */
554 | public native int setVolume(int volume);
555 |
556 | /**
557 | * Gets the current movie time (in ms).
558 | * @return the movie time (in ms), or -1 if there is no media.
559 | */
560 | public native long getTime();
561 |
562 | /**
563 | * Sets the movie time (in ms), if any media is being played.
564 | * @param time: Time in ms.
565 | * @return the movie time (in ms), or -1 if there is no media.
566 | */
567 | public native long setTime(long time);
568 |
569 | /**
570 | * Gets the movie position.
571 | * @return the movie position, or -1 for any error.
572 | */
573 | public native float getPosition();
574 |
575 | /**
576 | * Sets the movie position.
577 | * @param pos: movie position.
578 | */
579 | public native void setPosition(float pos);
580 |
581 | /**
582 | * Gets current movie's length in ms.
583 | * @return the movie length (in ms), or -1 if there is no media.
584 | */
585 | public native long getLength();
586 |
587 | /**
588 | * Get the libVLC version
589 | * @return the libVLC version string
590 | */
591 | public native String version();
592 |
593 | /**
594 | * Get the libVLC compiler
595 | * @return the libVLC compiler string
596 | */
597 | public native String compiler();
598 |
599 | /**
600 | * Get the libVLC changeset
601 | * @return the libVLC changeset string
602 | */
603 | public native String changeset();
604 |
605 | /**
606 | * Get a media thumbnail.
607 | * @return a bytearray with the RGBA thumbnail data inside.
608 | */
609 | private native byte[] getThumbnail(long instance, String mrl, int i_width, int i_height);
610 |
611 | /**
612 | * Return true if there is a video track in the file
613 | */
614 | private native boolean hasVideoTrack(long instance, String mrl);
615 |
616 | private native TrackInfo[] readTracksInfo(long instance, String mrl);
617 |
618 | public native TrackInfo[] readTracksInfoInternal();
619 |
620 | public native int getAudioTracksCount();
621 |
622 | public native Map getAudioTrackDescription();
623 |
624 | public native int getAudioTrack();
625 |
626 | public native int setAudioTrack(int index);
627 |
628 | public native int getVideoTracksCount();
629 |
630 | public native int addSubtitleTrack(String path);
631 |
632 | public native Map getSpuTrackDescription();
633 |
634 | public native int getSpuTrack();
635 |
636 | public native int setSpuTrack(int index);
637 |
638 | public native int getSpuTracksCount();
639 |
640 | public static native String nativeToURI(String path);
641 |
642 | public native static void sendMouseEvent( int action, int button, int x, int y);
643 |
644 | /**
645 | * Quickly converts path to URIs, which are mandatory in libVLC.
646 | *
647 | * @param path
648 | * The path to be converted.
649 | * @return A URI representation of path
650 | */
651 | public static String PathToURI(String path) {
652 | if(path == null) {
653 | throw new NullPointerException("Cannot convert null path!");
654 | }
655 | return LibVLC.nativeToURI(path);
656 | }
657 |
658 | public static native void nativeReadDirectory(String path, ArrayList res);
659 |
660 | public native static boolean nativeIsPathDirectory(String path);
661 |
662 | /**
663 | * Expand and continue playing the current media.
664 | *
665 | * @return the index of the media was expanded, and -1 if no media was expanded
666 | */
667 | public int expandAndPlay() {
668 | int r = mMediaList.expandMedia(mInternalMediaPlayerIndex);
669 | if(r == 0)
670 | this.playIndex(mInternalMediaPlayerIndex);
671 | return r;
672 | }
673 |
674 | /**
675 | * Expand the current media.
676 | * @return the index of the media was expanded, and -1 if no media was expanded
677 | */
678 | public int expand() {
679 | return mMediaList.expandMedia(mInternalMediaPlayerIndex);
680 | }
681 |
682 | private native void setEventHandler(EventHandler eventHandler);
683 |
684 | private native void detachEventHandler();
685 |
686 | public native float[] getBands();
687 |
688 | public native String[] getPresets();
689 |
690 | public native float[] getPreset(int index);
691 |
692 | public static interface OnNativeCrashListener {
693 | public void onNativeCrash();
694 | }
695 |
696 | public void setOnNativeCrashListener(OnNativeCrashListener l) {
697 | mOnNativeCrashListener = l;
698 | }
699 |
700 | private void onNativeCrash() {
701 | if (mOnNativeCrashListener != null)
702 | mOnNativeCrashListener.onNativeCrash();
703 | }
704 | }
705 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/LibVlcException.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * LibVlcException.java
3 | *****************************************************************************
4 | * Copyright © 2011-2012 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | /**
22 | * LibVlcException: exceptions thrown by the native LibVLC interface
23 | */
24 | package org.videolan.libvlc;
25 |
26 | /**
27 | * @author jpeg
28 | *
29 | */
30 | public class LibVlcException extends Exception {
31 | private static final long serialVersionUID = -1909522348226924189L;
32 |
33 | /**
34 | * Create an empty error
35 | */
36 | public LibVlcException() {
37 | super();
38 | }
39 |
40 | /**
41 | * @param detailMessage
42 | */
43 | public LibVlcException(String detailMessage) {
44 | super(detailMessage);
45 | }
46 |
47 | /**
48 | * @param throwable
49 | */
50 | public LibVlcException(Throwable throwable) {
51 | super(throwable);
52 | }
53 |
54 | /**
55 | * @param detailMessage
56 | * @param throwable
57 | */
58 | public LibVlcException(String detailMessage, Throwable throwable) {
59 | super(detailMessage, throwable);
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/LibVlcUtil.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * LibVlcUtil.java
3 | *****************************************************************************
4 | * Copyright © 2011-2013 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | import java.io.BufferedReader;
24 | import java.io.File;
25 | import java.io.FileNotFoundException;
26 | import java.io.FileReader;
27 | import java.io.IOException;
28 | import java.io.RandomAccessFile;
29 | import java.nio.ByteBuffer;
30 | import java.nio.ByteOrder;
31 | import java.util.Locale;
32 |
33 | import android.content.Context;
34 | import android.net.Uri;
35 | import android.os.Build;
36 | import android.util.Log;
37 |
38 | public class LibVlcUtil {
39 | public final static String TAG = "VLC/LibVLC/Util";
40 |
41 | public static boolean isFroyoOrLater()
42 | {
43 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO;
44 | }
45 |
46 | public static boolean isGingerbreadOrLater()
47 | {
48 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD;
49 | }
50 |
51 | public static boolean isHoneycombOrLater()
52 | {
53 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB;
54 | }
55 |
56 | public static boolean isICSOrLater()
57 | {
58 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH;
59 | }
60 |
61 | public static boolean isJellyBeanOrLater()
62 | {
63 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN;
64 | }
65 |
66 | public static boolean isJellyBeanMR1OrLater()
67 | {
68 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
69 | }
70 |
71 | public static boolean isJellyBeanMR2OrLater()
72 | {
73 | return android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
74 | }
75 |
76 | private static String errorMsg = null;
77 | private static boolean isCompatible = false;
78 | public static String getErrorMsg() {
79 | return errorMsg;
80 | }
81 |
82 | public static File URItoFile(String URI) {
83 | return new File(Uri.decode(URI).replace("file://",""));
84 | }
85 |
86 | public static String URItoFileName(String URI) {
87 | return URItoFile(URI).getName();
88 | }
89 |
90 | public static boolean hasCompatibleCPU(Context context)
91 | {
92 | // If already checked return cached result
93 | if(errorMsg != null || isCompatible) return isCompatible;
94 |
95 | ElfData elf = readLib(context.getApplicationInfo().dataDir + "/lib/libvlcjni.so");
96 | if(elf == null) {
97 | Log.e(TAG, "WARNING: Unable to read libvlcjni.so; cannot check device ABI!");
98 | Log.e(TAG, "WARNING: Cannot guarantee correct ABI for this build (may crash)!");
99 | return true;
100 | }
101 |
102 | String CPU_ABI = android.os.Build.CPU_ABI;
103 | String CPU_ABI2 = "none";
104 | if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) { // CPU_ABI2 since 2.2
105 | try {
106 | CPU_ABI2 = (String)android.os.Build.class.getDeclaredField("CPU_ABI2").get(null);
107 | } catch (Exception e) { }
108 | }
109 |
110 | Log.i(TAG, "machine = " + (elf.e_machine == EM_ARM ? "arm" : elf.e_machine == EM_386 ? "x86" : "mips"));
111 | Log.i(TAG, "arch = " + elf.att_arch);
112 | Log.i(TAG, "fpu = " + elf.att_fpu);
113 | boolean hasNeon = false, hasFpu = false, hasArmV6 = false,
114 | hasArmV7 = false, hasMips = false, hasX86 = false;
115 | float bogoMIPS = -1;
116 | int processors = 0;
117 |
118 | if(CPU_ABI.equals("x86")) {
119 | hasX86 = true;
120 | } else if(CPU_ABI.equals("armeabi-v7a") ||
121 | CPU_ABI2.equals("armeabi-v7a")) {
122 | hasArmV7 = true;
123 | hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
124 | } else if(CPU_ABI.equals("armeabi") ||
125 | CPU_ABI2.equals("armeabi")) {
126 | hasArmV6 = true;
127 | }
128 |
129 | try {
130 | FileReader fileReader = new FileReader("/proc/cpuinfo");
131 | BufferedReader br = new BufferedReader(fileReader);
132 | String line;
133 | while((line = br.readLine()) != null) {
134 | if(!hasArmV7 && line.contains("ARMv7")) {
135 | hasArmV7 = true;
136 | hasArmV6 = true; /* Armv7 is backwards compatible to < v6 */
137 | }
138 | if(!hasArmV7 && !hasArmV6 && line.contains("ARMv6"))
139 | hasArmV6 = true;
140 | // "clflush size" is a x86-specific cpuinfo tag.
141 | // (see kernel sources arch/x86/kernel/cpu/proc.c)
142 | if(line.contains("clflush size"))
143 | hasX86 = true;
144 | // "microsecond timers" is specific to MIPS.
145 | // see arch/mips/kernel/proc.c
146 | if(line.contains("microsecond timers"))
147 | hasMips = true;
148 | if(!hasNeon && line.contains("neon"))
149 | hasNeon = true;
150 | if(!hasFpu && line.contains("vfp"))
151 | hasFpu = true;
152 | if(line.startsWith("processor"))
153 | processors++;
154 | if(bogoMIPS < 0 && line.toLowerCase(Locale.ENGLISH).contains("bogomips")) {
155 | String[] bogo_parts = line.split(":");
156 | try {
157 | bogoMIPS = Float.parseFloat(bogo_parts[1].trim());
158 | } catch(NumberFormatException e) {
159 | bogoMIPS = -1; // invalid bogomips
160 | }
161 | }
162 | }
163 | fileReader.close();
164 | } catch(IOException ex){
165 | ex.printStackTrace();
166 | errorMsg = "IOException whilst reading cpuinfo flags";
167 | isCompatible = false;
168 | return false;
169 | }
170 | if(processors == 0)
171 | processors = 1; // possibly borked cpuinfo?
172 |
173 | // Enforce proper architecture to prevent problems
174 | if(elf.e_machine == EM_386 && !hasX86) {
175 | errorMsg = "x86 build on non-x86 device";
176 | isCompatible = false;
177 | return false;
178 | } else if(elf.e_machine == EM_ARM && hasX86) {
179 | errorMsg = "ARM build on x86 device";
180 | isCompatible = false;
181 | return false;
182 | }
183 |
184 | if(elf.e_machine == EM_MIPS && !hasMips) {
185 | errorMsg = "MIPS build on non-MIPS device";
186 | isCompatible = false;
187 | return false;
188 | } else if(elf.e_machine == EM_ARM && hasMips) {
189 | errorMsg = "ARM build on MIPS device";
190 | isCompatible = false;
191 | return false;
192 | }
193 |
194 | if(elf.e_machine == EM_ARM && elf.att_arch.startsWith("v7") && !hasArmV7) {
195 | errorMsg = "ARMv7 build on non-ARMv7 device";
196 | isCompatible = false;
197 | return false;
198 | }
199 | if(elf.e_machine == EM_ARM) {
200 | if(elf.att_arch.startsWith("v6") && !hasArmV6) {
201 | errorMsg = "ARMv6 build on non-ARMv6 device";
202 | isCompatible = false;
203 | return false;
204 | } else if(elf.att_fpu && !hasFpu) {
205 | errorMsg = "FPU-enabled build on non-FPU device";
206 | isCompatible = false;
207 | return false;
208 | }
209 | }
210 |
211 | errorMsg = null;
212 | isCompatible = true;
213 | // Store into MachineSpecs
214 | machineSpecs = new MachineSpecs();
215 | machineSpecs.hasArmV6 = hasArmV6;
216 | machineSpecs.hasArmV7 = hasArmV7;
217 | machineSpecs.hasFpu = hasFpu;
218 | machineSpecs.hasMips = hasMips;
219 | machineSpecs.hasNeon = hasNeon;
220 | machineSpecs.hasX86 = hasX86;
221 | machineSpecs.bogoMIPS = bogoMIPS;
222 | machineSpecs.processors = processors;
223 | return true;
224 | }
225 |
226 | public static MachineSpecs getMachineSpecs() {
227 | return machineSpecs;
228 | }
229 | private static MachineSpecs machineSpecs = null;
230 | public static class MachineSpecs {
231 | public boolean hasNeon;
232 | public boolean hasFpu;
233 | public boolean hasArmV6;
234 | public boolean hasArmV7;
235 | public boolean hasMips;
236 | public boolean hasX86;
237 | public float bogoMIPS;
238 | public int processors;
239 | }
240 |
241 | private static final int EM_386 = 3;
242 | private static final int EM_MIPS = 8;
243 | private static final int EM_ARM = 40;
244 | private static final int ELF_HEADER_SIZE = 52;
245 | private static final int SECTION_HEADER_SIZE = 40;
246 | private static final int SHT_ARM_ATTRIBUTES = 0x70000003;
247 | private static class ElfData {
248 | ByteOrder order;
249 | int e_machine;
250 | int e_shoff;
251 | int e_shnum;
252 | int sh_offset;
253 | int sh_size;
254 | String att_arch;
255 | boolean att_fpu;
256 | }
257 |
258 | /** '*' prefix means it's unsupported */
259 | private static String[] CPU_archs = {"*Pre-v4", "*v4", "*v4T",
260 | "v5T", "v5TE", "v5TEJ",
261 | "v6", "v6KZ", "v6T2", "v6K", "v7",
262 | "*v6-M", "*v6S-M", "*v7E-M", "*v8"};
263 |
264 | private static ElfData readLib(String path) {
265 | File file = new File(path);
266 | if (!file.exists() || !file.canRead())
267 | return null;
268 |
269 | RandomAccessFile in = null;
270 | try {
271 | in = new RandomAccessFile(file, "r");
272 |
273 | ElfData elf = new ElfData();
274 | if (!readHeader(in, elf))
275 | return null;
276 |
277 | switch (elf.e_machine) {
278 | case EM_386:
279 | case EM_MIPS:
280 | return elf;
281 | case EM_ARM:
282 | in.close();
283 | in = new RandomAccessFile(file, "r");
284 | if (!readSection(in, elf))
285 | return null;
286 | in.close();
287 | in = new RandomAccessFile(file, "r");
288 | if (!readArmAttributes(in, elf))
289 | return null;
290 | break;
291 | default:
292 | return null;
293 | }
294 | return elf;
295 | } catch (FileNotFoundException e) {
296 | e.printStackTrace();
297 | } catch (IOException e) {
298 | e.printStackTrace();
299 | } finally {
300 | try {
301 | if (in != null)
302 | in.close();
303 | } catch (IOException e) {
304 | }
305 | }
306 | return null;
307 | }
308 |
309 | private static boolean readHeader(RandomAccessFile in, ElfData elf) throws IOException {
310 | // http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html
311 | byte[] bytes = new byte[ELF_HEADER_SIZE];
312 | in.readFully(bytes);
313 | if (bytes[0] != 127 ||
314 | bytes[1] != 'E' ||
315 | bytes[2] != 'L' ||
316 | bytes[3] != 'F' ||
317 | bytes[4] != 1) { // ELFCLASS32, Only 32bit header is supported
318 | return false;
319 | }
320 |
321 | elf.order = bytes[5] == 1
322 | ? ByteOrder.LITTLE_ENDIAN // ELFDATA2LSB
323 | : ByteOrder.BIG_ENDIAN; // ELFDATA2MSB
324 |
325 | // wrap bytes in a ByteBuffer to force endianess
326 | ByteBuffer buffer = ByteBuffer.wrap(bytes);
327 | buffer.order(elf.order);
328 |
329 | elf.e_machine = buffer.getShort(18); /* Architecture */
330 | elf.e_shoff = buffer.getInt(32); /* Section header table file offset */
331 | elf.e_shnum = buffer.getShort(48); /* Section header table entry count */
332 | return true;
333 | }
334 |
335 | private static boolean readSection(RandomAccessFile in, ElfData elf) throws IOException {
336 | byte[] bytes = new byte[SECTION_HEADER_SIZE];
337 | in.seek(elf.e_shoff);
338 |
339 | for (int i = 0; i < elf.e_shnum; ++i) {
340 | in.readFully(bytes);
341 |
342 | // wrap bytes in a ByteBuffer to force endianess
343 | ByteBuffer buffer = ByteBuffer.wrap(bytes);
344 | buffer.order(elf.order);
345 |
346 | int sh_type = buffer.getInt(4); /* Section type */
347 | if (sh_type != SHT_ARM_ATTRIBUTES)
348 | continue;
349 |
350 | elf.sh_offset = buffer.getInt(16); /* Section file offset */
351 | elf.sh_size = buffer.getInt(20); /* Section size in bytes */
352 | return true;
353 | }
354 |
355 | return false;
356 | }
357 |
358 | private static boolean readArmAttributes(RandomAccessFile in, ElfData elf) throws IOException {
359 | byte[] bytes = new byte[elf.sh_size];
360 | in.seek(elf.sh_offset);
361 | in.readFully(bytes);
362 |
363 | // wrap bytes in a ByteBuffer to force endianess
364 | ByteBuffer buffer = ByteBuffer.wrap(bytes);
365 | buffer.order(elf.order);
366 |
367 | //http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/IHI0044E_aaelf.pdf
368 | //http://infocenter.arm.com/help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf
369 | if (buffer.get() != 'A') // format-version
370 | return false;
371 |
372 | // sub-sections loop
373 | while (buffer.remaining() > 0) {
374 | int start_section = buffer.position();
375 | int length = buffer.getInt();
376 | String vendor = getString(buffer);
377 | if (vendor.equals("aeabi")) {
378 | // tags loop
379 | while (buffer.position() < start_section + length) {
380 | int start = buffer.position();
381 | int tag = buffer.get();
382 | int size = buffer.getInt();
383 | // skip if not Tag_File, we don't care about others
384 | if (tag != 1) {
385 | buffer.position(start + size);
386 | continue;
387 | }
388 |
389 | // attributes loop
390 | while (buffer.position() < start + size) {
391 | tag = getUleb128(buffer);
392 | if (tag == 6) { // CPU_arch
393 | int arch = getUleb128(buffer);
394 | elf.att_arch = CPU_archs[arch];
395 | }
396 | else if (tag == 27) { // ABI_HardFP_use
397 | getUleb128(buffer);
398 | elf.att_fpu = true;
399 | }
400 | else {
401 | // string for 4=CPU_raw_name / 5=CPU_name / 32=compatibility
402 | // string for >32 && odd tags
403 | // uleb128 for other
404 | tag %= 128;
405 | if (tag == 4 || tag == 5 || tag == 32 || (tag > 32 && (tag & 1) != 0))
406 | getString(buffer);
407 | else
408 | getUleb128(buffer);
409 | }
410 | }
411 | }
412 | break;
413 | }
414 | }
415 | return true;
416 | }
417 |
418 | private static String getString(ByteBuffer buffer) {
419 | StringBuilder sb = new StringBuilder(buffer.limit());
420 | while (buffer.remaining() > 0) {
421 | char c = (char) buffer.get();
422 | if (c == 0)
423 | break;
424 | sb.append(c);
425 | }
426 | return sb.toString();
427 | }
428 |
429 | private static int getUleb128(ByteBuffer buffer) {
430 | int ret = 0;
431 | int c;
432 | do {
433 | ret <<= 7;
434 | c = buffer.get();
435 | ret |= c & 0x7f;
436 | } while((c & 0x80) > 0);
437 |
438 | return ret;
439 | }
440 | }
441 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/Media.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * Media.java
3 | *****************************************************************************
4 | * Copyright © 2011-2013 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation; either version 2 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program; if not, write to the Free Software
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | import java.lang.reflect.InvocationTargetException;
24 | import java.lang.reflect.Method;
25 | import java.util.HashSet;
26 | import java.util.Locale;
27 |
28 | import android.content.Context;
29 | import android.graphics.Bitmap;
30 | import android.util.Log;
31 |
32 | public class Media implements Comparable {
33 | public final static String TAG = "VLC/LibVLC/Media";
34 |
35 | public final static HashSet VIDEO_EXTENSIONS;
36 | public final static HashSet AUDIO_EXTENSIONS;
37 | public final static String EXTENSIONS_REGEX;
38 | public final static HashSet FOLDER_BLACKLIST;
39 |
40 | static {
41 | String[] video_extensions = {
42 | ".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".avi", ".divx", "drc", ".dv",
43 | ".f4v", ".flv", ".gvi", ".gxf", ".ismv", ".iso", ".m1v", ".m2v", ".m2t", ".m2ts",
44 | ".m4v", ".mkv", ".mov", ".mp2", ".mp2v", ".mp4", ".mp4v", ".mpe", ".mpeg",
45 | ".mpeg1", ".mpeg2", ".mpeg4", ".mpg", ".mpv2", ".mts", ".mtv", ".mxf", ".mxg",
46 | ".nsv", ".nut", ".nuv", ".ogm", ".ogv", ".ogx", ".ps", ".rec", ".rm", ".rmvb",
47 | ".tod", ".ts", ".tts", ".vob", ".vro", ".webm", ".wm", ".wmv", ".wtv", ".xesc" };
48 |
49 | String[] audio_extensions = {
50 | ".3ga", ".a52", ".aac", ".ac3", ".adt", ".adts", ".aif", ".aifc", ".aiff", ".amr",
51 | ".aob", ".ape", ".awb", ".caf", ".dts", ".flac", ".it", ".m4a", ".m4b", ".m4p",
52 | ".mid", ".mka", ".mlp", ".mod", ".mpa", ".mp1", ".mp2", ".mp3", ".mpc", ".mpga",
53 | ".oga", ".ogg", ".oma", ".opus", ".ra", ".ram", ".rmi", ".s3m", ".spx", ".tta",
54 | ".voc", ".vqf", ".w64", ".wav", ".wma", ".wv", ".xa", ".xm" };
55 |
56 | String[] folder_blacklist = {
57 | "/alarms",
58 | "/notifications",
59 | "/ringtones",
60 | "/media/alarms",
61 | "/media/notifications",
62 | "/media/ringtones",
63 | "/media/audio/alarms",
64 | "/media/audio/notifications",
65 | "/media/audio/ringtones",
66 | "/Android/data/" };
67 |
68 | VIDEO_EXTENSIONS = new HashSet();
69 | for (String item : video_extensions)
70 | VIDEO_EXTENSIONS.add(item);
71 | AUDIO_EXTENSIONS = new HashSet();
72 | for (String item : audio_extensions)
73 | AUDIO_EXTENSIONS.add(item);
74 |
75 | StringBuilder sb = new StringBuilder(115);
76 | sb.append(".+(\\.)((?i)(");
77 | sb.append(video_extensions[0].substring(1));
78 | for(int i = 1; i < video_extensions.length; i++) {
79 | sb.append('|');
80 | sb.append(video_extensions[i].substring(1));
81 | }
82 | for(int i = 0; i < audio_extensions.length; i++) {
83 | sb.append('|');
84 | sb.append(audio_extensions[i].substring(1));
85 | }
86 | sb.append("))");
87 | EXTENSIONS_REGEX = sb.toString();
88 | FOLDER_BLACKLIST = new HashSet();
89 | for (String item : folder_blacklist)
90 | FOLDER_BLACKLIST.add(android.os.Environment.getExternalStorageDirectory().getPath() + item);
91 | }
92 |
93 | public final static int TYPE_ALL = -1;
94 | public final static int TYPE_VIDEO = 0;
95 | public final static int TYPE_AUDIO = 1;
96 | public final static int TYPE_GROUP = 2;
97 |
98 | /** Metadata from libvlc_media */
99 | protected String mTitle;
100 | private String mArtist;
101 | private String mGenre;
102 | private String mCopyright;
103 | private String mAlbum;
104 | private String mTrackNumber;
105 | private String mDescription;
106 | private String mRating;
107 | private String mDate;
108 | private String mSettings;
109 | private String mNowPlaying;
110 | private String mPublisher;
111 | private String mEncodedBy;
112 | private String mTrackID;
113 | private String mArtworkURL;
114 |
115 | private final String mLocation;
116 | private String mFilename;
117 | private long mTime = 0;
118 | private int mAudioTrack = -1;
119 | private int mSpuTrack = -2;
120 | private long mLength = 0;
121 | private int mType;
122 | private int mWidth = 0;
123 | private int mHeight = 0;
124 | private Bitmap mPicture;
125 | private boolean mIsPictureParsed;
126 |
127 | /**
128 | * Create a new Media
129 | * @param libVLC A pointer to the libVLC instance. Should not be NULL
130 | * @param URI The URI of the media.
131 | */
132 | public Media(LibVLC libVLC, String URI) {
133 | if(libVLC == null)
134 | throw new NullPointerException("libVLC was null");
135 |
136 | mLocation = URI;
137 |
138 | mType = TYPE_ALL;
139 | TrackInfo[] tracks = libVLC.readTracksInfo(mLocation);
140 |
141 | extractTrackInfo(tracks);
142 | }
143 |
144 | private void extractTrackInfo(TrackInfo[] tracks) {
145 | if (tracks == null)
146 | return;
147 |
148 | for (TrackInfo track : tracks) {
149 | if (track.Type == TrackInfo.TYPE_VIDEO) {
150 | mType = TYPE_VIDEO;
151 | mWidth = track.Width;
152 | mHeight = track.Height;
153 | } else if (mType == TYPE_ALL && track.Type == TrackInfo.TYPE_AUDIO){
154 | mType = TYPE_AUDIO;
155 | } else if (track.Type == TrackInfo.TYPE_META) {
156 | mLength = track.Length;
157 | mTitle = track.Title;
158 | mArtist = getValueWrapper(track.Artist, UnknownStringType.Artist);
159 | mAlbum = getValueWrapper(track.Album, UnknownStringType.Album);
160 | mGenre = getValueWrapper(track.Genre, UnknownStringType.Genre);
161 | mArtworkURL = track.ArtworkURL;
162 | Log.d(TAG, "Title " + mTitle);
163 | Log.d(TAG, "Artist " + mArtist);
164 | Log.d(TAG, "Genre " + mGenre);
165 | Log.d(TAG, "Album " + mAlbum);
166 | }
167 | }
168 |
169 | /* No useful ES found */
170 | if (mType == TYPE_ALL) {
171 | int dotIndex = mLocation.lastIndexOf(".");
172 | if (dotIndex != -1) {
173 | String fileExt = mLocation.substring(dotIndex);
174 | if( Media.VIDEO_EXTENSIONS.contains(fileExt) ) {
175 | mType = TYPE_VIDEO;
176 | } else if (Media.AUDIO_EXTENSIONS.contains(fileExt)) {
177 | mType = TYPE_AUDIO;
178 | }
179 | }
180 | }
181 | }
182 |
183 | public Media(String location, long time, long length, int type,
184 | Bitmap picture, String title, String artist, String genre, String album,
185 | int width, int height, String artworkURL, int audio, int spu) {
186 | mLocation = location;
187 | mFilename = null;
188 | mTime = time;
189 | mAudioTrack = audio;
190 | mSpuTrack = spu;
191 | mLength = length;
192 | mType = type;
193 | mPicture = picture;
194 | mWidth = width;
195 | mHeight = height;
196 |
197 | mTitle = title;
198 | mArtist = getValueWrapper(artist, UnknownStringType.Artist);
199 | mGenre = getValueWrapper(genre, UnknownStringType.Genre);
200 | mAlbum = getValueWrapper(album, UnknownStringType.Album);
201 | mArtworkURL = artworkURL;
202 | }
203 |
204 | private enum UnknownStringType { Artist , Genre, Album };
205 | /**
206 | * Uses introspection to read VLC l10n databases, so that we can sever the
207 | * hard-coded dependency gracefully for 3rd party libvlc apps while still
208 | * maintaining good l10n in VLC for Android.
209 | *
210 | * @see org.videolan.vlc.Util#getValue(String, int)
211 | *
212 | * @param string The default string
213 | * @param type Alias for R.string.xxx
214 | * @return The default string if not empty or string from introspection
215 | */
216 | private static String getValueWrapper(String string, UnknownStringType type) {
217 | if(string != null && string.length() > 0) return string;
218 |
219 | try {
220 | Class> stringClass = Class.forName("org.videolan.vlc.R$string");
221 | Class> utilClass = Class.forName("org.videolan.vlc.Util");
222 |
223 | Integer value;
224 | switch(type) {
225 | case Album:
226 | value = (Integer)stringClass.getField("unknown_album").get(null);
227 | break;
228 | case Genre:
229 | value = (Integer)stringClass.getField("unknown_genre").get(null);
230 | break;
231 | case Artist:
232 | default:
233 | value = (Integer)stringClass.getField("unknown_artist").get(null);
234 | break;
235 | }
236 |
237 | Method getValueMethod = utilClass.getDeclaredMethod("getValue", String.class, Integer.TYPE);
238 | // Util.getValue(string, R.string.xxx);
239 | return (String) getValueMethod.invoke(null, string, value);
240 | } catch (ClassNotFoundException e) {
241 | } catch (IllegalArgumentException e) {
242 | } catch (IllegalAccessException e) {
243 | } catch (NoSuchFieldException e) {
244 | } catch (NoSuchMethodException e) {
245 | } catch (InvocationTargetException e) {
246 | }
247 |
248 | // VLC for Android translations not available (custom app perhaps)
249 | // Use hardcoded English phrases.
250 | switch(type) {
251 | case Album:
252 | return "Unknown Album";
253 | case Genre:
254 | return "Unknown Genre";
255 | case Artist:
256 | default:
257 | return "Unknown Artist";
258 | }
259 | }
260 |
261 | /**
262 | * Compare the filenames to sort items
263 | */
264 | @Override
265 | public int compareTo(Media another) {
266 | return mTitle.toUpperCase(Locale.getDefault()).compareTo(
267 | another.getTitle().toUpperCase(Locale.getDefault()));
268 | }
269 |
270 | public String getLocation() {
271 | return mLocation;
272 | }
273 |
274 | public void updateMeta() {
275 |
276 | }
277 |
278 | public String getFileName() {
279 | if (mFilename == null) {
280 | mFilename = LibVlcUtil.URItoFileName(mLocation);
281 | }
282 | return mFilename;
283 | }
284 |
285 | public long getTime() {
286 | return mTime;
287 | }
288 |
289 | public void setTime(long time) {
290 | mTime = time;
291 | }
292 |
293 | public int getAudioTrack() {
294 | return mAudioTrack;
295 | }
296 |
297 | public void setAudioTrack(int track) {
298 | mAudioTrack = track;
299 | }
300 |
301 | public int getSpuTrack() {
302 | return mSpuTrack;
303 | }
304 |
305 | public void setSpuTrack(int track) {
306 | mSpuTrack = track;
307 | }
308 |
309 | public long getLength() {
310 | return mLength;
311 | }
312 |
313 | public int getType() {
314 | return mType;
315 | }
316 |
317 | public int getWidth() {
318 | return mWidth;
319 | }
320 |
321 | public int getHeight() {
322 | return mHeight;
323 | }
324 |
325 | /**
326 | * Returns the raw picture object. Likely to be NULL in VLC for Android
327 | * due to lazy-loading.
328 | *
329 | * Use {@link org.videolan.vlc.Util#getPictureFromCache(Media)} instead.
330 | *
331 | * @return The raw picture or NULL
332 | */
333 | public Bitmap getPicture() {
334 | return mPicture;
335 | }
336 |
337 | /**
338 | * Sets the raw picture object.
339 | *
340 | * In VLC for Android, use {@link org.videolan.vlc.Util#setPicture(Context, Media, Bitmap)} instead.
341 | *
342 | * @param p
343 | */
344 | public void setPicture(Bitmap p) {
345 | mPicture = p;
346 | }
347 |
348 | public boolean isPictureParsed() {
349 | return mIsPictureParsed;
350 | }
351 |
352 | public void setPictureParsed(boolean isParsed) {
353 | mIsPictureParsed = isParsed;
354 | }
355 |
356 | public String getTitle() {
357 | if (mTitle != null && mType != TYPE_VIDEO)
358 | return mTitle;
359 | else {
360 | int end = getFileName().lastIndexOf(".");
361 | if (end <= 0)
362 | return getFileName();
363 | return getFileName().substring(0, end);
364 | }
365 | }
366 |
367 | public String getSubtitle() {
368 | return mType != TYPE_VIDEO ? mArtist + " - " + mAlbum : "";
369 | }
370 |
371 | public String getArtist() {
372 | return mArtist;
373 | }
374 |
375 | public String getGenre() {
376 | if(getValueWrapper(null, UnknownStringType.Genre).equals(mGenre))
377 | return mGenre;
378 | else if( mGenre.length() > 1)/* Make genres case insensitive via normalisation */
379 | return Character.toUpperCase(mGenre.charAt(0)) + mGenre.substring(1).toLowerCase(Locale.getDefault());
380 | else
381 | return mGenre;
382 | }
383 |
384 | public String getCopyright() {
385 | return mCopyright;
386 | }
387 |
388 | public String getAlbum() {
389 | return mAlbum;
390 | }
391 |
392 | public String getTrackNumber() {
393 | return mTrackNumber;
394 | }
395 |
396 | public String getDescription() {
397 | return mDescription;
398 | }
399 |
400 | public String getRating() {
401 | return mRating;
402 | }
403 |
404 | public String getDate() {
405 | return mDate;
406 | }
407 |
408 | public String getSettings() {
409 | return mSettings;
410 | }
411 |
412 | public String getNowPlaying() {
413 | return mNowPlaying;
414 | }
415 |
416 | public String getPublisher() {
417 | return mPublisher;
418 | }
419 |
420 | public String getEncodedBy() {
421 | return mEncodedBy;
422 | }
423 |
424 | public String getTrackID() {
425 | return mTrackID;
426 | }
427 |
428 | public String getArtworkURL() {
429 | return mArtworkURL;
430 | }
431 | }
432 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/MediaList.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * MediaList.java
3 | *****************************************************************************
4 | * Copyright © 2013 VLC authors and VideoLAN
5 | * Copyright © 2013 Edward Wang
6 | *
7 | * This program is free software; you can redistribute it and/or modify it
8 | * under the terms of the GNU Lesser General Public License as published by
9 | * the Free Software Foundation; either version 2.1 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public License
18 | * along with this program; if not, write to the Free Software Foundation,
19 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20 | *****************************************************************************/
21 | package org.videolan.libvlc;
22 |
23 | import java.util.ArrayList;
24 |
25 | import android.os.Bundle;
26 |
27 | /**
28 | * Java/JNI wrapper for the libvlc_media_list_t structure.
29 | */
30 | public class MediaList {
31 | private static final String TAG = "VLC/LibVLC/MediaList";
32 |
33 | /* Since the libvlc_media_t is not created until the media plays, we have
34 | * to cache them here. */
35 | private class MediaHolder {
36 | Media m;
37 | boolean noVideo; // default false
38 | boolean noHardwareAcceleration; // default false
39 |
40 | public MediaHolder(Media media) {
41 | m = media; noVideo = false; noHardwareAcceleration = false;
42 | }
43 | public MediaHolder(Media m_, boolean noVideo_, boolean noHardwareAcceleration_) {
44 | m = m_; noVideo = noVideo_; noHardwareAcceleration = noHardwareAcceleration_;
45 | }
46 | }
47 |
48 | /* TODO: add locking */
49 | private ArrayList mInternalList;
50 | private LibVLC mLibVLC; // Used to create new objects that require a libvlc instance
51 | private EventHandler mEventHandler;
52 |
53 | public MediaList(LibVLC libVLC) {
54 | mEventHandler = new EventHandler(); // used in init() below to fire events at the correct targets
55 | mInternalList = new ArrayList();
56 | mLibVLC = libVLC;
57 | }
58 |
59 | /**
60 | * Adds a media URI to the media list.
61 | *
62 | * @param mrl
63 | * The MRL to add. Must be a location and not a path.
64 | * {@link LibVLC#PathToURI(String)} can be used to convert a path
65 | * to a MRL.
66 | */
67 | public void add(String mrl) {
68 | add(new Media(mLibVLC, mrl));
69 | }
70 | public void add(Media media) {
71 | add(media, false, false);
72 | }
73 | public void add(Media media, boolean noVideo) {
74 | add(media, noVideo, false);
75 | }
76 | public void add(Media media, boolean noVideo, boolean noHardwareAcceleration) {
77 | mInternalList.add(new MediaHolder(media, noVideo, noHardwareAcceleration));
78 | signal_list_event(EventHandler.CustomMediaListItemAdded, mInternalList.size() - 1, media.getLocation());
79 | }
80 |
81 | /**
82 | * Clear the media list. (remove all media)
83 | */
84 | public void clear() {
85 | // Signal to observers of media being deleted.
86 | for(int i = 0; i < mInternalList.size(); i++) {
87 | signal_list_event(EventHandler.CustomMediaListItemDeleted, i, mInternalList.get(i).m.getLocation());
88 | }
89 | mInternalList.clear();
90 | }
91 |
92 | private boolean isValid(int position) {
93 | return position >= 0 && position < mInternalList.size();
94 | }
95 |
96 | /**
97 | * This function checks the currently playing media for subitems at the given
98 | * position, and if any exist, it will expand them at the same position
99 | * and replace the current media.
100 | *
101 | * @param position The position to expand
102 | * @return -1 if no subitems were found, 0 if subitems were expanded
103 | */
104 | public int expandMedia(int position) {
105 | ArrayList children = new ArrayList();
106 | int ret = expandMedia(mLibVLC, position, children);
107 | if(ret == 0) {
108 | mEventHandler.callback(EventHandler.CustomMediaListExpanding, new Bundle());
109 | this.remove(position);
110 | for(String mrl : children) {
111 | this.insert(position, mrl);
112 | }
113 | mEventHandler.callback(EventHandler.CustomMediaListExpandingEnd, new Bundle());
114 | }
115 | return ret;
116 | }
117 | private native int expandMedia(LibVLC libvlc_instance, int position, ArrayList children);
118 |
119 | public void loadPlaylist(String mrl) {
120 | ArrayList items = new ArrayList();
121 | loadPlaylist(mLibVLC, mrl, items);
122 | this.clear();
123 | for(String item : items) {
124 | this.add(item);
125 | }
126 | }
127 | private native void loadPlaylist(LibVLC libvlc_instance, String mrl, ArrayList items);
128 |
129 | public void insert(int position, String mrl) {
130 | insert(position, new Media(mLibVLC, mrl));
131 | }
132 | public void insert(int position, Media media) {
133 | mInternalList.add(position, new MediaHolder(media));
134 | signal_list_event(EventHandler.CustomMediaListItemAdded, position, media.getLocation());
135 | }
136 |
137 | /**
138 | * Move a media from one position to another
139 | *
140 | * @param startPosition start position
141 | * @param endPosition end position
142 | * @throws IndexOutOfBoundsException
143 | */
144 | public void move(int startPosition, int endPosition) {
145 | if (!(isValid(startPosition)
146 | && endPosition >= 0 && endPosition <= mInternalList.size()))
147 | throw new IndexOutOfBoundsException("Indexes out of range");
148 |
149 | MediaHolder toMove = mInternalList.get(startPosition);
150 | mInternalList.remove(startPosition);
151 | if (startPosition >= endPosition)
152 | mInternalList.add(endPosition, toMove);
153 | else
154 | mInternalList.add(endPosition - 1, toMove);
155 | Bundle b = new Bundle();
156 | b.putInt("index_before", startPosition);
157 | b.putInt("index_after", endPosition);
158 | mEventHandler.callback(EventHandler.CustomMediaListItemMoved, b);
159 | }
160 |
161 | public void remove(int position) {
162 | if (!isValid(position))
163 | return;
164 | String uri = mInternalList.get(position).m.getLocation();
165 | mInternalList.remove(position);
166 | signal_list_event(EventHandler.CustomMediaListItemDeleted, position, uri);
167 | }
168 |
169 | public void remove(String location) {
170 | for (int i = 0; i < mInternalList.size(); ++i) {
171 | String uri = mInternalList.get(i).m.getLocation();
172 | if (uri.equals(location)) {
173 | mInternalList.remove(i);
174 | signal_list_event(EventHandler.CustomMediaListItemDeleted, i, uri);
175 | i--;
176 | }
177 | }
178 | }
179 |
180 | public int size() {
181 | return mInternalList.size();
182 | }
183 |
184 | public Media getMedia(int position) {
185 | if (!isValid(position))
186 | return null;
187 | return mInternalList.get(position).m;
188 | }
189 |
190 | /**
191 | * @param position The index of the media in the list
192 | * @return null if not found
193 | */
194 | public String getMRL(int position) {
195 | if (!isValid(position))
196 | return null;
197 | return mInternalList.get(position).m.getLocation();
198 | }
199 |
200 | public String[] getMediaOptions(int position) {
201 | boolean noHardwareAcceleration = mLibVLC.getHardwareAcceleration() == 0;
202 | boolean noVideo = false;
203 | if (isValid(position))
204 | {
205 | if (!noHardwareAcceleration)
206 | noHardwareAcceleration = mInternalList.get(position).noHardwareAcceleration;
207 | noVideo = mInternalList.get(position).noVideo;
208 | }
209 | ArrayList options = new ArrayList();
210 |
211 | if (!noHardwareAcceleration) {
212 | /*
213 | * Set higher caching values if using iomx decoding, since some omx
214 | * decoders have a very high latency, and if the preroll data isn't
215 | * enough to make the decoder output a frame, the playback timing gets
216 | * started too soon, and every decoded frame appears to be too late.
217 | * On Nexus One, the decoder latency seems to be 25 input packets
218 | * for 320x170 H.264, a few packets less on higher resolutions.
219 | * On Nexus S, the decoder latency seems to be about 7 packets.
220 | */
221 | options.add(":file-caching=1500");
222 | options.add(":network-caching=1500");
223 | options.add(":codec=mediacodec,iomx,all");
224 | }
225 | if (noVideo)
226 | options.add(":no-video");
227 |
228 | return options.toArray(new String[options.size()]);
229 | }
230 |
231 | public EventHandler getEventHandler() {
232 | return mEventHandler;
233 | }
234 |
235 | @Override
236 | public String toString() {
237 | StringBuilder sb = new StringBuilder();
238 | sb.append("LibVLC Media List: {");
239 | for(int i = 0; i < size(); i++) {
240 | sb.append(((Integer)i).toString());
241 | sb.append(": ");
242 | sb.append(getMRL(i));
243 | sb.append(", ");
244 | }
245 | sb.append("}");
246 | return sb.toString();
247 | }
248 |
249 | private void signal_list_event(int event, int position, String uri) {
250 | Bundle b = new Bundle();
251 | b.putString("item_uri", uri);
252 | b.putInt("item_index", position);
253 | mEventHandler.callback(event, b);
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/app/src/main/java/org/videolan/libvlc/TrackInfo.java:
--------------------------------------------------------------------------------
1 | /*****************************************************************************
2 | * TrackInfo.java
3 | *****************************************************************************
4 | * Copyright © 2010-2013 VLC authors and VideoLAN
5 | *
6 | * This program is free software; you can redistribute it and/or modify it
7 | * under the terms of the GNU Lesser General Public License as published by
8 | * the Free Software Foundation; either version 2.1 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Lesser General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Lesser General Public License
17 | * along with this program; if not, write to the Free Software Foundation,
18 | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 | *****************************************************************************/
20 |
21 | package org.videolan.libvlc;
22 |
23 | public class TrackInfo {
24 |
25 | public static final int TYPE_UNKNOWN = -1;
26 | public static final int TYPE_AUDIO = 0;
27 | public static final int TYPE_VIDEO = 1;
28 | public static final int TYPE_TEXT = 2;
29 | public static final int TYPE_META = 3;
30 |
31 | public int Type;
32 | public int Id;
33 | public String Codec;
34 | public String Language;
35 |
36 | /* Video */
37 | public int Height;
38 | public int Width;
39 | public float Framerate;
40 |
41 | /* Audio */
42 | public int Channels;
43 | public int Samplerate;
44 |
45 | /* MetaData */
46 | public long Length;
47 | public String Title;
48 | public String Artist;
49 | public String Album;
50 | public String Genre;
51 | public String ArtworkURL;
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libiomx-gingerbread.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/jniLibs/armeabi-v7a/libiomx-gingerbread.so
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libiomx-hc.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/jniLibs/armeabi-v7a/libiomx-hc.so
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libiomx-ics.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/jniLibs/armeabi-v7a/libiomx-ics.so
--------------------------------------------------------------------------------
/app/src/main/jniLibs/armeabi-v7a/libvlcjni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/jniLibs/armeabi-v7a/libvlcjni.so
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_pause_over_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-hdpi/ic_action_pause_over_video.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_action_play_over_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-hdpi/ic_action_play_over_video.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wass08/VLC-Simple-Player-Android/e677e6644837e3785b0ec4d58adf0165bcd3b8c7/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_fullscreen_vlc_player.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
11 |
12 |
18 |
19 |
25 |
31 |
32 |
38 |
39 |
44 |
45 |
50 |
51 |
55 |
56 |
63 |
64 |
65 |
66 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_media_selector.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
14 |
15 |
22 |
23 |
33 |
34 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_media_selector.xml:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #66000000
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | VLC Simple Player
5 | Settings
6 | Stream this movie
7 | Here enter the URL of a movie file :
8 | http://distribution.bbb3d.renderfarming.net/video/mp4/bbb_sunflower_1080p_30fps_normal.mp4
9 | FullscreenVlcPlayer
10 | Dummy Button
11 | DUMMY\nCONTENT
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:0.13.2'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip
7 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------