Add remote control chapter menu

This commit is contained in:
Luke Pulverenti 2014-05-12 14:04:25 -04:00
parent b9b568de13
commit 6314428830
18 changed files with 126 additions and 111 deletions

View File

@ -1,6 +1,5 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;

View File

@ -444,18 +444,11 @@ namespace MediaBrowser.Api.Playback
var pts = string.Empty;
if (state.SubtitleStream != null)
if (state.SubtitleStream != null && !state.SubtitleStream.IsGraphicalSubtitleStream)
{
if (state.SubtitleStream.Codec.IndexOf("srt", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("subrip", StringComparison.OrdinalIgnoreCase) != -1 ||
string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
{
var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
var seconds = TimeSpan.FromTicks(state.Request.StartTimeTicks ?? 0).TotalSeconds;
pts = string.Format(",asetpts=PTS-{0}/TB",
Math.Round(seconds).ToString(UsCulture));
}
pts = string.Format(",asetpts=PTS-{0}/TB", Math.Round(seconds).ToString(UsCulture));
}
return string.Format("-af \"{0}aresample={1}async={4}{2}{3}\"",
@ -484,16 +477,10 @@ namespace MediaBrowser.Api.Playback
var request = state.VideoRequest;
if (state.SubtitleStream != null)
if (state.SubtitleStream != null && !state.SubtitleStream.IsGraphicalSubtitleStream)
{
if (state.SubtitleStream.Codec.IndexOf("srt", StringComparison.OrdinalIgnoreCase) != -1 ||
state.SubtitleStream.Codec.IndexOf("subrip", StringComparison.OrdinalIgnoreCase) != -1 ||
string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) ||
string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase))
{
assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion);
copyTsParam = " -copyts";
}
assSubtitleParam = GetTextSubtitleParam(state, performTextSubtitleConversion);
copyTsParam = " -copyts";
}
// If fixed dimensions were supplied
@ -713,12 +700,11 @@ namespace MediaBrowser.Api.Playback
/// <summary>
/// Gets the probe size argument.
/// </summary>
/// <param name="mediaPath">The media path.</param>
/// <param name="isVideo">if set to <c>true</c> [is video].</param>
/// <param name="videoType">Type of the video.</param>
/// <param name="isoType">Type of the iso.</param>
/// <returns>System.String.</returns>
private string GetProbeSizeArgument(string mediaPath, bool isVideo, VideoType? videoType, IsoType? isoType)
private string GetProbeSizeArgument(bool isVideo, VideoType? videoType, IsoType? isoType)
{
var type = !isVideo ? MediaEncoderHelpers.GetInputType(null, null) :
MediaEncoderHelpers.GetInputType(videoType, isoType);
@ -1831,7 +1817,7 @@ namespace MediaBrowser.Api.Playback
{
var inputModifier = string.Empty;
var probeSize = GetProbeSizeArgument(state.MediaPath, state.IsInputVideo, state.VideoType, state.IsoType);
var probeSize = GetProbeSizeArgument(state.IsInputVideo, state.VideoType, state.IsoType);
inputModifier += " " + probeSize;
inputModifier = inputModifier.Trim();

View File

@ -4,7 +4,5 @@ namespace MediaBrowser.Common.Constants
public static class Constants
{
public const string MbAdminUrl = "http://www.mb3admin.com/admin/";
public const string MbServerPkgName = "MBServer";
public const string MbTheaterPkgName = "MBTheater";
}
}

View File

@ -24,6 +24,12 @@ namespace MediaBrowser.Model.Configuration
/// <value>The audio language preference.</value>
public string AudioLanguagePreference { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [play default audio track].
/// </summary>
/// <value><c>true</c> if [play default audio track]; otherwise, <c>false</c>.</value>
public bool PlayDefaultAudioTrack { get; set; }
/// <summary>
/// Gets or sets the subtitle language preference.
/// </summary>
@ -61,6 +67,8 @@ namespace MediaBrowser.Model.Configuration
public UnratedItem[] BlockUnratedItems { get; set; }
public SubtitlePlaybackMode SubtitleMode { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
/// </summary>
@ -68,6 +76,7 @@ namespace MediaBrowser.Model.Configuration
{
IsAdministrator = true;
PlayDefaultAudioTrack = true;
EnableRemoteControlOfOtherUsers = true;
EnableLiveTvManagement = true;
EnableMediaPlayback = true;
@ -79,4 +88,12 @@ namespace MediaBrowser.Model.Configuration
BlockUnratedItems = new UnratedItem[] { };
}
}
public enum SubtitlePlaybackMode
{
Default = 0,
Always = 1,
OnlyForced = 2,
None = 3
}
}

View File

@ -1,8 +1,8 @@
using System;
using System.Runtime.Serialization;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace MediaBrowser.Model.Dto
{
@ -41,11 +41,27 @@ namespace MediaBrowser.Model.Dto
MediaStreams = new List<MediaStream>();
}
public int? DefaultAudioStreamIndex { get; set; }
public int? DefaultSubtitleStreamIndex { get; set; }
[IgnoreDataMember]
public MediaStream DefaultAudioStream
{
get
{
if (DefaultAudioStreamIndex.HasValue)
{
var val = DefaultAudioStreamIndex.Value;
foreach (MediaStream i in MediaStreams)
{
if (i.Type == MediaStreamType.Audio && i.Index == val)
{
return i;
}
}
}
foreach (MediaStream i in MediaStreams)
{
if (i.Type == MediaStreamType.Audio && i.IsDefault)

View File

@ -2,7 +2,8 @@
{
public class AudioCodec
{
public const string AAC = "AAC";
public const string MP3 = "MP3";
public const string AAC = "aac";
public const string MP3 = "mp3";
public const string AC3 = "ac3";
}
}

View File

@ -3,6 +3,7 @@ namespace MediaBrowser.Model.MediaInfo
{
public class Container
{
public const string MP4 = "MP4";
public const string MP4 = "mp4";
public const string MKV = "mkv";
}
}

View File

@ -2,6 +2,10 @@
{
public class SubtitleFormat
{
public const string SRT = "SRT";
public const string SRT = "srt";
public const string SSA = "ssa";
public const string ASS = "ass";
public const string VTT = "vtt";
public const string SUB = "sub";
}
}

View File

@ -2,11 +2,13 @@
{
public class VideoCodec
{
public const string H263 = "H263";
public const string H264 = "H264";
public const string H265 = "H265";
public const string MPEG4 = "MPEG4";
public const string MSMPEG4 = "MSMPEG4";
public const string VC1 = "VC1";
public const string H263 = "h263";
public const string H264 = "h264";
public const string H265 = "h265";
public const string MPEG4 = "mpeg4";
public const string MPEG1 = "mpeg1video";
public const string MPEG2 = "mpeg2video";
public const string MSMPEG4 = "msmpeg4";
public const string VC1 = "vc1";
}
}

View File

@ -12,6 +12,7 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@ -110,6 +111,15 @@ namespace MediaBrowser.Server.Implementations.Dto
AttachBasicFields(dto, item, owner, fields);
if (user != null && dto.MediaSources != null && item is Video)
{
foreach (var source in dto.MediaSources)
{
//source.DefaultAudioStreamIndex = GetDefaultAudioStreamIndex(source, user.Configuration);
//source.DefaultSubtitleStreamIndex = GetDefaultSubtitleStreamIndex(source, user.Configuration);
}
}
if (fields.Contains(ItemFields.SoundtrackIds))
{
var hasSoundtracks = item as IHasSoundtracks;

View File

@ -63,7 +63,7 @@
"HeaderPlaybackSettings": "Playback Settings",
"LabelAudioLanguagePreference": "Audio language preference:",
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
"LabelDisplayForcedSubtitlesOnly": "Display only forced subtitles",
"OptionDefaultSubtitles": "Default",
"TabProfiles": "Profiles",
"TabSecurity": "Security",
"ButtonAddUser": "Add User",
@ -228,6 +228,8 @@
"ButtonSearch": "Search",
"ButtonGroupVersions": "Group Versions",
"PismoMessage": "Utilizing Pismo File Mount through a donated license.",
"TangibleSoftwareMessage": "Utilizing Tangible Solutions Java/C# converters through a donated license.",
"HeaderCredits": "Credits",
"PleaseSupportOtherProduces": "Please support other free products we utilize:",
"VersionNumber": "Version {0}",
"TabPaths": "Paths",
@ -327,7 +329,7 @@
"OptionAutomatic": "Auto",
"LiveTvPluginRequired": "A Live TV service provider plugin is required in order to continue.",
"LiveTvPluginRequiredHelp": "Please install one of our available plugins, such as Next Pvr or ServerWmc.",
"HeaderCustomizeOptionsPerMediaType": "Customize options per media type",
"LabelCustomizeOptionsPerMediaType": "Customize for media type:",
"OptionDownloadThumbImage": "Thumb",
"OptionDownloadMenuImage": "Menu",
"OptionDownloadLogoImage": "Logo",
@ -339,6 +341,7 @@
"OptionDownloadPrimaryImage": "Primary",
"HeaderFetchImages": "Fetch Images:",
"HeaderImageSettings": "Image Settings",
"TabCustomizations": "Customizations",
"LabelMaxBackdropsPerItem": "Maximum number of backdrops per item:",
"LabelMaxScreenshotsPerItem": "Maximum number of screenshots per item:",
"LabelMinBackdropDownloadWidth": "Minimum backdrop download width:",
@ -721,7 +724,8 @@
"TabSubtitles": "Subtitles",
"LabelOpenSubtitlesUsername": "Open Subtitles username:",
"LabelOpenSubtitlesPassword": "Open Subtitles password:",
"LabelAudioLanguagePreferenceHelp": "If empty, the default audio track will be selected, regardless of language.",
"LabelPlayDefaultAudioTrack": "Play default audio track regardless of language",
"LabelSubtitlePlaybackMode": "Subtitle mode:",
"LabelDownloadLanguages": "Download languages:",
"ButtonRegister": "Register",
"LabelSkipIfAudioTrackPresent": "Skip if the default audio track matches the download language",

View File

@ -200,7 +200,6 @@
<Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" />
<Compile Include="Persistence\TypeMapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Roku\RokuControllerFactory.cs" />
<Compile Include="ScheduledTasks\PeopleValidationTask.cs" />
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
@ -209,7 +208,7 @@
<Compile Include="ServerApplicationPaths.cs" />
<Compile Include="ServerManager\ServerManager.cs" />
<Compile Include="ServerManager\WebSocketConnection.cs" />
<Compile Include="Roku\RokuSessionController.cs" />
<Compile Include="Session\HttpSessionController.cs" />
<Compile Include="Session\SessionManager.cs">
<SubType>Code</SubType>
</Compile>

View File

@ -1,36 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Server.Implementations.Roku
{
public class RokuControllerFactory : ISessionControllerFactory
{
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _json;
private readonly IServerApplicationHost _appHost;
public RokuControllerFactory(IHttpClient httpClient, IJsonSerializer json, IServerApplicationHost appHost)
{
_httpClient = httpClient;
_json = json;
_appHost = appHost;
}
public ISessionController GetSessionController(SessionInfo session)
{
if (string.Equals(session.Client, "roku", StringComparison.OrdinalIgnoreCase))
{
session.PlayableMediaTypes = new List<string> { MediaType.Video, MediaType.Audio };
return new RokuSessionController(_httpClient, _json, _appHost, session);
}
return null;
}
}
}

View File

@ -10,9 +10,9 @@ using System;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Roku
namespace MediaBrowser.Server.Implementations.Session
{
public class RokuSessionController : ISessionController
public class HttpSessionController : ISessionController
{
private readonly IHttpClient _httpClient;
private readonly IJsonSerializer _json;
@ -20,12 +20,21 @@ namespace MediaBrowser.Server.Implementations.Roku
public SessionInfo Session { get; private set; }
public RokuSessionController(IHttpClient httpClient, IJsonSerializer json, IServerApplicationHost appHost, SessionInfo session)
//var postUrl = string.Format("http://{0}/mediabrowser/message", session.RemoteEndPoint);
private readonly string _postUrl;
public HttpSessionController(IHttpClient httpClient,
IJsonSerializer json,
IServerApplicationHost appHost,
SessionInfo session,
string postUrl)
{
_httpClient = httpClient;
_json = json;
_appHost = appHost;
Session = session;
_postUrl = postUrl;
}
public bool SupportsMediaRemoteControl
@ -41,6 +50,19 @@ namespace MediaBrowser.Server.Implementations.Roku
}
}
private Task SendMessage(object obj, CancellationToken cancellationToken)
{
var json = _json.SerializeToString(obj);
return _httpClient.Post(new HttpRequestOptions
{
Url = _postUrl,
CancellationToken = cancellationToken,
RequestContent = json,
RequestContentType = "application/json"
});
}
public Task SendSessionEndedNotification(SessionInfoDto sessionInfo, CancellationToken cancellationToken)
{
return Task.FromResult(true);
@ -58,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Roku
public Task SendPlayCommand(PlayRequest command, CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<PlayRequest>
return SendMessage(new WebSocketMessage<PlayRequest>
{
MessageType = "Play",
Data = command
@ -68,7 +90,7 @@ namespace MediaBrowser.Server.Implementations.Roku
public Task SendPlaystateCommand(PlaystateRequest command, CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<PlaystateRequest>
return SendMessage(new WebSocketMessage<PlaystateRequest>
{
MessageType = "Playstate",
Data = command
@ -78,13 +100,12 @@ namespace MediaBrowser.Server.Implementations.Roku
public Task SendLibraryUpdateInfo(LibraryUpdateInfo info, CancellationToken cancellationToken)
{
// Roku probably won't care about this
return Task.FromResult(true);
}
public Task SendRestartRequiredNotification(CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<SystemInfo>
return SendMessage(new WebSocketMessage<SystemInfo>
{
MessageType = "RestartRequired",
Data = _appHost.GetSystemInfo()
@ -94,13 +115,12 @@ namespace MediaBrowser.Server.Implementations.Roku
public Task SendUserDataChangeInfo(UserDataChangeInfo info, CancellationToken cancellationToken)
{
// Roku probably won't care about this
return Task.FromResult(true);
}
public Task SendServerShutdownNotification(CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<string>
return SendMessage(new WebSocketMessage<string>
{
MessageType = "ServerShuttingDown",
Data = string.Empty
@ -110,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Roku
public Task SendServerRestartNotification(CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<string>
return SendMessage(new WebSocketMessage<string>
{
MessageType = "ServerRestarting",
Data = string.Empty
@ -118,24 +138,11 @@ namespace MediaBrowser.Server.Implementations.Roku
}, cancellationToken);
}
private Task SendCommand(object obj, CancellationToken cancellationToken)
{
var json = _json.SerializeToString(obj);
return _httpClient.Post(new HttpRequestOptions
{
Url = "http://" + Session.RemoteEndPoint + "/mb/remotecontrol",
CancellationToken = cancellationToken,
RequestContent = json,
RequestContentType = "application/json"
});
}
public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
{
return SendCommand(new WebSocketMessage<GeneralCommand>
return SendMessage(new WebSocketMessage<GeneralCommand>
{
MessageType = "Command",
MessageType = "GeneralCommand",
Data = command
}, cancellationToken);

View File

@ -1039,7 +1039,7 @@ namespace MediaBrowser.ServerApplication
{
var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, null, ApplicationVersion,
var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, "MBServer", null, ApplicationVersion,
ConfigurationManager.CommonConfiguration.SystemUpdateLevel);
HasUpdateAvailable = version != null && version.version >= ApplicationVersion;

View File

@ -481,7 +481,7 @@ namespace MediaBrowser.ServerApplication
private static bool PerformUpdateIfNeeded(ServerApplicationPaths appPaths, ILogger logger)
{
// Look for the existence of an update archive
var updateArchive = Path.Combine(appPaths.TempUpdatePath, Constants.MbServerPkgName + ".zip");
var updateArchive = Path.Combine(appPaths.TempUpdatePath, "MBServer" + ".zip");
if (File.Exists(updateArchive))
{
logger.Info("An update is available from {0}", updateArchive);

View File

@ -378,7 +378,7 @@ namespace MediaBrowser.WebDashboard.Api
//sb.Append("<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\">");
sb.Append("<link rel=\"icon\" sizes=\"114x114\" href=\"css/images/touchicon114.png\" />");
// http://developer.apple.com/library/ios/#DOCUMENTATION/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html
sb.Append("<link rel=\"apple-touch-icon\" href=\"css/images/touchicon.png\" />");
sb.Append("<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"css/images/touchicon72.png\" />");
@ -469,7 +469,7 @@ namespace MediaBrowser.WebDashboard.Api
builder.Append(Environment.NewLine);
}
}
foreach (var file in GetScriptFiles())
{
var path = GetDashboardResourcePath("scripts/" + file);
@ -563,7 +563,7 @@ namespace MediaBrowser.WebDashboard.Api
"itemgallery.js",
"itemlistpage.js",
"librarypathmapping.js",
"libraryreport.js",
"reports.js",
"librarysettings.js",
"livetvchannel.js",
"livetvchannels.js",
@ -670,6 +670,7 @@ namespace MediaBrowser.WebDashboard.Api
"remotecontrol.css",
"userimage.css",
"livetv.css",
"nowplaying.css",
"icons.css"
};

View File

@ -172,6 +172,9 @@
<Content Include="dashboard-ui\css\images\items\folders\edit.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\items\folders\report.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\images\items\folders\settings.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -280,6 +283,9 @@
<Content Include="dashboard-ui\css\mediaplayer.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\css\nowplaying.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\dashboardgeneral.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@ -313,7 +319,7 @@
<Content Include="dashboard-ui\librarypathmapping.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\libraryreport.html">
<Content Include="dashboard-ui\reports.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\livetvchannel.html">
@ -631,7 +637,7 @@
<Content Include="dashboard-ui\scripts\librarypathmapping.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\libraryreport.js">
<Content Include="dashboard-ui\scripts\reports.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\livetvchannel.js">