Introducing WMC mini-mods

Discussion of getting WMC to work on Windows 11 (unsupported)
Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

Introducing WMC mini-mods

#1

Post by Kevin Chalet » Sun Jan 21, 2024 5:07 pm

Hey everybody,

I recently mentioned .NET assembly patching as a way to tweak Windows Media Center and fix broken things or change how specific features work internally.

It's definitely not something new and I've personally been using this approach for years to implement QoL improvements that make my everyday use of WMC a more pleasant experience. But since it requires replacing the Windows Media Center files by patched versions, it was a risky option when Windows Media Center was still supported (as there was a risk the patched .dlls would end up being overwritten by Microsoft during an update).
Now that Windows 8.1 - the latest Windows version offering WMC as a paid option - is no longer supported, this risk is pretty much non-existent.

As I suspect some of these patches might be useful to other people, I decided to share them and distribute the patched assemblies so that people not comfortable with this technique can benefit from these QoL improvements.

Given these changes target very specific areas of WMC, I decided to call this project "WMC mini-mods" :mrgreen:

For those who are interested in the gnarly details, here's the list of opt-in patches I decided to include in the 1.0.0 version:

mcepg.dll patches:

Option to disable the automatic removal of "invalid" TV recordings:

By default, when launching ehshell.exe, a "watcher" instance is automatically started by WMC to scan new TV recordings and delete TV recordings that are thought to be missing or unreadable. It's a very convenient feature as it ensures TV recordings that are no longer on the disk are automatically removed from the WMC database.

Sadly, this feature has a huge downside when using remote shares: if a remote share is for some reason inaccessible at the exact moment WMC starts scanning it (e.g the server is being rebooted or the WMC machine is not connected to the network), all the recordings it contains are automatically removed from the WMC database. It's of course no big deal when you have a few hundred recordings but - if like me - you have thousands of recordings, the user experience is absolutely horrible, as WMC has to rescan everything, which takes ages. Not to mention that the thumbnails are deleted and have to be recreated one by one by the ehvid.exe process (which is quite unreliable when having to handle thousands of recordings at the same time).

The workaround for that is quite simple: disabling the automatic removal so that recordings are not deleted by WMC, unless when they are deleted via the WMC GUI or from the disk when ehshell.exe is running.
For that, I patched the Watcher.EnsureValidRecordings() method to return immediately if DisableInvalidRecordingsDeletion was set to 1 in the registry:

Code: Select all

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.MediaCenter.Interop;

