Get every episode from a Season (1 Viewer)

FreakyJ

Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    @morpheus_xx
    I need your help again :( I am working on a MAS implementation for MP2 adn for http://wiki.team-mediaportal.com/1_...opers/API_Documentation/MAS#GetTVEpisodeCount
    I need to get all episodes from a season.

    If I take a look into the DB -> M_MEDIAITEM I can see a Mediaitem for the Series, each Season and each episode.
    But there are two questions:
    1) How are they linked together?
    2) The Title for the season is lokalized -> I could use String.Split(' ') and convert the number to an int and than selecting all Items where the SeriesAspect -> Season is equal to that number.

    But this feels like a really dirty hack to me. Any suggestions?

    Looking at the client Side SeriesFilterBySeasonScreenData.cs I found this:
    Code:
    // subViewSpecification contains "Series S01" pattern, here we only want to show the season number.
          string season = subViewSpecification.ViewDisplayName ?? string.Empty;
          season = season.Substring(season.LastIndexOf("S") + 1);
          return LocalizationHelper.Translate(_navbarSubViewNavigationDisplayLabel, season);

    I guess this is pretty much option 2
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    You have to create a media library query: load all episodes for given series name, than count the distinct episode numbers of the given season.

    Your quoted code is a workaround, because we don't have Series / Season aspects as own objects right now, but only depend on querying distinct items attributes. So if you go for an implementation now, you will need to change it again after MIA rework.

    If you plan to implement it, I can prepare some example code for ML query, but this takes some time.
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    Thanks for the fast reply, I think I will than go with the work around for now, the reason is that I have to report an ID for a Season/Series.
    So if somebody wants to get All episodes for a season I only have the Season ID and therefore only the title (e.g. "Staffel 01").

    I can prepare some example code for ML query
    Do you mean something like this:
    Code:
    internal static IList<MediaItem> GetMediaItemsByString(string name, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, MediaItemAspectMetadata.AttributeSpecification attributeSpecification,  uint limit)
        {
          IFilter searchFilter = new RelationalFilter(attributeSpecification, RelationalOperator.EQ, name);
          MediaItemQuery searchQuery = new MediaItemQuery(necessaryMIATypes, optionalMIATypes, searchFilter) { Limit = limit };
    
          return ServiceRegistration.Get<IMediaLibrary>().Search(searchQuery, false);
        }

    I think I can manager this than :)
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    In case anybody should ever have the same problem :)

    Code:
    HttpParam httpParam = request.Param;
          if (httpParam["id"].Value == null)
            throw new BadRequestException("GetMediaItem: no id is null");
    
          ISet<Guid> necessaryMIATypes = new HashSet<Guid>();
          necessaryMIATypes.Add(MediaAspect.ASPECT_ID);
    
          // this is the MediaItem from the Season
          MediaItem item = GetMediaItems.GetMediaItemById(httpParam["id"].Value, necessaryMIATypes);
    
          if (item == null)
            throw new BadRequestException(String.Format("GetTVEpisodeCountForSeason: No MediaItem found with id: {0}", httpParam["id"].Value));
    
          int seasonNumer;
          try
          {
            seasonNumer = Convert.ToInt32(((string)item[MediaAspect.ASPECT_ID][MediaAspect.ATTR_TITLE]).Split(' ')[1]);
          }
          catch (Exception ex)
          {
            throw new BadRequestException(String.Format("GetTVEpisodeCountForSeason: Couldn't convert Title to int: {0}", ex.Message));
          }
    
          // Get all episodes for this season
          ISet<Guid> necessaryMIATypesEpisodes = new HashSet<Guid>();
          necessaryMIATypes.Add(MediaAspect.ASPECT_ID);
          necessaryMIATypes.Add(SeriesAspect.ASPECT_ID);
    
          IList<MediaItem> episodes = GetMediaItems.GetMediaItemsByInt(seasonNumer, necessaryMIATypesEpisodes, null, SeriesAspect.ATTR_SEASON, null);
    
          WebIntResult webIntResult = new WebIntResult { Result = episodes.Count };
    
          return webIntResult;

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using MediaPortal.Backend.MediaLibrary;
    using MediaPortal.Common;
    using MediaPortal.Common.MediaManagement;
    using MediaPortal.Common.MediaManagement.DefaultItemAspects;
    using MediaPortal.Common.MediaManagement.MLQueries;
    
    namespace MediaPortal.Plugins.MP2Extended.ResourceAccess
    {
      internal class GetMediaItems
      {
        #region ById
    
        internal static MediaItem GetMediaItemById(string id, ISet<Guid> necessaryMIATypes)
        {
          return GetMediaItemById(id, necessaryMIATypes, null);
        }
       
        internal static MediaItem GetMediaItemById(string id, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes)
        {
          return GetMediaItemById(Guid.Parse(id), necessaryMIATypes, optionalMIATypes);
        }
    
        internal static MediaItem GetMediaItemById(Guid id, ISet<Guid> necessaryMIATypes)
        {
          return GetMediaItemById(id, necessaryMIATypes, null);
        }
    
        internal static MediaItem GetMediaItemById(Guid id, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes)
        {
          IList<MediaItem> items = GetMediaItemsById(id, necessaryMIATypes, optionalMIATypes, 1);
          if (items.Count != 0)
            return items[0];
          return null;
        }
    
        internal static IList<MediaItem> GetMediaItemsById(string id, ISet<Guid> necessaryMIATypes, uint limit)
        {
          return GetMediaItemsById(id, necessaryMIATypes, null, limit);
        }
    
        internal static IList<MediaItem> GetMediaItemsById(string id, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, uint limit)
        {
          return GetMediaItemsById(Guid.Parse(id), necessaryMIATypes, optionalMIATypes, limit);
        }
    
        internal static IList<MediaItem> GetMediaItemsById(Guid id, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, uint limit)
        {
          IFilter searchFilter = new MediaItemIdFilter(id);
          MediaItemQuery searchQuery = new MediaItemQuery(necessaryMIATypes, optionalMIATypes, searchFilter) { Limit = limit };
    
          return ServiceRegistration.Get<IMediaLibrary>().Search(searchQuery, false);
        }
    
        #endregion ByID
    
        #region ByName
    
        internal static MediaItem GetMediaItemByName(string name, ISet<Guid> necessaryMIATypes)
        {
          return GetMediaItemByName(name, necessaryMIATypes, null);
        }
    
    
        /// <summary>
        /// Filters by MediaAspect.ATTR_TITLE
        /// </summary>
        /// <param name="name"></param>
        /// <param name="necessaryMIATypes">Must contain MediaAspect</param>
        /// <param name="optionalMIATypes"></param>
        /// <returns></returns>
        internal static MediaItem GetMediaItemByName(string name, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes)
        {
          IList<MediaItem> items = GetMediaItemsByName(name, necessaryMIATypes, optionalMIATypes, 1);
          if (items.Count != 0)
            return items[0];
          return null;
        }
    
        internal static IList<MediaItem> GetMediaItemsByName(string name, ISet<Guid> necessaryMIATypes, uint limit)
        {
          if (necessaryMIATypes == null)
          {
            necessaryMIATypes = new HashSet<Guid> { MediaAspect.ASPECT_ID };
          }
    
          return GetMediaItemsByName(name, necessaryMIATypes, null, limit);
        }
    
        /// <summary>
        /// Filters by MediaAspect.ATTR_TITLE
        /// </summary>
        /// <param name="name"></param>
        /// <param name="necessaryMIATypes">Must contain MediaAspect</param>
        /// <param name="optionalMIATypes"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        internal static IList<MediaItem> GetMediaItemsByName(string name, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, uint? limit)
        {
          return GetMediaItemsByString(name, necessaryMIATypes, optionalMIATypes, MediaAspect.ATTR_TITLE, limit);
        }
    
        internal static IList<MediaItem> GetMediaItemsByString(string name, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, MediaItemAspectMetadata.AttributeSpecification attributeSpecification,  uint? limit)
        {
          IFilter searchFilter = new RelationalFilter(attributeSpecification, RelationalOperator.EQ, name);
          MediaItemQuery searchQuery = new MediaItemQuery(necessaryMIATypes, optionalMIATypes, searchFilter) { Limit = limit };
    
          return ServiceRegistration.Get<IMediaLibrary>().Search(searchQuery, false);
        }
    
        internal static IList<MediaItem> GetMediaItemsByInt(int number, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes, MediaItemAspectMetadata.AttributeSpecification attributeSpecification, uint? limit)
        {
          IFilter searchFilter = new RelationalFilter(attributeSpecification, RelationalOperator.EQ, number);
          MediaItemQuery searchQuery = new MediaItemQuery(necessaryMIATypes, optionalMIATypes, searchFilter) { Limit = limit };
    
          return ServiceRegistration.Get<IMediaLibrary>().Search(searchQuery, false);
        }
    
        #endregion ByName
      }
    }
     

    morpheus_xx

    Retired Team Member
  • Team MediaPortal
  • March 24, 2007
    12,073
    7,459
    Home Country
    Germany Germany
    Some remarks:
    if (httpParam["id"].Value == null)
    1) --> please introduce a variable for it, it will be accessed twice

    seasonNumer = Convert.ToInt32(((string)item[MediaAspect.ASPECT_ID][MediaAspect.ATTR_TITLE]).Split(' ')[1]);
    2) why do you parse the season from Title? There is the SeriesAspect.Season attribute you can use directly.

    3) Please reduce them number of methods, i.e.:
    internal static MediaItem GetMediaItemById(string id, ISet<Guid> necessaryMIATypes, ISet<Guid> optionalMIATypes)
    --> if you expect to query always by MediaItem Id, then the Guid version is enough. Parsing (TryParse) the Guid should then be done in step 1)
     

    FreakyJ

    Retired Team Member
  • Premium Supporter
  • July 25, 2010
    4,024
    1,420
    Home Country
    Germany Germany
    1) --> please introduce a variable for it, it will be accessed twice
    I can agree with this :)

    2) why do you parse the season from Title? There is the SeriesAspect.Season attribute you can use directly.
    If you take a look here: http://wiki.team-mediaportal.com/1_...s/MPExtended/Developers/API_Documentation/MAS
    The API has a Id's for seasons and Shows. MP2 doesn't really (yet). So if one requests all episodes for a season, I get the id for the Season item in M_MEDIAITEM.
    Now there is no link to the episodes, that's why I have to pars the name and than take the season number to get the episodes.

    And I think I just found a bug :/ Because it will return all episodes corresponding to a season number and not a special season.

    So I need to create my own ID:
    1) {seariesName:confused:eason} -> base64
    2) {GUID-Seasies:GUID-Season}

    I think I will go with option two. I meant more DB requests, but I think it will have less errors, because GUIDs don't contain ":", names could.

    if you expect to query always by MediaItem Id, then the Guid version is enough. Parsing (TryParse) the Guid should then be done in step 1)
    Actually I use both. I called it MicroModules. and every Api part (e.g. GetTVEpisodeCountForTVShow ) has it's own micro module. And a lot of these use id's. That's why I put the GUID parsing in it's own function, but sometimes I also get the GUID from MP directly. I hope that makes sense :)

    I use your method :)

    Code:
    {"GetMediaItem", new GetMediaItem()},
          { "TestConnection", new TestConnection()},
          // TvShow
          { "GetTVEpisodeBasicById", new GetTVEpisodeBasicById()},
          { "GetTVEpisodeCountForSeason", new GetTVEpisodeCountForSeason()},
          { "GetTVEpisodeCountForTVShow", new GetTVEpisodeCountForTVShow()},
          { "GetTVEpisodeDetailedById", new GetTVEpisodeDetailedById()},
          { "GetTVEpisodesBasic", new GetTVEpisodesBasic()}

    It is like a Switch: I registered a HTTP module for MPExtened this module routes the request to the submodules: MAS, SAS, ?? depending on the second part of the URL, e.g. "MediaAccessService".
    This module than sends the request depending on the last part of the url to one of the micromodules, it get's an answer (dynamic), parsis it with json and sends it to the client :)
     

    Users who are viewing this thread

    Top Bottom