Permalink
Browse files

Image Sharing to Windows Media Player

  • Loading branch information...
1 parent 72505fb commit 6ab8a9b6fcd435c1c7ae7c9a511958ea600498ec @longkerdandy committed Jun 15, 2011
Showing with 539 additions and 19 deletions.
  1. +7 −0 medialibrary.api/src/main/java/org/chii2/medialibrary/api/core/MediaLibraryService.java
  2. +7 −0 medialibrary.api/src/main/java/org/chii2/medialibrary/api/persistence/PersistenceService.java
  3. +5 −0 medialibrary.core/src/main/java/org/chii2/medialibrary/MediaLibraryServiceImpl.java
  4. +6 −1 ...alibrary.persistence/src/main/java/org/chii2/medialibrary/persistence/PersistenceServiceImpl.java
  5. +4 −0 mediaserver.api/pom.xml
  6. +29 −2 mediaserver.api/src/main/java/org/chii2/mediaserver/api/content/ContentManager.java
  7. +62 −0 mediaserver.api/src/main/java/org/chii2/mediaserver/api/upnp/SearchCriterion.java
  8. +151 −1 mediaserver.core/src/main/java/org/chii2/mediaserver/content/common/CommonContentManager.java
  9. +44 −0 mediaserver.core/src/main/java/org/chii2/mediaserver/content/wmp/WMPContentManager.java
  10. +1 −1 mediaserver.core/src/main/java/org/chii2/mediaserver/content/xbox/XBoxContentManager.java
  11. +46 −4 mediaserver.core/src/main/java/org/chii2/mediaserver/upnp/ContentDirectory.java
  12. +119 −2 mediaserver.core/src/main/java/org/chii2/mediaserver/upnp/MediaReceiverRegistrar.java
  13. +10 −8 mediaserver.core/src/main/java/org/chii2/mediaserver/upnp/MediaServerServiceImpl.java
  14. +16 −0 mediaserver.core/src/test/java/org/chii2/mediaserver/content/DeviceDetailsTest.java
  15. +16 −0 mediaserver.core/src/test/java/org/chii2/mediaserver/content/SearchCriterionTest.java
  16. +2 −0 transcoder.api/src/main/java/org/chii2/transcoder/api/core/TranscoderService.java
  17. +14 −0 transcoder.core/src/main/java/org/chii2/transcoder/core/TranscoderServiceImpl.java