namespace Microsoft.MediaCenter.Pvr
{
    // Token: 0x020001F7 RID: 503
    public sealed partial class Watcher : ICollection<string>, IEnumerable<string>, IEnumerable, IDisposable
    {
        // Token: 0x06000F9C RID: 3996 RVA: 0x000411B0 File Offset: 0x0003F3B0
        private void EnsureValidRecordings()
        {
            var setting = Settings.Recording.Value<int>("DisableInvalidRecordingsDeletion");
            if (setting.Value == 1)
            {
                return;
            }

            using (ILockHandle usingHandle = this._library.UsingHandle)
            {
                if (usingHandle.IsLocked)
                {
                    foreach (object obj in this._library.Recordings)
                    {
                        Recording recording = (Recording)obj;
                        if (!this.Contains(recording.FileName))
                        {
                            this.OnDeletedFile(recording.FileName);
                        }
                        else
                        {
                            Win32Api.WIN32_FILE_ATTRIBUTE_DATA win32_FILE_ATTRIBUTE_DATA = default(Win32Api.WIN32_FILE_ATTRIBUTE_DATA);
                            if (!Win32Api.GetFileAttributesEx(recording.FileName, Win32Api.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, out win32_FILE_ATTRIBUTE_DATA))
                            {
                                int lastWin32Error = Marshal.GetLastWin32Error();
                                if ((long)lastWin32Error != 5L && (long)lastWin32Error != 86L && (long)lastWin32Error != 1244L && (long)lastWin32Error != 1326L)
                                {
                                    this.OnDeletedFile(recording.FileName);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Option to store the season number and episode number in WTV files:

For reasons beyond my comprehension, Windows Media Center doesn't store the episode number or season number in the .wtv files it creates, even if these details were available in the EPG. Of course, one of the common approaches to deal with that is to store these details in the program description, but if your EPG source doesn't do that, the episode details will be lost. Yet, these details can be very useful when creating your own library management tools.

The fix for that is very simple: storing these values in the WTV metadata when creating the recordings. For that, I patched the RecordingMetadata.WriteInitialMetadata() method to store the episode and season numbers as WM/EpisodeNumber and WM/SeasonNumber attributes if WriteAdditionalMetadata was set to 1 in the registry.

Code: Select all

using System;

namespace Microsoft.MediaCenter.Pvr
{
    // Token: 0x02000189 RID: 393
    internal static partial class RecordingMetadata
    {
        // Token: 0x06000BBD RID: 3005 RVA: 0x0002EEE8 File Offset: 0x0002D0E8
        public static void WriteInitialMetadata(IRecordingMetadata metadata, RecordingAttributes attributes)
        {
            if (metadata == null)
            {
                throw new ArgumentNullException("metadata");
            }
            if (attributes == null)
            {
                throw new ArgumentNullException("attributes");
            }
            attributes.Write("WM/MediaClassPrimaryID", RecordingMetadata.PrimaryCLSID);
            attributes.Write("WM/MediaClassSecondaryID", RecordingMetadata.SecondaryCLSID);
            attributes.Write("Title", metadata.Title);
            attributes.Write("WM/SubTitle", metadata.EpisodeTitle);
            attributes.Write("WM/SubTitleDescription", metadata.Description);
            attributes.Write("WM/Genre", metadata.Genre);
            attributes.Write("WM/OriginalReleaseTime", metadata.YearString);
            attributes.Write("WM/Language", metadata.Language);
            attributes.Write("WM/MediaCredits", metadata.Credits);
            attributes.Write("WM/MediaStationCallSign", metadata.CallSign);
            attributes.Write("WM/MediaStationName", metadata.StationName);
            attributes.Write("WM/MediaNetworkAffiliation", metadata.NetworkAffiliation);
            attributes.Write("WM/MediaOriginalChannel", metadata.Channel);
            attributes.Write("WM/MediaOriginalChannelSubNumber", metadata.ChannelSubNumber);
            attributes.Write("WM/MediaOriginalBroadcastDateTime", metadata.OriginalAirString);
            attributes.Write("WM/MediaOriginalRunTime", metadata.RunTime);
            attributes.Write("WM/MediaIsStereo", metadata.Stereo);
            attributes.Write("WM/MediaIsRepeat", metadata.Repeat);
            attributes.Write("WM/MediaIsLive", metadata.Live);
            attributes.Write("WM/MediaIsTape", metadata.Tape);
            attributes.Write("WM/MediaIsDelay", metadata.Delay);
            attributes.Write("WM/MediaIsSubtitled", metadata.SubTitled);
            attributes.Write("WM/MediaIsMovie", metadata.Movie);
            attributes.Write("WM/MediaIsPremiere", metadata.Premiere);
            attributes.Write("WM/MediaIsFinale", metadata.Finale);
            attributes.Write("WM/MediaIsSAP", metadata.SAP);
            attributes.Write("WM/MediaIsSport", metadata.Sport);
            attributes.Write("WM/ParentalRating", metadata.RatingLevel);
            attributes.Write("WM/ParentalRatingReason", metadata.RatingReason);
            attributes.Write("WM/Provider", metadata.Provider);
            attributes.Write("WM/ProviderCopyright", metadata.Copyright);
            attributes.Write("WM/ProviderRating", metadata.StarRating);
            attributes.Write("WM/VideoClosedCaptioning", metadata.CC);
            attributes.Write("WM/WMRVEncodeTime", metadata.StartTimeTicks);
            attributes.Write("WM/WMRVSeriesUID", metadata.SeriesUID);
            attributes.Write("WM/WMRVServiceID", metadata.ServiceID);
            attributes.Write("WM/WMRVProgramID", metadata.ProgramID);
            attributes.Write("WM/WMRVRequestID", metadata.RecordingRequestID);
            attributes.Write("WM/WMRVScheduleItemID", metadata.Id);
            attributes.Write("WM/WMRVQuality", metadata.Quality);
            attributes.Write("WM/WMRVOriginalSoftPrePadding", metadata.OriginalSoftPrePadding);
            attributes.Write("WM/WMRVOriginalSoftPostPadding", metadata.OriginalSoftPostPadding);
            attributes.Write("WM/WMRVHardPrePadding", metadata.HardPrePadding);
            attributes.Write("WM/WMRVHardPostPadding", metadata.HardPostPadding);
            attributes.Write("WM/WMRVBrandingName", metadata.BrandingName);
            attributes.Write("WM/WMRVBrandingImageID", metadata.BrandingImageID);
            attributes.Write("WM/WMRVATSCContent", metadata.ATSCContent);
            attributes.Write("WM/WMRVDTVContent", metadata.DTV);
            attributes.Write("WM/WMRVHDContent", metadata.HDTV);
            
            var setting = Settings.Recording.Value<int>("WriteAdditionalMetadata");
            if (setting.Value == 1)
            {
                if (metadata is Recording recording)
                {
                    attributes.Write("WM/SeasonNumber", recording.Program.SeasonNumber);
                    attributes.Write("WM/EpisodeNumber", recording.Program.EpisodeNumber);
                }

                else if (metadata is RemoteRecording remoteRecording)
                {
                    attributes.Write("WM/SeasonNumber", remoteRecording.Program.SeasonNumber);
                    attributes.Write("WM/EpisodeNumber", remoteRecording.Program.EpisodeNumber);
                }
            }
        }
    }
}
ehshell.dll patches:

Option to disable TV overscan independently of the configured TV mode:

While most users have probably never realized it, Windows Media Center automatically applies a small overscan to all TV programs (live or recorded). Some people - myself included - didn't like that and eventually found a workaround: running the display configuration wizard and selecting "TV set" as the main display to disable it (in this case, WMC uses what it calls a "TV skin" mode that assumes the TV set itself will perform an overscan and disables its own one to prevent a double-overscan). Sadly, this had side effects (e.g it slightly changed the colors and contrast) and required tweaking a few registry keys to undo the extended margins applied by WMC when using this mode.

To simplify things a lot, I patched PresentationPolicy.OverscanMode to completely disable the overscan when DisableVideoOverscan is set to 1, without ever having to run the display configuration wizard.

Code: Select all

using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.MediaCenter.Interop;
using Microsoft.MediaCenter.Shell;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.UI.Drawing;
using Microsoft.MediaCenter.UI.VideoPlayback;
using ServiceBus.UIFramework;
using Microsoft.Win32;

namespace Microsoft.MediaCenter.Playback
{
    // Token: 0x020008C6 RID: 2246
    public partial class PresentationPolicy : DynamicImage.IDynamicImageOwner, IDisposable
    {
        // Token: 0x17001481 RID: 5249
        // (get) Token: 0x06004F7B RID: 20347 RVA: 0x001425A4 File Offset: 0x001407A4
        private VideoOverscanMode OverscanMode
        {
            get
            {
                var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Settings\\DisplayService");
                if (UCPUtility.CheckBoolRegVal(key, "DisableVideoOverscan"))
                {
                    return VideoOverscanMode.NoOverscan;
                }

                VideoOverscanMode videoOverscanMode = VideoOverscanMode.NoOverscan;
                if (!UCPUtility.UseTVSkin || this.Form.WindowState != FormWindowState.Maximized)
                {
                    if (this.HasNoOverscanOverride)
                    {
                        videoOverscanMode = VideoOverscanMode.ValidContent;
                    }
                    else if (this.IsBroadcastMediaItemPlaying)
                    {
                        videoOverscanMode = VideoOverscanMode.InvalidContent;
                    }
                    else if (this.IsDvdMediaItemPlaying)
                    {
                        videoOverscanMode = VideoOverscanMode.ValidContent;
                    }
                }
                return videoOverscanMode;
            }
        }
    }
}
Option to disable the DirectX 9 fullscreen exclusive mode:

I recently had to add this one to work around an issue I was seeing on an Intel NUC. While it worked for me, it seems it's not enough to fix the issues encountered by owners of Intel 11th generation iGPUs: that said, I decided to keep it in case it could help other people. For that, I had to patch the PageBasedUCPService.OnRendererConnected() method:

Code: Select all

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel.Design;
using System.Runtime.InteropServices;
using System.Threading;
using ehiExtCOM;
using EHMedia;
using MediaCenter.Extensibility;
using Microsoft.MediaCenter.Debug;
using Microsoft.MediaCenter.Hosting.Infrastructure;
using Microsoft.MediaCenter.Interop;
using Microsoft.MediaCenter.Playback;
using Microsoft.MediaCenter.Shell;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.UI.Drawing;
using Microsoft.MediaCenter.UI.VideoPlayback;
using Microsoft.MediaCenter.Utility;
using Microsoft.Win32;

namespace ServiceBus.UIFramework
{
    // Token: 0x02000B4F RID: 2895
    internal sealed partial class PageBasedUCPService : UCPService, IUsageLogger, IUIVideoStreamBroker
    {
        // Token: 0x060066D7 RID: 26327 RVA: 0x001A2C64 File Offset: 0x001A0E64
        private void OnRendererConnected(object sender, EventArgs args)
        {
            PerfInfo.SetMark("ehShell::OnRendererEnter");
            Capabilities.UpdateRemoteKeyboard();
            this.AddPrivateFonts();
            switch (this._session.DeviceType)
            {
            case DeviceType.Gdi:
                this.InitGdiDevice();
                break;
            case DeviceType.NtDirectX9:
                this.InitNtDevice();
                break;
            case DeviceType.XeDirectX9:
                this.InitXeDevice();
                break;
            }
            if (Capabilities.IsUISessionRemoted)
            {
                PageBasedUCPService.s_hShellReadyEvent = Win32Api.OpenEvent(2U, false, "ShellDesktopSwitchEvent");
                PageBasedUCPService.s_hUserRequestedCloseEvent = Win32Api.CreateEvent(IntPtr.Zero, false, false, "UserRequestedEhshellCloseEvent");
            }
            Dx9DeviceInfo.RemoveFromRegistry(Registry.CurrentUser, "Software\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Dx9DeviceInfo");
            this._session.InvalidKeyFocus += this.OnInvalidKeyFocus;
            this._session.KeyCoalescePolicy = new KeyCoalesceFilter(this.QueryCoalesce);
            this._popupUiTracker = new VisibleUITracker();
            this._popupUiTracker.MemberStatusChange += this.OnVisiblePopupChange;
            this._session.OnUnhandledException += this.MyUnhandledExceptionHandler;
            this._session.Rendering.OnRendererSuspended += new RenderingSession.RendererSuspendedHandler(this.MyRendererSuspendedHandler);
            this._session.Rendering.OnLostSound += new RenderingSession.LostSoundHandler(this.MyLostSoundHandler);
            this._session.OutputDevice.FallbackFontName = this.RootStyleFrame.Constants["FallbackFontFace"];
            this._session.Rendering.ImagePartResolver = new ResolveImagePartHandler(this.LoadImage);
            this._bgPages = new HybridDictionary();
            this.UserConfig.LoadWithUpgrade(typeof(PageBasedUCPUserConfig));
            this.UpdateSoundEffectsState();
            this.UserConfig.InitOverscanMargins();
            ShellData shellData = ShellData.Get(this.Session);
            if (shellData != null)
            {
                shellData.SetBindNavHintsToToolbars(PageBasedUCPService.GlobalConfig.bindNavHintsToToolbars);
            }
            this._serviceDisplay = new DisplayService(this._session);
            this._serviceDisplay.LoadSettings();
            this.UpdateAnimationState();
            AnimationDescription.CreateRootAnimation("CommonAnimations.xml");
            this.UpdateSkin();
            this.RefreshHighContrastMode();
            this._backPages = new PageBasedUCPService.PageStack(UCPService.s_iStackDepth);
            this._backPages.ShouldDisposeHandler = new PageBasedUCPService.PageStack.ShouldDisposeDelegate(this.ShouldDisposePSE);
            this.PushTemporaryBackground();
            this._notifyWindow = new PageBasedUCPNotifyWindow(this);
            bool flag = true;
            if (base.GetOption("nochrome"))
            {
                this._fStandardWindowAdornment = false;
            }
            this._form = new PageBasedUCPForm(this, this._session, this._fStandardWindowAdornment, flag);

            var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Settings\\DisplayService");
            if (UCPUtility.CheckBoolRegVal(key, "DisableFullscreenOptimizations"))
            {
                this._form.OptimizeFullscreenMode = false;
            }

            this._form.PreDestroy += this.OnPreShutdown;
            this._form.AppNotifyWindow = this._notifyWindow.Handle;
            Win32Api.STARTUPINFO startupinfo = new Win32Api.STARTUPINFO();
            Win32Api.GetStartupInfo(startupinfo);
            ushort wShowWindow = startupinfo.wShowWindow;
            FormWindowState formWindowState;
            switch (wShowWindow)
            {
            case 2:
            case 6:
            case 7:
                break;
            case 3:
                formWindowState = FormWindowState.Maximized;
                goto IL_2FA;
            case 4:
            case 5:
                goto IL_2D1;
            default:
                if (wShowWindow != 11)
                {
                    goto IL_2D1;
                }
                break;
            }
            formWindowState = FormWindowState.Minimized;
            goto IL_2FA;
            IL_2D1:
            if (this.ExtensibilityHostMode)
            {
                formWindowState = FormWindowState.Normal;
            }
            else
            {
                int showCmd = this.UserConfig.showCmd;
                if (showCmd == 1 || showCmd == 5)
                {
                    formWindowState = FormWindowState.Normal;
                }
                else
                {
                    formWindowState = FormWindowState.Maximized;
                }
            }
            IL_2FA:
            Point point = new Point(0, 0);
            Size size = new Size(0, 0);
            this.GetDefaultPositionAndSize(ref point, ref size);
            this.ValidateWindowPosition(ref point);
            this.ValidateWindowSize(ref size, formWindowState);
            if (!Capabilities.Current.IsWindowModeAllowed)
            {
                formWindowState = FormWindowState.Maximized;
            }
            this.Form.Position = point;
            this.Form.InitialClientSize = size;
            this.Form.WindowState = formWindowState;
            this.LaunchWindowState = this.Form.WindowState;
            this.Form.MinResizeWidth = 230;
            this.Form.MaxResizeWidth = -1;
            this.UpdateDisplayOverscan(this.UserConfig.OverscanMargins);
            if (base.GetOption("alwaysallowscreensaver"))
            {
                this.Form.PushPreventScreenSaverBlocks();
            }
            this._rootGadget = new RootGadget(this.RootStyleFrame, UCPService.StringTable, this);
            this.UpdateAppBackground();
            this._pageHost = new PageHost(this.NotificationPanel, this, this._services);
            this._rootGadget.IdealLeft = new SizeSpec(0);
            this._rootGadget.IdealTop = new SizeSpec(0);
            this._rootGadget.IdealWidth = new SizeSpec(1024);
            this._rootGadget.IdealHeight = new SizeSpec(768);
            AutoScan.NotifyOnMusicInsertEvent += base.HandleMusicInsertEvent;
            AutoScan.NotifyOnAudioCDEvent += this.CdromChangeEvent;
            AutoScan.NotifyOnCDEvent += this.NotifyFPDOnCDChangeEvent;
            this._loggingTimer = new Microsoft.MediaCenter.UI.Timer();
            this._loggingTimer.TimeSpanInterval = TimeSpan.FromMinutes(1.0);
            this._loggingTimer.AutoRepeat = true;
            this._loggingTimer.Enabled = true;
            this.InitTemplates();
            PerfInfo.SetMark("ehShell::OnRendererDone");
        }
    }
}
Option to force Windows Media Center to always run fullscreen:

I added this option as a way to mitigate one of the side effects of running WMC with the fullscreen exclusive mode disabled: the fact the WMC GUI didn't run fullscreen when restarting it. For that, I decided to patch the LocalCapabilities.InitializeDefaultProperties() to force WMC to always run fullscreen when DisableWindowedMode is set to 1:

Code: Select all

using System;
using System.Text;
using Microsoft.MediaCenter.Debug;
using Microsoft.MediaCenter.Interop;
using Microsoft.Win32;

namespace ServiceBus.UIFramework
{
    // Token: 0x02000AE9 RID: 2793
    internal partial class LocalCapabilities : Capabilities
    {
        // Token: 0x06006398 RID: 25496 RVA: 0x001973A0 File Offset: 0x001955A0
        protected override void InitializeDefaultProperties()
        {
            StringBuilder stringBuilder = new StringBuilder(260);
            int capacity = stringBuilder.Capacity;
            try
            {
                if (UIHelper.EHGetUserName(stringBuilder, ref capacity) == 0)
                {
                    this.m_strClientName = stringBuilder.ToString();
                }
            }
            catch (Exception ex)
            {
                if (eDebug.FilterException("Unable to get User Name", eDebug.ExceptionType.Ignored, ex))
                {
                    throw;
                }
            }
            this.m_bAreAdvancedPhotoFeaturesAllowed = true;
            this.m_bArePopupsAllowed = true;
            this.m_bAreVideoZoomModesAllowed = true;
            this.m_bIs10FootHelpAllowed = true;
            this.m_bIs10FootWebContentAllowed = true;
            this.m_bIs2FootHelpAllowed = true;
            this.m_bIs2FootWebContentAllowed = true;
            this.m_bIsAudioAllowed = true;
            this.m_bIsAutoRestartAllowed = true;
            this.m_bIsCDBurningAllowed = true;
            this.m_bIsCDCopyingAllowed = true;
            this.m_bIsCDPlaybackAllowed = true;
            this.m_bIsDVDBurningAllowed = true;
            this.m_bIsDvdPlaybackAllowed = true;
            this.m_bIsFPDAllowed = true;
            this.m_bIsHDContentAllowed = true;
            this.m_bIsHDContentAllowedByNetwork = true;
            this.m_bIsIntensiveAnimationAllowed = true;
            this.m_bIs2DAnimationAllowed = false;
            this.m_bIsIntensiveHTMLRenderingAllowed = true;
            this.m_bIsMyDocumentsPopulated = true;
            this.m_bIsOnlineSpotlightAllowed = true;
            this.m_bIsSDContentAllowedByNetwork = true;
            this.m_bIsToolbarAllowed = true;
            this.m_bIsTransferToDeviceAllowed = true;
            this.m_bIsTrayAppletAllowed = true;
            this.m_bIsUISoundSupported = true;
            this.m_bIsVideoAllowed = true;
            this.m_bIsVolumeUIAllowed = true;
            this.m_bIsMuteUIAllowed = true;
            this.m_bIsWin32ContentAllowed = true;
            this.m_bIsWmpVisualizationAllowed = true;
            this.m_bIsNonLinearZoomSupported = true;
            this.m_bIsRawStretchedZoomSupported = false;
            this.m_bIsWidescreenSupported = true;
            this.m_bIsHighContrastSkinSupported = true;
            this.m_strProtocolInfo = "";
            this.m_strGetExtenderType = "";
            this.m_strGetPakBuildVersion = "";

            var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Settings\\DisplayService");
            if (UCPUtility.CheckBoolRegVal(key, "DisableWindowedMode"))
            {
                this.m_bIsWindowModeAllowed = false;
            }
            else
            {
                this.m_bIsWindowModeAllowed = true;
            }
        }
    }
}
For those who don't want to patch the Windows Media Center assemblies themselves, I attached a copy of the WMC mini-mods 1.0.0 tool, which is based on the DLLs taken from the 8.8.5 installer (x64-only).
While it's based on the 8.8.5 installer, it should also work with the other branches.

The tool is very easy to use: make sure WIndows Media Center is not running (ehshell + the ehrecvr/ehsched services) and launch Installer.cmd.

Once you've done that, configure the registry keys depending on the options you want to enable. To enable everything, you can create a .reg file with the following content:

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\Recording]
"DisableInvalidRecordingsDeletion"=dword:00000001
"WriteAdditionalMetadata"=dword:00000001

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Settings\DisplayService]
"DisableVideoOverscan"=dword:00000001
"DisableWindowedMode"=dword:00000001
"DisableFullscreenOptimizations"=dword:00000001
To disable everything, you can create a .reg file with the following content:

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\Recording]
"DisableInvalidRecordingsDeletion"=dword:00000000
"WriteAdditionalMetadata"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Settings\DisplayService]
"DisableVideoOverscan"=dword:00000000
"DisableWindowedMode"=dword:00000000
"DisableFullscreenOptimizations"=dword:00000000
Hope this will be useful to other people :mrgreen:
Of course, I'm open to adding other fixes/workarounds, but please keep in mind they have to stay very focused (e.g changing the EPG to have a completely different look is not a goal of this project)
Attachments
WMC mini-mods 1.0.0.zip
(2.44 MiB) Downloaded 102 times
Last edited by Kevin Chalet on Mon Jan 22, 2024 12:36 pm, edited 1 time in total.

Space

Posts: 2840
Joined: Sun Jun 02, 2013 9:44 pm
Location:

HTPC Specs: Show details

#2

Post by Space » Sun Jan 21, 2024 10:00 pm

Wow! Good stuff!

The WMC bug that has always annoyed me is when it marks multiple instances of the same exact episode to record. For instance if an episode is airing multiple times within a few days, it will have all of them marked (8pm, 11pm, 2am, etc.) This doesn't always happen, but I usually notice that it happens when those multiple instances are first in the guide as "generic" episodes, and therefore WMC correctly marks them to record, however when a later guide update adds the episode specific information to these episodes, WMC continues to keep all of them marked to record instead of realizing that they are all the same episode and it only needs to record one of them.

Not sure if this is something that would be in scope for this type of "fix", it may be too complicated compared to these relatively more simple "tweaks", but I just thought I'd mention it since it is something that has been plaguing me since I first started using WMC over a decade ago.

As an aside, I assume if you run "SFC /scannow" these tweaks would be removed, correct?

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#3

Post by Kevin Chalet » Sun Jan 21, 2024 11:32 pm

Space wrote: Sun Jan 21, 2024 10:00 pm Wow! Good stuff!
Thanks :mrgreen:
Space wrote: Sun Jan 21, 2024 10:00 pm The WMC bug that has always annoyed me is when it marks multiple instances of the same exact episode to record. For instance if an episode is airing multiple times within a few days, it will have all of them marked (8pm, 11pm, 2am, etc.) This doesn't always happen, but I usually notice that it happens when those multiple instances are first in the guide as "generic" episodes, and therefore WMC correctly marks them to record, however when a later guide update adds the episode specific information to these episodes, WMC continues to keep all of them marked to record instead of realizing that they are all the same episode and it only needs to record one of them.

Not sure if this is something that would be in scope for this type of "fix", it may be too complicated compared to these relatively more simple "tweaks", but I just thought I'd mention it since it is something that has been plaguing me since I first started using WMC over a decade ago.
Interesting: I've never encountered this bug (my EPG source uses a different program ID if they change the episode number), but I suspect I've seen a related one: sometimes, they need to correct the extended cast/crew and fix the name of actors or directors but don't change the program ID. When WMC imports the updated guide, it doesn't correctly merge the updated program with the old one and I end up with multiple entries for the same role. It's very likely there's a bug somewhere that affects how entries are merged in the WMC database (in their defense, program details should be immutable).

When that happens, try to run the ReindexSearchRoot scheduled task to force ehsched to re-evaluate recordings and see if it helps.

I'll take a look, but I suspect it won't be easy to find what's the root cause :mrgreen:
Space wrote: Sun Jan 21, 2024 10:00 pm As an aside, I assume if you run "SFC /scannow" these tweaks would be removed, correct?
Unless you're using one of the old branches based on DISM, nope, the tweaks should survive as none of the ehome files are marked as protected system files so they shouldn't be affected (it's worth noting that all existing installers already use patched binaries and AFAIK, we haven't seen reports indicating running SFC breaks things).
Last edited by Kevin Chalet on Mon Jan 22, 2024 10:27 am, edited 1 time in total.

Space

Posts: 2840
Joined: Sun Jun 02, 2013 9:44 pm
Location:

HTPC Specs: Show details

#4

Post by Space » Mon Jan 22, 2024 5:16 am

Next time it happens I will try running ReindexSearchRoot. I do know that one of those WMC maintenance processes does "fix" this problem, but I don't remember if it was this one. But I don't think it was because I believe that this process runs after every EPG123 guide update and it does not fix it.

Another interesting thing about this problem is, for example, if I have a Series for a show, and there are three airings of a specific episode of this series, and they are all scheduled to record (due to this bug), I can select two of them and select "Do not record" and the red dot will go away, and they will not record, however the one I didn't tell WMC to not record will still record, even if the guide updates multiple times between when I told WMC to not record those two instances of the episode.

Normally when you tell WMC to "do not record" an episode that was set to record due to a Series request, it will add that episode to the list of episodes that have already been recorded, and therefore will not record it in the future. But in this case, it does not appear to do that, or at least WMC ignores the fact that it is in that list and still records that one airing that was set to record.

Also note that if for some reason WMC is unable to record that episode (perhaps a conflict later occurs, or a power outage at airing time, etc.) it will NOT consider the two episodes that I told it to "Do not record" as replacement airings and will still not record them, however if another airing shows up in the guide at a later time, it WILL record it, assuming it meets the criteria for the Series (i.e.: it's not set to "New only" if it is airing more than 7 days from the OAD).

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#5

Post by Kevin Chalet » Mon Jan 22, 2024 11:17 am

Thanks for all these details! I started taking a look, but of course, it's like looking for a needle in a haystack: that part is absolutely massive (of course, it's not surprising as the scheduling stuff in WMC is very powerful and one of its best features!).
I'll set up a VM and try to recreate the scenario you describe. If you could isolate a specific program that causes and create two MXF files with just that program (one buggy and one with the fixed series info), that would also help a lot.

If you're interested in giving it a try too, you can download ILSpy from GitHub (https://github.com/icsharpcode/ILSpy/re ... 35-x64.zip) and load mcepg.dll from the ehome folder: it's very likely the root cause is somewhere in that assembly :mrgreen:

prsa01

Posts: 136
Joined: Fri Dec 13, 2019 4:19 pm
Location:

HTPC Specs: Show details

#6

Post by prsa01 » Mon Jan 22, 2024 11:56 am

Wonderful stuff, Kevin, Thanks much!

If these changes are tweaking the ehshell, or any other files, I would expect they need to be ported to the install package afterwards, correct? If a win10/11 update requires going thru the uninstall /reinstall process to get wmc back again.

If simpler i suppose ehome could just be overwritten after un/install process.

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#7

Post by Kevin Chalet » Mon Jan 22, 2024 12:34 pm

prsa01 wrote: Mon Jan 22, 2024 11:56 am Wonderful stuff, Kevin, Thanks much!
Thanks! :thumbup:
prsa01 wrote: Mon Jan 22, 2024 11:56 am If these changes are tweaking the ehshell, or any other files, I would expect they need to be ported to the install package afterwards, correct? If a win10/11 update requires going thru the uninstall /reinstall process to get WMC back again.

If simpler i suppose ehome could just be overwritten after un/install process.
Yeah, the idea with this tool is that you first use the installer of your choice (I'd recommend 8.8.5 or Gary's MSI-based installer personally) and then use it to overwrite the existing files.
Alternatively, if you prefer doing that in a single pass, you can unzip the 8.8.5 installer and replace the two .dll by the patched versions contained in the mini-mods patcher.

That said, maybe I should release a 8.8.6 version that directly does that?

User avatar
IT Troll

Posts: 1193
Joined: Sun Nov 27, 2011 9:42 am
Location: Edinburgh, UK

HTPC Specs: Show details

#8

Post by IT Troll » Tue Jan 23, 2024 10:24 pm

Some really nice mods there. Thanks for sharing with the community.
What is the situation for folks running Windows 7 or 8? I'm guessing the patched DLL is one originally taken from Windows 8.

Once cosmetic annoyance I would love to see patched is the fact Media Center applies a blue tint to inactive third-party tiles on the home screen menu strips. With theme utilities you can change almost everything, but that blue tint is hard coded.
Are you a Recorded TV HD user or want to give it a try? Check out the new community-made update; Recorded TV HD v2.1.1

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#9

Post by Kevin Chalet » Wed Jan 24, 2024 9:23 am

IT Troll wrote: Tue Jan 23, 2024 10:24 pm Some really nice mods there. Thanks for sharing with the community.
My pleasure! It's something I wanted to do for a long time :mrgreen:
IT Troll wrote: Tue Jan 23, 2024 10:24 pm What is the situation for folks running Windows 7 or 8? I'm guessing the patched DLL is one originally taken from Windows 8.
It won't work (at all) on Windows 7, as the original .dll are indeed taken from the 8.8.5 package, which is essentially a .zip of the ehome folder extracted from a Windows 8 (or 8.1) machine. I mentioned that in the middle of my OP, but it's likely not visible enough. I'll update it to mention it won't work as-is on Windows 7 :mrgreen:

Edit: crap, I'm no longer allowed to edit my OP :crazy:

It should be possible to apply the same modifications using dnSpy: the only difference is WMC for Windows 7 is compiled against .NET Framework 2.0 while WMC for WIndows 8 targets .NET Framework 4.0 (which means a lot more APIs are available). That said, I don't think I used any of these new APIs in my mods so it should be trivial.
IT Troll wrote: Tue Jan 23, 2024 10:24 pm Once cosmetic annoyance I would love to see patched is the fact Media Center applies a blue tint to inactive third-party tiles on the home screen menu strips. With theme utilities you can change almost everything, but that blue tint is hard coded.
Just to be sure, are you referring to this blue tint, visible in the first screen but removed in the second one (I used a completely black background to make that more visible)?
WMC 1.png
WMC 2.png

User avatar
IT Troll

Posts: 1193
Joined: Sun Nov 27, 2011 9:42 am
Location: Edinburgh, UK

HTPC Specs: Show details

#10

Post by IT Troll » Wed Jan 24, 2024 10:31 pm

Kevin Chalet wrote: Wed Jan 24, 2024 9:23 am
Just to be sure, are you referring to this blue tint, visible in the first screen but removed in the second one (I used a completely black background to make that more visible)?
No quite. It is when you add a custom row with custom icons (e.g. Recorded TV HD). The inactive icons are given a blue tint.
I’ll post a screenshot tomorrow if that’s not clear.
Are you a Recorded TV HD user or want to give it a try? Check out the new community-made update; Recorded TV HD v2.1.1

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#11

Post by Kevin Chalet » Thu Jan 25, 2024 10:35 am

IT Troll wrote: Wed Jan 24, 2024 10:31 pm I’ll post a screenshot tomorrow if that’s not clear.
Yeah, please post a screenshot :oops:

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#12

Post by Kevin Chalet » Thu Jan 25, 2024 11:59 am

New 1.1.0 release:

ehshell.dll and Microsoft.MediaCenter.UI.dll patches:

Option to enable watching live/recorded TV via RDP:

1.1.0 reverts the changes introduced in Capabilities._IsUISessionRemoted and SystemInformation.RemoteSession a while ago by Graznok to allow watching live/recorded TV via RDP (and disable extenders support + prevent fullscreen from working via RDP at the same time). See https://forums.mydigitallife.net/thread ... st-1206327 for more information.

These changes are replaced by a unique hook in SystemInformation.RemoteSession that allows dynamically controlling how things work:

Code: Select all

using System;
using Microsoft.MediaCenter.UI;
using Microsoft.Win32;

namespace Microsoft.MediaCenter.Interop
{
    // Token: 0x02000427 RID: 1063
    internal static partial class SystemInformation
    {
        // Token: 0x170008F9 RID: 2297
        // (get) Token: 0x06002792 RID: 10130 RVA: 0x00070945 File Offset: 0x0006EB45
        public static bool RemoteSession
        {
            get
            {
                var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Settings\\DisplayService");
                if (key is not null && key.GetValue("DisableRemoteSessionSupport") is 1)
                {
                    return false;
                }

                return Win32Api.GetSystemMetrics(4096) != 0;
            }
        }
    }
}
By default, live TV via RDP will no longer be possible (which matches the default WMC implementation and the behavior seen in Gary's MSI installer, that doesn't support that).

To support live TV via RDP (which also prevents fullscreen via RDP):

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Settings\DisplayService]
"DisableRemoteSessionSupport"=dword:00000001
To revert back to the default WMC behavior:

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Settings\DisplayService]
"DisableRemoteSessionSupport"=dword:00000000
Attachments
WMC mini-mods 1.1.0.zip
(3.22 MiB) Downloaded 68 times

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#13

Post by Kevin Chalet » Thu Jan 25, 2024 5:20 pm

IT Troll wrote: Wed Jan 24, 2024 10:31 pm
Kevin Chalet wrote: Wed Jan 24, 2024 9:23 am
Just to be sure, are you referring to this blue tint, visible in the first screen but removed in the second one (I used a completely black background to make that more visible)?
No quite. It is when you add a custom row with custom icons (e.g. Recorded TV HD). The inactive icons are given a blue tint.
I’ll post a screenshot tomorrow if that’s not clear.
I think I got it: do you mean this?
WMC 3.png
If so, that blue tint indeed only applies to "quick links" and not regular links, which is why I wasn't seeing it on my test VM that doesn't have any third-party plugin installed.
I'll investigate, but it should be fairly easy to fix.

User avatar
IT Troll

Posts: 1193
Joined: Sun Nov 27, 2011 9:42 am
Location: Edinburgh, UK

HTPC Specs: Show details

#14

Post by IT Troll » Thu Jan 25, 2024 11:06 pm

Kevin Chalet wrote: Thu Jan 25, 2024 5:20 pm I think I got it: do you mean this?
Yep, that is exactly it. It is odd that Media Center has code which adds this blue tint to these icons.
It would be great if you can mod this. The blue really grates with my monochrome theme.
Are you a Recorded TV HD user or want to give it a try? Check out the new community-made update; Recorded TV HD v2.1.1

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#15

Post by Kevin Chalet » Fri Jan 26, 2024 12:37 am

IT Troll wrote: Thu Jan 25, 2024 11:06 pm It would be great if you can mod this. The blue really grates with my monochrome theme.
It took a little bit of time, but I found it :mrgreen:

New 1.2.0 release:

ehshell.dll patches:

Option to disable the grayscale/blue tint filters applied to quick links:

This option allows removing the blue tint filter enforced by WMC for all the quick link images present in the start menu:
WMC 4.png
For that, I had to tweak QuickLink.ImageFilterRequirements to avoid adding these filters if DisableQuickLinkImageFilters was set to 1.
I applied the same logic to PackageQuickLink.LoadFilteredImage(), tho' these types of links should be quite rare.

Code: Select all

using System;
using ServiceBus.UIFramework;
using Microsoft.MediaCenter.Shell;
using Microsoft.MediaCenter.UI;
using Microsoft.Win32;

namespace MediaCenter.Home
{
    // Token: 0x0200050E RID: 1294
    internal abstract partial class QuickLink : StartMenuQuickLink, IThumbnailCommand, ICommand, IModelItem, IPropertyObject, IModelItemOwner
    {
        // Token: 0x17000A4C RID: 2636
        // (get) Token: 0x06002C68 RID: 11368 RVA: 0x000EFC84 File Offset: 0x000EDE84
        public ImageRequirements ImageFilterRequirements
        {
            get
            {
                if (this._imgFilterReq == null)
                {
                    this._imgFilterReq = new ImageRequirements();

                    using var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Start Menu");
                    if (!UCPUtility.CheckBoolRegVal(key, "DisableQuickLinkImageFilters"))
                    {
                        ColorFilterSet colorFilterSet = new ColorFilterSet();
                        colorFilterSet.Values.Add(new GrayscaleFilter());
                        colorFilterSet.Values.Add(new TintFilter(-0.3f, 0.1f, 0.5f));
                        this._imgFilterReq.nMask |= ImageRequirements.Fields.FilterSet;
                        this._imgFilterReq.cfsFilterSet = colorFilterSet;
                    }
                }
                return this._imgFilterReq;
            }
        }
    }
}

Code: Select all

using System;
using ServiceBus.UIFramework;
using Microsoft.MediaCenter.UI;
using Microsoft.MediaCenter.Utility;
using Microsoft.Win32;
using Image = Microsoft.MediaCenter.UI.Image;

namespace MediaCenter.Home
{
    // Token: 0x0200050F RID: 1295
    internal partial class PackageQuickLink : QuickLink
    {
        // Token: 0x06002C7C RID: 11388 RVA: 0x000EFE0C File Offset: 0x000EE00C
        private Image LoadFilteredImage(string url)
        {
            ImageRequirements imageRequirements = new ImageRequirements();
            
            using var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center\\Start Menu");
            if (!UCPUtility.CheckBoolRegVal(key, "DisableQuickLinkImageFilters"))
            {
                ColorFilterSet colorFilterSet = new ColorFilterSet();
                colorFilterSet.Values.Add(new GrayscaleFilter());
                colorFilterSet.Values.Add(new TintFilter(-0.3f, 0.1f, 0.5f));
                imageRequirements.nMask |= ImageRequirements.Fields.FilterSet;
                imageRequirements.cfsFilterSet = colorFilterSet;
            }

            return this.LoadImage(url, imageRequirements);
        }
    }
}
To disable the grayscale/tint filters:

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Start Menu]
"DisableQuickLinkImageFilters"=dword:00000001
To revert back to the default WMC behavior:

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Start Menu]
"DisableQuickLinkImageFilters"=dword:00000000
Attachments
WMC mini-mods 1.2.0.zip
(3.22 MiB) Downloaded 63 times

User avatar
IT Troll

Posts: 1193
Joined: Sun Nov 27, 2011 9:42 am
Location: Edinburgh, UK

HTPC Specs: Show details

#16

Post by IT Troll » Fri Jan 26, 2024 3:29 pm

Kevin Chalet wrote: Fri Jan 26, 2024 12:37 am It took a little bit of time, but I found it :mrgreen:
Amazing, what a hero! :thumbup:
This has bugged me for years. Installed and working fine on Windows 8.1.

Before:
Before.jpg

After:
After.jpg

It is worth noting that the installer doesn't backup the original files before replacing them, so Windows 8 folks may wish to keep a copy somewhere safe.
Are you a Recorded TV HD user or want to give it a try? Check out the new community-made update; Recorded TV HD v2.1.1

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#17

Post by Kevin Chalet » Fri Jan 26, 2024 5:24 pm

IT Troll wrote: Fri Jan 26, 2024 3:29 pm Amazing, what a hero! :thumbup:
Haha, thanks! Glad to hear it's working :mrgreen:
IT Troll wrote: Fri Jan 26, 2024 3:29 pm This has bugged me for years. Installed and working fine on Windows 8.1.
Ah yeah, I can totally see why... that blueish tint definitely doesn't look great with that black theme :lol:

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#18

Post by Kevin Chalet » Fri Jan 26, 2024 6:37 pm

New 1.3.0 release:

ehshell.dll patches:

Option to override the default sort attribute used to sort automatic album playlists:

By default, WMC (just like Windows Media Player) sorts album playlists using the WM/TrackNumber attribute. Sadly, this attribute doesn't include the disc number, so when you have multi-CD albums, the order is always completely wrong: you get the first track of each CD first, then the second one, etc.

In WMP, it's possible to use Windows Media Player Plus! to work around this stupid limitation, but it's limited to 500 tracks for performance reasons.
In WMC, for those who have adopted a file hierarchy that contains the disc number and track number (e.g Music\Chris Rea\The Road To Hell\Disc 1\02 - The Road To Hell (Part II).m4a), it's possible to work around this limitation by sorting the album using the file name.

This new release makes that possible by introducing a new AlbumPlaylistSortAttribute registry hook that takes one of the values listed here: https://learn.microsoft.com/en-us/windo ... -reference.
It can be set to SourceURL for those who want to sort the playlist based on the file name, or pretty much anything else (e.g Title if you want the tracks to be listed alphabetically).

Code: Select all

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Drawing;
using ehiUserXp;
using ehiwmp;
using MediaCenter.SyncDevice;
using Microsoft.MediaCenter.Playback;
using Microsoft.MediaCenter.Shell;
using Microsoft.MediaCenter.UI;
using Microsoft.Win32;
using ServiceBus.UIFramework;

namespace EHMedia
{
    // Token: 0x02000A50 RID: 2640
    internal partial class EHMediaControl : NativeUIObj, IEHMediaControl, ITransportControl, IPropertyObject
    {
        // Token: 0x06005C81 RID: 23681 RVA: 0x00185158 File Offset: 0x00183358
        public EHPlaylist2 GetAlbumPlaylist(WMPQueryWrapper constraints, string strAlbumId)
        {
            constraints.AddCondition(EHMediaLiterals.s_strAlbumIDAttribute, QueryOperators.QOEquals, strAlbumId);
            EHPlaylist2 playlistByQuery = this.GetPlaylistByQuery(constraints, constraints.Library);
            if (playlistByQuery != null)
            {
                using var key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Media Center");
                if (key is null || key.GetValue("AlbumPlaylistSortAttribute") is not string attribute)
                {
                    attribute = EHMediaLiterals.s_strTrackNumberAttribute;
                }
                playlistByQuery.SortPlaylist(attribute);
                playlistByQuery.AlbumId = strAlbumId;
            }
            return playlistByQuery;
        }
    }
}

Code: Select all

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center]
"AlbumPlaylistSortAttribute"="SourceURL"
Attachments
WMC mini-mods 1.3.0.zip
(3.22 MiB) Downloaded 53 times

