|
|
|
@ -20,6 +20,8 @@ |
|
|
|
|
|
|
|
package org.videolan.libvlc.util; |
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
|
|
|
import org.videolan.libvlc.LibVLC; |
|
|
|
import org.videolan.libvlc.Media; |
|
|
|
import org.videolan.libvlc.MediaDiscoverer; |
|
|
|
@ -29,9 +31,16 @@ import org.videolan.libvlc.VLCObject; |
|
|
|
public class MediaBrowser { |
|
|
|
private static final String TAG = "LibVLC/util/MediaBrowser"; |
|
|
|
|
|
|
|
private static final String[] DISCOVERER_LIST = { |
|
|
|
"dsm", // Netbios discovery via libdsm
|
|
|
|
// "bonjour",
|
|
|
|
// "mdns"
|
|
|
|
}; |
|
|
|
|
|
|
|
private LibVLC mLibVlc; |
|
|
|
private MediaDiscoverer mMediaDiscoverer; |
|
|
|
private MediaList mMediaList; |
|
|
|
private ArrayList<MediaDiscoverer> mMediaDiscoverers = new ArrayList<MediaDiscoverer>(); |
|
|
|
private ArrayList<Media> mDiscovererMediaArray = new ArrayList<Media>(); |
|
|
|
private MediaList mBrowserMediaList; |
|
|
|
private Media mMedia; |
|
|
|
private EventListener mEventListener; |
|
|
|
|
|
|
|
@ -39,11 +48,22 @@ public class MediaBrowser { |
|
|
|
* Listener called when medias are added or removed. |
|
|
|
*/ |
|
|
|
public interface EventListener { |
|
|
|
/** |
|
|
|
* Received when a new media is added. |
|
|
|
* @param index |
|
|
|
* @param media |
|
|
|
*/ |
|
|
|
public void onMediaAdded(int index, Media media); |
|
|
|
public void onMediaRemoved(int index); |
|
|
|
/** |
|
|
|
* Received when a media is removed (Happens only when you discover networks) |
|
|
|
* @param index |
|
|
|
* @param media Released media, but cached attributes are still |
|
|
|
* available (like media.getMrl()) |
|
|
|
*/ |
|
|
|
public void onMediaRemoved(int index, Media media); |
|
|
|
/** |
|
|
|
* Called when browse ended. |
|
|
|
* It won't be called when you browse a service discovery. |
|
|
|
* It won't be called when you discover networks |
|
|
|
*/ |
|
|
|
public void onBrowseEnd(); |
|
|
|
} |
|
|
|
@ -54,17 +74,17 @@ public class MediaBrowser { |
|
|
|
} |
|
|
|
|
|
|
|
private synchronized void reset() { |
|
|
|
if (mMediaDiscoverer != null) { |
|
|
|
mMediaDiscoverer.release(); |
|
|
|
mMediaDiscoverer = null; |
|
|
|
} |
|
|
|
for (MediaDiscoverer md : mMediaDiscoverers) |
|
|
|
md.release(); |
|
|
|
mMediaDiscoverers.clear(); |
|
|
|
mDiscovererMediaArray.clear(); |
|
|
|
if (mMedia != null) { |
|
|
|
mMedia.release(); |
|
|
|
mMedia = null; |
|
|
|
} |
|
|
|
/* don't need to release the MediaList since it's either |
|
|
|
* associated with a Media or a MediaDiscoverer that will release it */ |
|
|
|
mMediaList = null; |
|
|
|
mBrowserMediaList = null; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -74,26 +94,41 @@ public class MediaBrowser { |
|
|
|
reset(); |
|
|
|
} |
|
|
|
|
|
|
|
private void startMediaDiscoverer(String discovererName) { |
|
|
|
MediaDiscoverer md = new MediaDiscoverer(mLibVlc, discovererName); |
|
|
|
mMediaDiscoverers.add(md); |
|
|
|
final MediaList ml = md.getMediaList(); |
|
|
|
ml.setEventListener(mDiscovererMediaListEventListener); |
|
|
|
md.start(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Discover networks shares using available MediaDiscoverers |
|
|
|
*/ |
|
|
|
public synchronized void discoverNetworkShares() { |
|
|
|
reset(); |
|
|
|
for (String discovererName : DISCOVERER_LIST) |
|
|
|
startMediaDiscoverer(discovererName); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Discover networks shares using specified MediaDiscoverer |
|
|
|
* @param discovererName |
|
|
|
*/ |
|
|
|
public synchronized void discoverNetworkShares(String discovererName) { |
|
|
|
reset(); |
|
|
|
startMediaDiscoverer(discovererName); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Browse to the specified mrl. |
|
|
|
* |
|
|
|
* @param mrl |
|
|
|
*/ |
|
|
|
public synchronized void browse(String mrl) { |
|
|
|
if (!mrl.contains("://") && !mrl.startsWith("/")) { |
|
|
|
reset(); |
|
|
|
if (mrl.equals("smb")) |
|
|
|
mMediaDiscoverer = new MediaDiscoverer(mLibVlc, "dsm"); |
|
|
|
else |
|
|
|
mMediaDiscoverer = new MediaDiscoverer(mLibVlc, mrl); |
|
|
|
mMediaList = mMediaDiscoverer.getMediaList(); |
|
|
|
mMediaList.setEventListener(mMediaListEventListener); |
|
|
|
mMediaDiscoverer.start(); |
|
|
|
} else { |
|
|
|
final Media media = new Media(mLibVlc, mrl); |
|
|
|
browse(media); |
|
|
|
media.release(); |
|
|
|
} |
|
|
|
final Media media = new Media(mLibVlc, mrl); |
|
|
|
browse(media); |
|
|
|
media.release(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
@ -107,8 +142,8 @@ public class MediaBrowser { |
|
|
|
*/ |
|
|
|
media.retain(); |
|
|
|
reset(); |
|
|
|
mMediaList = media.subItems(); |
|
|
|
mMediaList.setEventListener(mMediaListEventListener); |
|
|
|
mBrowserMediaList = media.subItems(); |
|
|
|
mBrowserMediaList.setEventListener(mBrowserMediaListEventListener); |
|
|
|
media.parseAsync(Media.Parse.ParseNetwork); |
|
|
|
mMedia = media; |
|
|
|
} |
|
|
|
@ -117,29 +152,79 @@ public class MediaBrowser { |
|
|
|
* Get the number or media. |
|
|
|
*/ |
|
|
|
public synchronized int getMediaCount() { |
|
|
|
return mMediaList != null ? mMediaList.getCount() : 0; |
|
|
|
return mBrowserMediaList != null ? mBrowserMediaList.getCount() : mDiscovererMediaArray.size(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Get a media at a specified index. |
|
|
|
*/ |
|
|
|
public synchronized Media getMediaAt(int index) { |
|
|
|
return mMediaList != null ? mMediaList.getMediaAt(index) : null; |
|
|
|
return index >= 0 && index < getMediaCount() ? |
|
|
|
mBrowserMediaList != null ? mBrowserMediaList.getMediaAt(index) : |
|
|
|
mDiscovererMediaArray.get(index) : null; |
|
|
|
} |
|
|
|
|
|
|
|
private MediaList.EventListener mMediaListEventListener = new MediaList.EventListener() { |
|
|
|
private MediaList.EventListener mBrowserMediaListEventListener = new MediaList.EventListener() { |
|
|
|
@Override |
|
|
|
public void onEvent(VLCObject.Event event) { |
|
|
|
if (mEventListener == null) |
|
|
|
return; |
|
|
|
final MediaList.Event mlEvent = (MediaList.Event) event; |
|
|
|
|
|
|
|
/* |
|
|
|
* We use an intermediate array here since more than one MediaDiscoverer can be used |
|
|
|
*/ |
|
|
|
switch (mlEvent.type) { |
|
|
|
case MediaList.Events.MediaListItemAdded: |
|
|
|
mEventListener.onMediaAdded(mlEvent.index, mlEvent.media); |
|
|
|
break; |
|
|
|
case MediaList.Events.MediaListItemDeleted: |
|
|
|
mEventListener.onMediaRemoved(mlEvent.index); |
|
|
|
mEventListener.onMediaRemoved(mlEvent.index, mlEvent.media); |
|
|
|
break; |
|
|
|
case MediaList.Events.MediaListEndReached: |
|
|
|
mEventListener.onBrowseEnd(); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
private MediaList.EventListener mDiscovererMediaListEventListener = new MediaList.EventListener() { |
|
|
|
@Override |
|
|
|
public void onEvent(VLCObject.Event event) { |
|
|
|
if (mEventListener == null) |
|
|
|
return; |
|
|
|
final MediaList.Event mlEvent = (MediaList.Event) event; |
|
|
|
int index = -1; |
|
|
|
|
|
|
|
/* |
|
|
|
* We use an intermediate array here since more than one MediaDiscoverer can be used |
|
|
|
*/ |
|
|
|
switch (mlEvent.type) { |
|
|
|
case MediaList.Events.MediaListItemAdded: |
|
|
|
synchronized (MediaBrowser.this) { |
|
|
|
/* one item can be found by severals discoverers */ |
|
|
|
boolean found = false; |
|
|
|
for (Media media : mDiscovererMediaArray) { |
|
|
|
if (media.getMrl().equals(mlEvent.media.getMrl())) { |
|
|
|
found = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
if (!found) { |
|
|
|
mDiscovererMediaArray.add(mlEvent.media); |
|
|
|
index = mDiscovererMediaArray.size() - 1; |
|
|
|
} |
|
|
|
} |
|
|
|
if (index != -1) |
|
|
|
mEventListener.onMediaAdded(index, mlEvent.media); |
|
|
|
break; |
|
|
|
case MediaList.Events.MediaListItemDeleted: |
|
|
|
synchronized (MediaBrowser.this) { |
|
|
|
index = mDiscovererMediaArray.indexOf(mlEvent.media); |
|
|
|
if (index != -1) |
|
|
|
mDiscovererMediaArray.remove(index); |
|
|
|
} |
|
|
|
if (index != -1) |
|
|
|
mEventListener.onMediaRemoved(index, mlEvent.media); |
|
|
|
break; |
|
|
|
case MediaList.Events.MediaListEndReached: |
|
|
|
mEventListener.onBrowseEnd(); |
|
|
|
|