support theme songs in the web client
This commit is contained in:
parent
2913638b67
commit
e89d4e605b
|
@ -187,7 +187,7 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
if (!state.HasMediaStreams)
|
||||
{
|
||||
return state.IsInputVideo ? "-map -0:s" : string.Empty;
|
||||
return state.IsInputVideo ? "-sn" : string.Empty;
|
||||
}
|
||||
|
||||
if (state.VideoStream != null)
|
||||
|
@ -1493,7 +1493,7 @@ namespace MediaBrowser.Api.Playback
|
|||
|
||||
if (videoRequest != null)
|
||||
{
|
||||
if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream, state.VideoType))
|
||||
if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream))
|
||||
{
|
||||
videoRequest.VideoCodec = "copy";
|
||||
}
|
||||
|
@ -1507,19 +1507,13 @@ namespace MediaBrowser.Api.Playback
|
|||
return state;
|
||||
}
|
||||
|
||||
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream, VideoType videoType)
|
||||
private bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream)
|
||||
{
|
||||
if (videoStream.IsInterlaced)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not going to attempt this with folder rips
|
||||
if (videoType != VideoType.VideoFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Source and target codecs must match
|
||||
if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
|
|
@ -24,7 +24,8 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
/// </summary>
|
||||
public abstract class BaseHlsService : BaseStreamingService
|
||||
{
|
||||
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IDtoService dtoService, IFileSystem fileSystem, IItemRepository itemRepository, ILiveTvManager liveTvManager, IEncodingManager encodingManager, IDlnaManager dlnaManager)
|
||||
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, dtoService, fileSystem, itemRepository, liveTvManager, encodingManager, dlnaManager)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -77,6 +78,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
return ProcessRequestAsync(request).Result;
|
||||
}
|
||||
|
||||
private static readonly SemaphoreSlim FfmpegStartLock = new SemaphoreSlim(1, 1);
|
||||
/// <summary>
|
||||
/// Processes the request async.
|
||||
/// </summary>
|
||||
|
@ -103,13 +105,23 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
}
|
||||
|
||||
var playlist = GetOutputFilePath(state);
|
||||
var isPlaylistNewlyCreated = false;
|
||||
|
||||
// If the playlist doesn't already exist, startup ffmpeg
|
||||
if (!File.Exists(playlist))
|
||||
if (File.Exists(playlist))
|
||||
{
|
||||
isPlaylistNewlyCreated = true;
|
||||
|
||||
ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls);
|
||||
}
|
||||
else
|
||||
{
|
||||
await FfmpegStartLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (File.Exists(playlist))
|
||||
{
|
||||
ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the playlist doesn't already exist, startup ffmpeg
|
||||
try
|
||||
{
|
||||
await StartFfMpeg(state, playlist).ConfigureAwait(false);
|
||||
|
@ -120,15 +132,14 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls);
|
||||
}
|
||||
|
||||
if (isPlaylistNewlyCreated)
|
||||
{
|
||||
await WaitForMinimumSegmentCount(playlist, GetSegmentWait()).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FfmpegStartLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
int audioBitrate;
|
||||
int videoBitrate;
|
||||
|
|
|
@ -210,6 +210,9 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
return SetVolume(tmp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets volume on a scale of 0-100
|
||||
/// </summary>
|
||||
public async Task<bool> SetVolume(int value)
|
||||
{
|
||||
var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "SetVolume");
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Common.Net;
|
||||
using System.Globalization;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Dlna;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
|
@ -206,7 +207,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
IsPaused = _device.IsPaused,
|
||||
MediaSourceId = playlistItem.MediaSourceId,
|
||||
AudioStreamIndex = playlistItem.AudioStreamIndex,
|
||||
SubtitleStreamIndex = playlistItem.SubtitleStreamIndex
|
||||
SubtitleStreamIndex = playlistItem.SubtitleStreamIndex,
|
||||
VolumeLevel = _device.Volume
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -614,6 +616,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
}
|
||||
}
|
||||
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
GeneralCommandType commandType;
|
||||
|
@ -632,6 +636,24 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
return _device.VolumeUp(true);
|
||||
case GeneralCommandType.ToggleMute:
|
||||
return _device.ToggleMute();
|
||||
case GeneralCommandType.SetVolume:
|
||||
{
|
||||
string volumeArg;
|
||||
|
||||
if (command.Arguments.TryGetValue("Volume", out volumeArg))
|
||||
{
|
||||
int volume;
|
||||
|
||||
if (int.TryParse(volumeArg, NumberStyles.Any, _usCulture, out volume))
|
||||
{
|
||||
return _device.SetVolume(volume);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unsupported volume value supplied.");
|
||||
}
|
||||
|
||||
throw new ArgumentException("Volume argument cannot be null");
|
||||
}
|
||||
default:
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
|
|
@ -265,7 +265,8 @@ namespace MediaBrowser.Dlna.PlayTo
|
|||
GeneralCommandType.VolumeUp.ToString(),
|
||||
GeneralCommandType.Mute.ToString(),
|
||||
GeneralCommandType.Unmute.ToString(),
|
||||
GeneralCommandType.ToggleMute.ToString()
|
||||
GeneralCommandType.ToggleMute.ToString(),
|
||||
GeneralCommandType.SetVolume.ToString()
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -57,8 +57,17 @@ namespace MediaBrowser.Dlna.Server
|
|||
{
|
||||
builder.Append("<UDN>" + SecurityElement.Escape(_serverUdn) + "</UDN>");
|
||||
builder.Append("<dlna:X_DLNACAP>" + SecurityElement.Escape(_profile.XDlnaCap ?? string.Empty) + "</dlna:X_DLNACAP>");
|
||||
builder.Append("<dlna:X_DLNADOC>M-DMS-1.50</dlna:X_DLNADOC>");
|
||||
builder.Append("<dlna:X_DLNADOC>" + SecurityElement.Escape(_profile.XDlnaDoc ?? string.Empty) + "</dlna:X_DLNADOC>");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(_profile.XDlnaDoc))
|
||||
{
|
||||
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">" +
|
||||
SecurityElement.Escape(_profile.XDlnaDoc) + "</dlna:X_DLNADOC>");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.Append("<dlna:X_DLNADOC xmlns:dlna=\"urn:schemas-dlna-org:device-1-0\">DMS-1.50</dlna:X_DLNADOC>");
|
||||
}
|
||||
|
||||
builder.Append("<friendlyName>" + SecurityElement.Escape(_profile.FriendlyName ?? string.Empty) + "</friendlyName>");
|
||||
builder.Append("<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>");
|
||||
builder.Append("<manufacturer>" + SecurityElement.Escape(_profile.Manufacturer ?? string.Empty) + "</manufacturer>");
|
||||
|
@ -99,7 +108,7 @@ namespace MediaBrowser.Dlna.Server
|
|||
|
||||
foreach (var service in GetServices())
|
||||
{
|
||||
builder.Append("<icon>");
|
||||
builder.Append("<service>");
|
||||
|
||||
builder.Append("<serviceType>" + SecurityElement.Escape(service.ServiceType ?? string.Empty) + "</serviceType>");
|
||||
builder.Append("<serviceId>" + SecurityElement.Escape(service.ServiceId ?? string.Empty) + "</serviceId>");
|
||||
|
@ -107,7 +116,7 @@ namespace MediaBrowser.Dlna.Server
|
|||
builder.Append("<controlURL>" + SecurityElement.Escape(service.ControlUrl ?? string.Empty) + "</controlURL>");
|
||||
builder.Append("<eventSubURL>" + SecurityElement.Escape(service.EventSubUrl ?? string.Empty) + "</eventSubURL>");
|
||||
|
||||
builder.Append("</icon>");
|
||||
builder.Append("</service>");
|
||||
}
|
||||
|
||||
builder.Append("</serviceList>");
|
||||
|
|
|
@ -147,7 +147,7 @@ namespace MediaBrowser.Dlna.Server
|
|||
|
||||
foreach (var d in Devices)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(req) && req != d.Type)
|
||||
if (!string.IsNullOrEmpty(req) && !string.Equals(req, d.Type, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -263,13 +263,19 @@ namespace MediaBrowser.Dlna.Server
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var t in new[] { "upnp:rootdevice", "urn:schemas-upnp-org:device:MediaServer:1", "urn:schemas-upnp-org:service:ContentDirectory:1", "uuid:" + uuid })
|
||||
foreach (var t in new[]
|
||||
{
|
||||
"upnp:rootdevice",
|
||||
"urn:schemas-upnp-org:device:MediaServer:1",
|
||||
"urn:schemas-upnp-org:service:ContentDirectory:1",
|
||||
"uuid:" + uuid
|
||||
})
|
||||
{
|
||||
list.Add(new UpnpDevice(uuid, t, descriptor, address));
|
||||
}
|
||||
|
||||
NotifyAll();
|
||||
_logger.Debug("Registered mount {0}", uuid);
|
||||
_logger.Debug("Registered mount {0} at {1}", uuid, descriptor);
|
||||
}
|
||||
|
||||
private void UnregisterNotification(Guid uuid)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace MediaBrowser.Model.Dto
|
||||
|
|
|
@ -51,6 +51,12 @@ namespace MediaBrowser.Model.Session
|
|||
/// <value>The user id.</value>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the user primary image tag.
|
||||
/// </summary>
|
||||
/// <value>The user primary image tag.</value>
|
||||
public Guid? UserPrimaryImageTag { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the user.
|
||||
/// </summary>
|
||||
|
|
|
@ -34,7 +34,10 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
|
|||
{
|
||||
var collectionType = args.GetCollectionType();
|
||||
|
||||
if (string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
|
||||
var isStandalone = args.Parent == null;
|
||||
|
||||
if (isStandalone ||
|
||||
string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Controller.Entities.Audio.Audio();
|
||||
}
|
||||
|
|
|
@ -450,5 +450,70 @@
|
|||
"LabelMinResumeDuration": "Min resume duration (seconds):",
|
||||
"LabelMinResumePercentageHelp": "Titles are assumed unplayed if stopped before this time",
|
||||
"LabelMaxResumePercentageHelp": "Titles are assumed fully played if stopped after this time",
|
||||
"LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable"
|
||||
"LabelMinResumeDurationHelp": "Titles shorter than this will not be resumable",
|
||||
"TitleAutoOrganize": "Auto-Organize",
|
||||
"TabActivityLog": "Activity Log",
|
||||
"HeaderName": "Name",
|
||||
"HeaderDate": "Date",
|
||||
"HeaderSource": "Source",
|
||||
"HeaderStatus": "Status",
|
||||
"HeaderDestination": "Destination",
|
||||
"HeaderProgram": "Program",
|
||||
"HeaderClients": "Clients",
|
||||
"LabelCompleted": "Completed",
|
||||
"LabelFailed": "Failed",
|
||||
"LabelSkipped": "Skipped",
|
||||
"HeaderEpisodeOrganization": "Episode Organization",
|
||||
"LabelSeries": "Series:",
|
||||
"LabelSeasonNumber": "Season number:",
|
||||
"LabelEpisodeNumber": "Episode number:",
|
||||
"LabelEndingEpisodeNumber": "Ending episode number:",
|
||||
"LabelEndingEpisodeNumberHelp": "Only required for multi-episode files",
|
||||
"HeaderSupportTheTeam": "Support the Media Browser Team",
|
||||
"LabelSupportAmount": "Amount (USD)",
|
||||
"HeaderSupportTheTeamHelp": "Help ensure the continued development of this project by donating. A portion of all donations will be contributed to other free tools we depend on.",
|
||||
"ButtonEnterSupporterKey": "Enter supporter key",
|
||||
"DonationNextStep": "Once complete, please return and enter your supporter key, which you will receive by email.",
|
||||
"AutoOrganizeHelp": "Auto-organize monitors your download folders for new files and moves them to your media directories.",
|
||||
"AutoOrganizeTvHelp": "TV file organizing will only add episodes to existing series. It will not create new series folders.",
|
||||
"OptionEnableEpisodeOrganization": "Enable new episode organization",
|
||||
"LabelWatchFolder": "Watch folder:",
|
||||
"LabelWatchFolderHelp": "The server will poll this folder during the 'Organize new media files' scheduled task.",
|
||||
"ButtonViewScheduledTasks": "View scheduled tasks",
|
||||
"LabelMinFileSizeForOrganize": "Minimum file size (MB):",
|
||||
"LabelMinFileSizeForOrganizeHelp": "Files under this size will be ignored.",
|
||||
"LabelSeasonFolderPattern": "Season folder pattern:",
|
||||
"LabelSeasonZeroFolderName": "Season zero folder name:",
|
||||
"HeaderEpisodeFilePattern": "Episode file pattern",
|
||||
"LabelEpisodePattern": "Episode pattern:",
|
||||
"LabelMultiEpisodePattern": "Multi-Episode pattern:",
|
||||
"HeaderSupportedPatterns": "Supported Patterns",
|
||||
"HeaderTerm": "Term",
|
||||
"HeaderPattern": "Pattern",
|
||||
"HeaderResult": "Result",
|
||||
"LabelDeleteEmptyFolders": "Delete empty folders after organizing",
|
||||
"LabelDeleteEmptyFoldersHelp": "Enable this to keep the download directory clean.",
|
||||
"LabelDeleteLeftOverFiles": "Delete left over files with the following extensions:",
|
||||
"LabelDeleteLeftOverFilesHelp": "Separate with ;. For example: .nfo;.txt",
|
||||
"OptionOverwriteExistingEpisodes": "Overwrite existing episodes",
|
||||
"LabelTransferMethod": "Transfer method",
|
||||
"OptionCopy": "Copy",
|
||||
"OptionMove": "Move",
|
||||
"LabelTransferMethodHelp": "Copy or move files from the watch folder",
|
||||
"HeaderLatestNews": "Latest News",
|
||||
"HeaderHelpImproveMediaBrowser": "Help Improve Media Browser",
|
||||
"HeaderRunningTasks": "Running Tasks",
|
||||
"HeaderActiveDevices": "Active Devices",
|
||||
"HeaderPendingInstallations": "Pending Installations",
|
||||
"HeaerServerInformation": "Server Information",
|
||||
"ButtonRestartNow": "Restart Now",
|
||||
"ButtonRestart": "Restart",
|
||||
"ButtonShutdown": "Shutdown",
|
||||
"ButtonUpdateNow": "Update Now",
|
||||
"PleaseUpdateManually": "Please shutdown the server and update manually.",
|
||||
"NewServerVersionAvailable": "A new version of Media Browser Server is available!",
|
||||
"ServerUpToDate": "Media Browser Server is up to date",
|
||||
"ErrorConnectingToMediaBrowserRepository": "There was an error connecting to the remote Media Browser repository.",
|
||||
"LabelComponentsUpdated": "The following components have been installed or updated:",
|
||||
"MessagePleaseRestartServerToFinishUpdating": "Please restart the server to finish applying updates."
|
||||
}
|
|
@ -1182,6 +1182,13 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
if (session.UserId.HasValue)
|
||||
{
|
||||
dto.UserId = session.UserId.Value.ToString("N");
|
||||
|
||||
var user = _userManager.GetUserById(session.UserId.Value);
|
||||
|
||||
if (user != null)
|
||||
{
|
||||
dto.UserPrimaryImageTag = GetImageCacheTag(user, ImageType.Primary);
|
||||
}
|
||||
}
|
||||
|
||||
return dto;
|
||||
|
@ -1311,6 +1318,11 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
}
|
||||
}
|
||||
|
||||
if (backropItem == null)
|
||||
{
|
||||
backropItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Backdrop));
|
||||
}
|
||||
|
||||
if (thumbItem == null)
|
||||
{
|
||||
thumbItem = item.Parents.FirstOrDefault(i => i.HasImage(ImageType.Thumb));
|
||||
|
@ -1322,7 +1334,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
info.ThumbItemId = GetDtoId(thumbItem);
|
||||
}
|
||||
|
||||
if (thumbItem != null)
|
||||
if (backropItem != null)
|
||||
{
|
||||
info.BackdropImageTag = GetImageCacheTag(backropItem, ImageType.Backdrop);
|
||||
info.BackdropItemId = GetDtoId(backropItem);
|
||||
|
|
|
@ -608,6 +608,7 @@ namespace MediaBrowser.WebDashboard.Api
|
|||
"supporterkeypage.js",
|
||||
"supporterpage.js",
|
||||
"episodes.js",
|
||||
"thememediaplayer.js",
|
||||
"tvgenres.js",
|
||||
"tvlatest.js",
|
||||
"tvpeople.js",
|
||||
|
|
|
@ -220,6 +220,9 @@
|
|||
<Content Include="dashboard-ui\css\images\media\tvflyout.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\css\images\nowplayingdefault.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\css\livetv.css">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -505,6 +508,9 @@
|
|||
<Content Include="dashboard-ui\livetvrecordings.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\nowplaying.html">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\advancedpaths.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@ -637,6 +643,9 @@
|
|||
<Content Include="dashboard-ui\scripts\livetvsuggested.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\thememediaplayer.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="dashboard-ui\scripts\tvupcoming.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
|
Loading…
Reference in New Issue
Block a user