User avatar
IT Troll

Posts: 1193
Joined: Sun Nov 27, 2011 9:42 am
Location: Edinburgh, UK

HTPC Specs: Show details

#19

Post by IT Troll » Fri Jan 26, 2024 11:30 pm

I share my music library between iTunes and Media Center. I worked around this issue by changing the track numbers so that they run consecutively across the discs.
Are you a Recorded TV HD user or want to give it a try? Check out the new community-made update; Recorded TV HD v2.1.1

Kevin Chalet

Posts: 147
Joined: Mon Oct 08, 2018 12:00 pm
Location:

HTPC Specs: Show details

#20

Post by Kevin Chalet » Sat Jan 27, 2024 12:03 am

IT Troll wrote: Fri Jan 26, 2024 11:30 pm I share my music library between iTunes and Media Center. I worked around this issue by changing the track numbers so that they run consecutively across the discs.
Ah yeah, that works too! (OCD me wouldn't be very happy with the fake track numbers tho': they are not visible in WMC, but they are in Music on iOS :mrgreen:)

I was a fan of iTunes, but the "recent" versions are insanely slow even on very beefy hardware (too bad they abandoned iTunes for Windows, it was a nice piece of software)
I now exclusively use WMC for all my audio needs, it's blazingly fast and straight to the point... even on machines not meant to be used with a remote.

I re-ripped my entire CD collection last year and moved from good old MP3 320kbps to ALAC. It's insane to be able to play ALAC files natively in WMC/WMP without having to tweak them :mrgreen:

Post Reply