@@ -162,6 +162,13 @@
public List<String> getImageAlbums(int firstResult, int maxResults, Map<String, String> sorts);
/**
+ * Get the count of total images
+ *
+ * @return Count
+ */
+ public long getImagesCount();
+
+ /**
* Get the count of total image albums
*
* @return Count
@@ -144,6 +144,13 @@
public List<String> getImageAlbums(int firstResult, int maxResults, Map<String, String> sorts);
/**
+ * Get the count of total images
+ *
+ * @return Count
+ */
+ public long getImagesCount();
+
+ /**
* Get the count of total image albums
*
* @return Count
@@ -141,6 +141,11 @@ public Image getImageById(String id) {
}
@Override
+ public long getImagesCount() {
+ return persistenceService.getImagesCount();
+ }
+
+ @Override
public long getImageAlbumsCount() {
return persistenceService.getImageAlbumsCount();
}
@@ -359,11 +359,16 @@ public Image getImageById(String id) {
}
@Override
- public long getImageAlbumsCount() {
+ public long getImagesCount() {
return entityManager.createQuery("SELECT COUNT(i) FROM IMAGE i", Long.class).getSingleResult();
}
@Override
+ public long getImageAlbumsCount() {
+ return entityManager.createQuery("SELECT COUNT(DISTINCT i.album) FROM IMAGE i", Long.class).getSingleResult();
+ }
+
+ @Override
public long getImagesCountByAlbum(String album) {
return entityManager.createQuery("SELECT COUNT(i) FROM IMAGE i WHERE i.album = ?1", Long.class).setParameter(1, album).getSingleResult();
}
View
@@ -21,6 +21,10 @@
<dependencies>
<dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.teleal.cling</groupId>
<artifactId>cling-core</artifactId>
</dependency>
@@ -3,6 +3,7 @@
import org.chii2.mediaserver.api.content.container.VisualContainer;
import org.chii2.mediaserver.api.content.item.VisualPictureItem;
import org.chii2.mediaserver.api.content.item.VisualVideoItem;
+import org.chii2.mediaserver.api.upnp.SearchCriterion;
import org.teleal.cling.model.message.UpnpHeaders;
import org.teleal.cling.support.contentdirectory.DIDLParser;
import org.teleal.cling.support.model.DIDLObject;
@@ -49,7 +50,7 @@
public boolean isMatch(UpnpHeaders headers);
/**
- * Find Object (Container or Item) based on ID
+ * Browse Object (Container or Item) based on ID
*
* @param objectId Object ID
* @param filter Filter
@@ -58,7 +59,33 @@
* @param orderBy Sort Method
* @return Object (Container or Item), null if not found
*/
- public DIDLObject findObject(String objectId, String filter, long startIndex, long requestCount, SortCriterion[] orderBy);
+ public DIDLObject browseObject(String objectId, String filter, long startIndex, long requestCount, SortCriterion[] orderBy);
+
+ /**
+ * Search Object
+ *
+ * @param containerId Container ID
+ * @param searchCriteria Search Criterion
+ * @param filter Filter
+ * @param startIndex Start Index
+ * @param requestCount Request (Max) Count
+ * @param orderBy Sort Method
+ * @return Objects
+ */
+ public List<? extends DIDLObject> searchObject(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long requestCount, SortCriterion[] orderBy);
+
+ /**
+ * Search Total Count
+ *
+ * @param containerId Container ID
+ * @param searchCriteria Search Criterion
+ * @param filter Filter
+ * @param startIndex Start Index
+ * @param requestCount Request (Max) Count
+ * @param orderBy Sort Method
+ * @return Total Count
+ */
+ public long searchCount(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long requestCount, SortCriterion[] orderBy);
/**
* Get all Pictures Storage Folder Containers in library
@@ -0,0 +1,62 @@
+package org.chii2.mediaserver.api.upnp;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Search Criterion
+ */
+public class SearchCriterion {
+ // Search Type
+ private SearchType searchType;
+
+ public SearchType getSearchType() {
+ return searchType;
+ }
+
+ public void setSearchType(SearchType searchType) {
+ this.searchType = searchType;
+ }
+
+ /**
+ * Parse Search Criterion from String
+ * TODO: Not Completed
+ *
+ * @param searchCriterionString Search Criterion String
+ * @return Search Criterion
+ */
+ public static SearchCriterion parseSearchCriterion(String searchCriterionString) {
+ SearchCriterion searchCriterion = new SearchCriterion();
+ if (searchCriterionString != null) {
+ String[] factors = searchCriterionString.split("(and|or)");
+ for (String factor : factors) {
+ factor = StringUtils.trimToEmpty(factor);
+ String[] subFactors = factor.split("\\s", 3);
+ if (subFactors != null && subFactors.length == 3) {
+ if ("upnp:class".equalsIgnoreCase(subFactors[0]) && ("=".equalsIgnoreCase(subFactors[1]) || "derivedfrom".equalsIgnoreCase(subFactors[1]))) {
+ if ("\"object.item.imageItem\"".equalsIgnoreCase(subFactors[2]) || "\"object.item.imageItem.photo\"".equalsIgnoreCase(subFactors[2])) {
+ searchCriterion.setSearchType(SearchCriterion.SearchType.SEARCH_IMAGE);
+ } else if ("\"object.item.videoItem\"".equalsIgnoreCase(subFactors[2])) {
+ searchCriterion.setSearchType(SearchCriterion.SearchType.SEARCH_VIDEO);
+ } else if ("\"object.container.playlistContainer\"".equalsIgnoreCase(subFactors[2])) {
+ searchCriterion.setSearchType(SearchCriterion.SearchType.SEARCH_PLAYLIST);
+ } else {
+ searchCriterion.setSearchType(SearchCriterion.SearchType.SEARCH_UNKNOWN);
+ }
+ }
+ }
+ }
+ }
+ return searchCriterion;
+ }
+
+ /**
+ * Search Type
+ * TODO: Not Completed
+ */
+ public enum SearchType {
+ SEARCH_IMAGE,
+ SEARCH_VIDEO,
+ SEARCH_PLAYLIST,
+ SEARCH_UNKNOWN
+ }
+}
@@ -9,6 +9,7 @@
import org.chii2.mediaserver.api.content.item.VisualVideoItem;
import org.chii2.mediaserver.api.http.HttpServerService;
import org.chii2.mediaserver.api.provider.OnlineVideoProviderService;
+import org.chii2.mediaserver.api.upnp.SearchCriterion;
import org.chii2.mediaserver.content.common.Item.PhotoItem;
import org.chii2.mediaserver.content.common.Item.PictureItem;
import org.chii2.mediaserver.content.common.container.*;
@@ -98,7 +99,7 @@ public boolean isMatch(UpnpHeaders headers) {
}
@Override
- public DIDLObject findObject(String objectId, String filter, long startIndex, long requestCount, SortCriterion[] orderBy) {
+ public DIDLObject browseObject(String objectId, String filter, long startIndex, long requestCount, SortCriterion[] orderBy) {
// Root Container
if (isRootContainer(objectId)) {
VisualContainer container = new RootContainer(filter);
@@ -154,6 +155,155 @@ else if (isMovieBaseStorageFolderContainer(objectId)) {
}
@Override
+ public List<? extends DIDLObject> searchObject(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long requestCount, SortCriterion[] orderBy) {
+ List<? extends DIDLObject> results = null;
+ switch (searchCriteria.getSearchType()) {
+ case SEARCH_IMAGE:
+ results = this.searchImage(containerId, searchCriteria, filter, startIndex, requestCount, orderBy);
+ break;
+ }
+ return results;
+ }
+
+ @Override
+ public long searchCount(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long requestCount, SortCriterion[] orderBy) {
+ long result = 0;
+ switch (searchCriteria.getSearchType()) {
+ case SEARCH_IMAGE:
+ result = this.searchImageCount(containerId, searchCriteria, filter, startIndex, requestCount, orderBy);
+ break;
+ }
+ return result;
+ }
+
+ // Search Image
+ private List<? extends DIDLObject> searchImage(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long maxCount, SortCriterion[] orderBy) {
+ // Forge sort
+ Map<String, String> sorts = new HashMap<String, String>();
+ for (SortCriterion sort : orderBy) {
+ String field = null;
+ if ("dc:title".equalsIgnoreCase(sort.getPropertyName())) {
+ field = "title";
+ } else if ("dc:date".equalsIgnoreCase(sort.getPropertyName())) {
+ field = "file.date_taken";
+ }
+ if (field != null) {
+ if (sort.isAscending()) {
+ sorts.put(field, "asc");
+ } else {
+ sorts.put(field, "desc");
+ }
+ }
+ }
+ // Get images from library
+ List<? extends Image> images;
+
+ int start = -1;
+ int max = -1;
+ try {
+ start = (int) startIndex;
+ max = (int) maxCount;
+ } catch (Exception ignore) {
+ }
+ images = this.mediaLibrary.getImages(start, max, sorts);
+
+ // Results
+ List<VisualPictureItem> pictures = new ArrayList<VisualPictureItem>();
+ // Create picture item and add to results
+ for (Image image : images) {
+ // Item
+ VisualPictureItem pictureItem;
+ // Parent ID
+ // TODO: We use PICTURES_STORAGE_FOLDER_PREFIX here, maybe not correct
+ String parentId = this.forgeContainerId(image.getAlbum(), PICTURES_STORAGE_FOLDER_PREFIX);
+ // ID from library
+ String libraryId = image.getId();
+ // ID
+ String id;
+ // Title
+ String title = image.getTitle();
+ // Photo?
+ if (image.isPhoto()) {
+ id = forgeItemId(libraryId, parentId, PHOTO_ITEM_PREFIX);
+ pictureItem = new PhotoItem(filter, id, parentId, title, image.getAlbum());
+ } else {
+ id = forgeItemId(libraryId, parentId, PICTURE_ITEM_PREFIX);
+ pictureItem = new PictureItem(filter, id, parentId, title, image.getAlbum());
+ }
+
+ //Picture Date
+ Date date = image.getDateTaken();
+ if (filter.contains("dc:date") && date != null) {
+ pictureItem.setDate(new SimpleDateFormat("yyyy-MM-dd").format(date));
+ }
+ String comment = image.getUserComment();
+ // Description
+ if (filter.contains("dc:description") && StringUtils.isNotBlank(comment)) {
+ pictureItem.setDescription(comment);
+ }
+ // Long Description
+ if (filter.contains("upnp:longDescription") && StringUtils.isNotBlank(comment)) {
+ pictureItem.setLongDescription(comment);
+ }
+ // Rating
+ float rating = image.getRating();
+ if (filter.contains("upnp:rating") && rating > 0) {
+ pictureItem.setRating(Float.toString(rating));
+ }
+
+ // Resource
+ if (this.transcoder.isValidImage(this.getClientProfile(), image.getType(), image.getWidth(), image.getHeight())) {
+ // Resource
+ Res originalResource = this.getResource();
+ // URL
+ URI originalUri = this.httpServer.forgeUrl("image", getClientProfile(), false, libraryId);
+ originalResource.setValue(originalUri.toString());
+ // Profile
+ DLNAProfiles originalProfile = this.transcoder.getImageTranscodedProfile(this.getClientProfile(), image.getType(), image.getWidth(), image.getHeight());
+ // MIME
+ String mime = this.transcoder.getImageTranscodedMime(this.getClientProfile(), image.getType(), image.getWidth(), image.getHeight());
+ // This should not happens
+ if (StringUtils.isBlank(mime)) {
+ mime = image.getMimeType();
+ logger.warn("Can't determine image MIME type, use {} from file information.", mime);
+ }
+ // DLNA Attribute
+ EnumMap<DLNAAttribute.Type, DLNAAttribute> dlnaAttributes = new EnumMap<DLNAAttribute.Type, DLNAAttribute>(DLNAAttribute.Type.class);
+ if (originalProfile != null && originalProfile != DLNAProfiles.NONE) {
+ dlnaAttributes.put(DLNAAttribute.Type.DLNA_ORG_PN, new DLNAProfileAttribute(originalProfile));
+ }
+ dlnaAttributes.put(DLNAAttribute.Type.DLNA_ORG_OP, new DLNAOperationsAttribute(DLNAOperations.RANGE));
+ dlnaAttributes.put(DLNAAttribute.Type.DLNA_ORG_FLAGS, new DLNAFlagsAttribute(DLNAFlags.STREAMING_TRANSFER_MODE, DLNAFlags.BACKGROUND_TRANSFERT_MODE, DLNAFlags.DLNA_V15));
+ originalResource.setProtocolInfo(new DLNAProtocolInfo(Protocol.HTTP_GET, ProtocolInfo.WILDCARD, mime, dlnaAttributes));
+ // Resolution
+ if (filter.contains("res@resolution")) {
+ originalResource.setResolution(image.getWidth(), image.getHeight());
+ }
+ // Color Depth
+ if (filter.contains("res@colorDepth")) {
+ originalResource.setColorDepth((long) image.getColorDepth());
+ }
+ // Size
+ if (filter.contains("res@size")) {
+ originalResource.setSize(image.getSize());
+ }
+ // Add Resource to item
+ pictureItem.addResource(originalResource);
+ } else {
+ // TODO: Transcoded Image Handling
+ }
+ // Add to results
+ pictures.add(pictureItem);
+ }
+ return pictures;
+ }
+
+ // Search Image Count
+ public long searchImageCount(String containerId, SearchCriterion searchCriteria, String filter, long startIndex, long requestCount, SortCriterion[] orderBy) {
+ return this.mediaLibrary.getImagesCount();
+ }
+
+ @Override
public List<PicturesStorageFolderContainer> getPicturesStorageFolders(String filter, long startIndex, long maxCount, SortCriterion[] orderBy) {
// Forge sort
Map<String, String> sorts = new HashMap<String, String>();
Oops, something went wrong.

0 comments on commit 6ab8a9b

Please sign in to comment.