protected override void Prepare()
    {
      base.Prepare();

      _defaultScreen = new AudioFilterByArtistScreenData();
      _availableScreens = new List<AbstractScreenData>
        {
          new AudioShowItemsScreenData(_genericPlayableItemCreatorDelegate),
          // C# doesn't like it to have an assignment inside a collection initializer
          _defaultScreen,
          new AudioFilterByAlbumScreenData(),
          new AudioFilterByGenreScreenData(),
          new AudioFilterByDecadeScreenData(),
          new AudioFilterBySystemScreenData(),
          new AudioSimpleSearchScreenData(_genericPlayableItemCreatorDelegate),
        };

      _defaultSorting = new AudioSortByAlbumTrack();
      _availableSortings = new List<Sorting.Sorting>
        {
          _defaultSorting,
          new SortByTitle(),
          new AudioSortByFirstGenre(),
          new AudioSortByFirstArtist(),
          new AudioSortByAlbum(),
          new AudioSortByTrack(),
          new SortByYear(),
          new SortBySystem(),
        };
    }
 public void InitMediaNavigation(out string mediaNavigationMode, out NavigationData navigationData)
 {
   IEnumerable<Guid> skinDependentOptionalMIATypeIDs = MediaNavigationModel.GetMediaSkinOptionalMIATypes(MediaNavigationMode);
   AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new AudioItem(mi)
   {
     Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
   };
   ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_AUDIO_VIEW_NAME,
     null, Consts.NECESSARY_AUDIO_MIAS, skinDependentOptionalMIATypeIDs, true)
   {
     MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
   };
   AbstractScreenData filterByAlbum = new AudioFilterByAlbumScreenData();
   ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
     {
       new AudioShowItemsScreenData(picd),
       new AudioFilterByArtistScreenData(),
       filterByAlbum,
       // C# doesn't like it to have an assignment inside a collection initializer
       new AudioFilterByGenreScreenData(),
       new AudioFilterByDecadeScreenData(),
       new AudioFilterBySystemScreenData(),
       new AudioSimpleSearchScreenData(picd),
     };
   Sorting.Sorting sortByAlbumTrack = new AudioSortByAlbumTrack();
   ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
     {
       sortByAlbumTrack,
       new SortByTitle(),
       new AudioSortByFirstGenre(),
       new AudioSortByFirstArtist(),
       new AudioSortByAlbum(),
       new AudioSortByTrack(),
       new SortByYear(),
       new SortBySystem(),
     };
   navigationData = new NavigationData(null, Consts.RES_AUDIO_VIEW_NAME, MediaNavigationRootState,
     MediaNavigationRootState, rootViewSpecification, filterByAlbum, availableScreens, sortByAlbumTrack)
   {
     AvailableSortings = availableSortings
   };
   mediaNavigationMode = MediaNavigationMode;
 }
    /// <summary>
    /// Returns context variables to be set for the given workflow state id.
    /// </summary>
    /// <param name="workflowStateId">Workflow state which determines the root media navigation state.</param>
    /// <returns>Mapping of context variable keys to values.</returns>
    protected static IDictionary<string, object> PrepareRootState(Guid workflowStateId)
    {
      IDictionary<string, object> result = new Dictionary<string, object>();
      // The initial state ID determines the media model "part" to initialize: Browse local media, browse media library, audio, videos or images.
      // The media model part determines the media navigation mode and the view contents to be set.
      NavigationData navigationData;
      MediaNavigationMode mode;
      if (workflowStateId == Consts.WF_STATE_ID_AUDIO_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Audio;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new AudioItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_AUDIO_VIEW_NAME,
            null, Consts.NECESSARY_AUDIO_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByAlbum = new AudioFilterByAlbumScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new AudioShowItemsScreenData(picd),
              new AudioFilterByArtistScreenData(),
              filterByAlbum, // C# doesn't like it to have an assignment inside a collection initializer
              new AudioFilterByGenreScreenData(),
              new AudioFilterByDecadeScreenData(),
              new AudioFilterBySystemScreenData(),
              new AudioSimpleSearchScreenData(picd),
            };
        Sorting.Sorting sortByAlbumTrack = new AudioSortByAlbumTrack();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByAlbumTrack,
              new SortByTitle(),
              new AudioSortByFirstGenre(),
              new AudioSortByFirstArtist(),
              new AudioSortByAlbum(),
              new AudioSortByTrack(),
              new SortByYear(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_AUDIO_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByAlbum, availableScreens, sortByAlbumTrack)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_VIDEOS_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Videos;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new VideoItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_VIDEOS_VIEW_NAME,
            null, Consts.NECESSARY_VIDEO_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new VideosShowItemsScreenData(picd),
              new VideosFilterByLanguageScreenData(),
              new VideosFilterByActorScreenData(),
              filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByYearScreenData(),
              new VideosFilterBySystemScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByTitle = new SortByTitle();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByTitle,
              new SortByYear(),
              new VideoSortByFirstGenre(),
              new VideoSortByDuration(),
              new VideoSortByDirector(),
              new VideoSortByFirstActor(),
              new VideoSortBySize(),
              new VideoSortByAspectRatio(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_VIDEOS_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle)
          {
              AvailableSortings = availableSortings
          };
      } 
      else if (workflowStateId == Consts.WF_STATE_ID_SERIES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Videos;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new SeriesItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_SERIES_VIEW_NAME,
            null, Consts.NECESSARY_SERIES_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterBySeries = new SeriesFilterByNameScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new SeriesShowItemsScreenData(picd),
              filterBySeries, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByLanguageScreenData(),
              new SeriesFilterBySeasonScreenData(),
              new VideosFilterByGenreScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByEpisode = new SeriesSortByEpisode();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByEpisode,
              new SortByTitle(),
              new SortByDate(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_SERIES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterBySeries, availableScreens, sortByEpisode)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_MOVIES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Movies;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new MovieItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_MOVIES_VIEW_NAME,
            null, Consts.NECESSARY_MOVIES_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByGenre = new VideosFilterByGenreScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new MoviesShowItemsScreenData(picd),
              new VideosFilterByActorScreenData(),
              filterByGenre, // C# doesn't like it to have an assignment inside a collection initializer
              new VideosFilterByYearScreenData(),
              new VideosFilterBySystemScreenData(),
              new VideosSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByTitle = new SortByTitle();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              sortByTitle,
              new SortByYear(),
              new VideoSortByFirstGenre(),
              new VideoSortByDuration(),
              new VideoSortByDirector(),
              new VideoSortByFirstActor(),
              new VideoSortBySize(),
              new VideoSortByAspectRatio(),
              new SortBySystem(),
          };

        navigationData = new NavigationData(null, Consts.RES_MOVIES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByGenre, availableScreens, sortByTitle)
          {
              AvailableSortings = availableSortings
          };
      }
      else if (workflowStateId == Consts.WF_STATE_ID_IMAGES_NAVIGATION_ROOT)
      {
        mode = MediaNavigationMode.Images;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi => new ImageItem(mi)
          {
              Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
          };
        ViewSpecification rootViewSpecification = new MediaLibraryQueryViewSpecification(Consts.RES_IMAGES_VIEW_NAME,
            null, Consts.NECESSARY_IMAGE_MIAS, skinDependentOptionalMIATypeIDs, true)
          {
              MaxNumItems = Consts.MAX_NUM_ITEMS_VISIBLE
          };
        AbstractScreenData filterByYear = new ImagesFilterByYearScreenData();
        ICollection<AbstractScreenData> availableScreens = new List<AbstractScreenData>
            {
              new ImagesShowItemsScreenData(picd),
              filterByYear, // C# doesn't like it to have an assignment inside a collection initializer
              new ImagesFilterBySizeScreenData(),
              new ImagesFilterBySystemScreenData(),
              new ImagesSimpleSearchScreenData(picd),
          };
        Sorting.Sorting sortByYear = new SortByYear();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              new SortByYear(),
              new SortByTitle(),
              new ImageSortBySize(),
              new SortBySystem(),
          };
        navigationData = new NavigationData(null, Consts.RES_IMAGES_VIEW_NAME, workflowStateId,
            workflowStateId, rootViewSpecification, filterByYear, availableScreens, sortByYear)
          {
              AvailableSortings = availableSortings
          };
      }
      else
      {
        // If we were called with a supported root state, we should be either in state WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT
        // or WF_STATE_ID_MEDIA_BROWSE_NAVIGATION_ROOT here
        if (workflowStateId != Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT &&
            workflowStateId != Consts.WF_STATE_ID_BROWSE_MEDIA_NAVIGATION_ROOT)
        {
          // Error case: We cannot handle the given state
          ServiceRegistration.Get<ILogger>().Warn("MediaNavigationModel: Unknown root workflow state with ID '{0}', initializing local media navigation", workflowStateId);
          // We simply use the local media mode as fallback for this case, so we go on
          workflowStateId = Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT;
        }
        mode = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ? MediaNavigationMode.BrowseLocalMedia :
            MediaNavigationMode.BrowseMediaLibrary;
        IEnumerable<Guid> skinDependentOptionalMIATypeIDs = GetMediaSkinOptionalMIATypes(mode);
        AbstractItemsScreenData.PlayableItemCreatorDelegate picd = mi =>
          {
            if (mi.Aspects.ContainsKey(AudioAspect.ASPECT_ID))
              return new AudioItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            if (mi.Aspects.ContainsKey(VideoAspect.ASPECT_ID))
              return new VideoItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            if (mi.Aspects.ContainsKey(ImageAspect.ASPECT_ID))
              return new ImageItem(mi)
                {
                    Command = new MethodDelegateCommand(() => PlayItemsModel.CheckQueryPlayAction(mi))
                };
            return null;
          };
        IEnumerable<Guid> necessaryMIATypeIDs = new Guid[]
            {
                ProviderResourceAspect.ASPECT_ID,
                MediaAspect.ASPECT_ID,
            };
        IEnumerable<Guid> optionalMIATypeIDs = new Guid[]
            {
                AudioAspect.ASPECT_ID,
                VideoAspect.ASPECT_ID,
                ImageAspect.ASPECT_ID,
            }.Union(skinDependentOptionalMIATypeIDs);
        string viewName = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            Consts.RES_LOCAL_MEDIA_ROOT_VIEW_NAME : Consts.RES_BROWSE_MEDIA_ROOT_VIEW_NAME;
        ViewSpecification rootViewSpecification = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            new AddedRemovableMediaViewSpecificationFacade(new LocalMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs)) :
            new AddedRemovableMediaViewSpecificationFacade(new BrowseMediaRootProxyViewSpecification(viewName, necessaryMIATypeIDs, optionalMIATypeIDs));
        // Dynamic screens remain null - browse media states don't provide dynamic filters
        AbstractScreenData screenData = workflowStateId == Consts.WF_STATE_ID_LOCAL_MEDIA_NAVIGATION_ROOT ?
            (AbstractScreenData) new LocalMediaNavigationScreenData(picd) : new BrowseMediaNavigationScreenData(picd);
        Sorting.Sorting browseDefaultSorting = new BrowseDefaultSorting();
        ICollection<Sorting.Sorting> availableSortings = new List<Sorting.Sorting>
          {
              browseDefaultSorting,
              new SortByTitle(),
              new SortByDate(),
              // We could offer sortings here which are specific for one media item type but which will cope with all three item types (and sort items of the three types in a defined order)
          };
        navigationData = new NavigationData(null, viewName, workflowStateId,
            workflowStateId, rootViewSpecification, screenData, null, browseDefaultSorting)
          {
              AvailableSortings = availableSortings
          };
      }
      result.Add(Consts.KEY_NAVIGATION_MODE, mode);
      result.Add(Consts.KEY_NAVIGATION_DATA, navigationData);
      return result;
    }