Functions/GenXdev.Console.Vlc/Open-VlcMediaPlayer.ps1

<##############################################################################
Part of PowerShell module : GenXdev.Console.Vlc
Original cmdlet filename : Open-VlcMediaPlayer.ps1
Original author : René Vaessen / GenXdev
Version : 3.24.2026
################################################################################
Copyright (c) René Vaessen / GenXdev
 
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
 
    http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
################################################################################>

###############################################################################
<#
.SYNOPSIS
Launches and controls VLC Media Player with extensive configuration options.
 
.DESCRIPTION
This function provides a comprehensive interface to launch and control VLC
Media Player with support for window positioning, monitor selection, playback
settings, audio and video filters, subtitle handling, multiple language
support, network proxy settings, and advanced performance options. The
function can automatically install VLC if not present and provides extensive
customization for media playbook scenarios. It integrates seamlessly with the
GenXdev window management system and supports keyboard input automation through
the Send-Key functionality.
 
.PARAMETER Path
The media file(s) or URL(s) to open in VLC. Supports local files, network
 
.PARAMETER Width
The initial width of the VLC window in pixels. Used for precise window sizing.
 
.PARAMETER Height
The initial height of the VLC window in pixels. Used for precise window sizing.
 
.PARAMETER X
The initial X position of the VLC window on the screen in pixels.
 
.PARAMETER Y
The initial Y position of the VLC window on the screen in pixels.
 
.PARAMETER KeysToSend
Keystrokes to send to the VLC Player Window after opening. Uses the same
syntax as the GenXdev.Windows\Send-Key function for automation purposes.
 
.PARAMETER SendKeyEscape
Escape control characters and modifiers when sending keys to VLC to ensure
literal key interpretation.
 
.PARAMETER SendKeyUseShiftEnter
Use Shift+Enter instead of Enter when sending keys to VLC for line breaks.
 
.PARAMETER SendKeyDelayMilliSeconds
Delay between different input strings in milliseconds when sending keys to
ensure reliable delivery.
 
.PARAMETER SendKeyHoldKeyboardFocus
Hold keyboard focus on the VLC window after sending keys instead of returning
focus to PowerShell.
 
.PARAMETER Monitor
The monitor to use for VLC display. 0 = default monitor, -1 = discard
positioning, >0 = specific monitor number.
 
.PARAMETER AspectRatio
Source aspect ratio for video display to ensure correct proportions.
 
.PARAMETER Crop
Video cropping settings to adjust the visible video area.
 
.PARAMETER SubtitleFile
Path to subtitle file to use with the media for caption display.
 
.PARAMETER SubtitleScale
Subtitles text scaling factor percentage for readability adjustment.
 
.PARAMETER SubtitleLanguage
Subtitle language preference for multi-language content selection.
 
.PARAMETER AudioLanguage
Audio language preference for multi-language content selection.
 
.PARAMETER PreferredAudioLanguage
Preferred audio language for multi-language content when multiple tracks exist.
 
.PARAMETER HttpProxy
HTTP proxy server for network streams when behind corporate firewalls.
 
.PARAMETER HttpProxyPassword
HTTP proxy password for authentication when required by proxy server.
 
.PARAMETER VerbosityLevel
Verbosity level for VLC output to control logging detail.
 
.PARAMETER SubdirectoryBehavior
How to handle subdirectories in playlists for folder-based media organization.
 
.PARAMETER IgnoredExtensions
File extensions to ignore when building playlists to filter unwanted files.
 
.PARAMETER VLCPath
Custom path to VLC executable when installed in non-standard location.
 
.PARAMETER ReplayGainMode
Replay gain mode for audio normalization to maintain consistent volume levels.
 
.PARAMETER ReplayGainPreamp
Replay gain preamp value in decibels for volume adjustment.
 
.PARAMETER ForceDolbySurround
Force detection of Dolby Surround audio for enhanced audio processing.
 
.PARAMETER AudioFilters
Audio filters to apply during playback for sound enhancement.
 
.PARAMETER Visualization
Audio visualization type to display for audio-only content.
 
.PARAMETER Deinterlace
Deinterlace video content to improve quality of interlaced video.
 
.PARAMETER DeinterlaceMode
Deinterlace algorithm to use for optimal video quality processing.
 
.PARAMETER VideoFilters
Video filters to apply during playback for visual enhancement.
 
.PARAMETER VideoFilterModules
Video filter modules to load for advanced video processing.
 
.PARAMETER Modules
Additional modules to load for extended VLC functionality.
 
.PARAMETER AudioFilterModules
Audio filter modules to load for advanced audio processing.
 
.PARAMETER AudioVisualization
Audio visualization mode for visual representation of audio content.
 
.PARAMETER PreferredSubtitleLanguage
Preferred subtitle language for automatic subtitle selection.
 
.PARAMETER IgnoredFileExtensions
File extensions to ignore during media file processing.
 
.PARAMETER Arguments
Additional command-line arguments to pass to VLC for custom configuration.
 
.PARAMETER NoBorders
Removes window borders for a cleaner, distraction-free viewing experience.
 
.PARAMETER Left
Places VLC window on left side of screen for side-by-side arrangements.
 
.PARAMETER Right
Places VLC window on right side of screen for side-by-side arrangements.
 
.PARAMETER Top
Places VLC window on top side of screen for vertical arrangements.
 
.PARAMETER Bottom
Places VLC window on bottom side of screen for vertical arrangements.
 
.PARAMETER Centered
Centers the VLC window on screen for optimal viewing position.
 
.PARAMETER Fullscreen
Maximizes the VLC window to fullscreen for immersive viewing.
 
.PARAMETER PassThru
Returns the window helper object for further manipulation and control.
 
.PARAMETER AlwaysOnTop
Keeps the VLC window always on top of other windows for persistent visibility.
 
.PARAMETER Random
Play files randomly forever in shuffle mode for varied playback order.
 
.PARAMETER Loop
Repeat all files in the playlist continuously for extended viewing.
 
.PARAMETER Repeat
Repeat current item continuously for focused content consumption.
 
.PARAMETER StartPaused
Start playback in paused state for manual playback control.
 
.PARAMETER PlayAndExit
Play media and exit VLC when finished for automated batch processing.
 
.PARAMETER DisableAudio
Disable audio output completely for silent video playback.
 
.PARAMETER DisableSubtitles
Disable all subtitles for clean video display without captions.
 
.PARAMETER AutoScale
Enable automatic video scaling for optimal display size adjustment.
 
.PARAMETER HighPriority
Increase the priority of the VLC process for better performance.
 
.PARAMETER EnableTimeStretch
Enable time stretching audio during playback for speed adjustments.
 
.PARAMETER NewWindow
Open new VLC mediaplayer instance instead of reusing existing windows.
 
.PARAMETER EnableWallpaperMode
Enable video wallpaper mode for desktop background video display.
 
.PARAMETER EnableAudioTimeStretch
Enable audio time stretching for playback speed modifications.
 
.PARAMETER Close
Close the VLC media player window and terminate the process.
 
.PARAMETER SideBySide
Will either set the window fullscreen on a different monitor than PowerShell,
or side by side with PowerShell on the same monitor for workflow optimization.
 
.PARAMETER FocusWindow
Focus the VLC window after opening for immediate interaction readiness.
 
.PARAMETER SetForeground
Set the VLC window to foreground after opening for visibility assurance.
 
.PARAMETER Maximize
Maximize the window after positioning
 
.PARAMETER SetRestored
Restore the window to normal state after positioning
 
.PARAMETER RestoreFocus
Restore PowerShell window focus after opening VLC for continued workflow.
 
.PARAMETER SessionOnly
Use alternative settings stored in session for AI preferences during current
session only.
 
.PARAMETER ClearSession
Clear alternative settings stored in session for AI preferences to reset
configuration.
 
.PARAMETER SkipSession
Store settings only in persistent preferences without affecting session to
maintain separation.
 
.EXAMPLE
Open-VlcMediaPlayer -Path "video.mp4" -Fullscreen -Monitor 0
Opens a video file in fullscreen mode on the primary monitor for immersive
viewing experience.
 
.EXAMPLE
vlc "video.mp4" -fs -m 0
Short form using aliases to open video fullscreen on monitor 0 with minimal
typing required.
 
.EXAMPLE
Open-VlcMediaPlayer -Path "movie.mkv" -SubtitleFile "movie.srt" -AudioLanguage "English"
Opens a movie with external subtitles and specific audio language for
enhanced viewing with captions.
#>

###############################################################################
function Open-VlcMediaPlayer {

    [CmdletBinding()]
    [Alias('vlc')]

    param(
        ###########################################################################
        [Parameter(
            Position = 0,
            Mandatory = $false,
            HelpMessage = 'The media file(s) or URL(s) to open in VLC'
        )]
        [string[]]$Path,
        ###########################################################################
        [Parameter(
            Position = 1,
            Mandatory = $false,
            HelpMessage = 'The initial width of the window'
        )]
        [int] $Width = -1,
        ###########################################################################
        [Parameter(
            Position = 2,
            Mandatory = $false,
            HelpMessage = 'The initial height of the window'
        )]
        [int] $Height = -1,
        ###########################################################################
        [Parameter(
            Position = 3,
            Mandatory = $false,
            HelpMessage = 'The initial X position of the window'
        )]
        [int] $X = -999999,
        ###########################################################################
        [Parameter(
            Position = 4,
            Mandatory = $false,
            HelpMessage = 'The initial Y position of the window'
        )]
        [int] $Y = -999999,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage = ('Keystrokes to send to the VLC Player Window, ' +
                'see documentation for cmdlet GenXdev.Windows\Send-Key')
        )]
        [string[]] $KeysToSend = @(),
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Escape control characters and modifiers when sending keys to VLC'
        )]
        [Alias('Escape')]
        [switch] $SendKeyEscape,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Use Shift+Enter instead of Enter when sending keys to VLC'
        )]
        [Alias('UseShiftEnter')]
        [switch] $SendKeyUseShiftEnter,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Delay between different input strings in milliseconds when sending keys to VLC'
        )]
        [ValidateRange(0, [int]::MaxValue)]
        [Alias('DelayMilliSeconds')]
        [int] $SendKeyDelayMilliSeconds = 50,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Hold keyboard focus on the VLC window after sending keys'
        )]
        [Alias('HoldKeyboardFocus')]
        [switch] $SendKeyHoldKeyboardFocus,
        ###########################################################################
        [Alias('m', 'mon')]
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'The monitor to use, 0 = default, -1 is discard'
        )]
        [int] $Monitor = -1,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Source aspect ratio'
        )]
        [string]$AspectRatio,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Video cropping'
        )]
        [string]$Crop,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Use subtitle file'
        )]
        [string]$SubtitleFile,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Subtitles text scaling factor'
        )]
        [ValidateRange(10, 500)]
        [int]$SubtitleScale,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Subtitle language'
        )]
        [ValidateSet(
            'Afrikaans', 'Akan', 'Albanian', 'Amharic', 'Arabic', 'Armenian', 'Azerbaijani', 'Basque', 'Belarusian',
            'Bemba', 'Bengali', 'Bihari', 'Bork, bork, bork!', 'Bosnian', 'Breton', 'Bulgarian', 'Cambodian',
            'Catalan', 'Cherokee', 'Chichewa', 'Chinese (Simplified)', 'Chinese (Traditional)', 'Corsican',
            'Croatian', 'Czech', 'Danish', 'Dutch', 'Elmer Fudd', 'English', 'Esperanto', 'Estonian', 'Ewe',
            'Faroese', 'Filipino', 'Finnish', 'French', 'Frisian', 'Ga', 'Galician', 'Georgian', 'German', 'Greek',
            'Guarani', 'Gujarati', 'Hacker', 'Haitian Creole', 'Hausa', 'Hawaiian', 'Hebrew', 'Hindi', 'Hungarian',
            'Icelandic', 'Igbo', 'Indonesian', 'Interlingua', 'Irish', 'Italian', 'Japanese', 'Javanese', 'Kannada',
            'Kazakh', 'Kinyarwanda', 'Kirundi', 'Klingon', 'Kongo', 'Korean', 'Krio (Sierra Leone)', 'Kurdish',
            'Kurdish (Soranî)', 'Kyrgyz', 'Laothian', 'Latin', 'Latvian', 'Lingala', 'Lithuanian', 'Lozi', 'Luganda',
            'Luo', 'Macedonian', 'Malagasy', 'Malay', 'Malayalam', 'Maltese', 'Maori', 'Marathi', 'Mauritian Creole',
            'Moldavian', 'Mongolian', 'Montenegrin', 'Nepali', 'Nigerian Pidgin', 'Northern Sotho', 'Norwegian',
            'Norwegian (Nynorsk)', 'Occitan', 'Oriya', 'Oromo', 'Pashto', 'Persian', 'Pirate', 'Polish',
            'Portuguese (Brazil)', 'Portuguese (Portugal)', 'Punjabi', 'Quechua', 'Romanian', 'Romansh', 'Runyakitara',
            'Russian', 'Scots Gaelic', 'Serbian', 'Serbo-Croatian', 'Sesotho', 'Setswana', 'Seychellois Creole',
            'Shona', 'Sindhi', 'Sinhalese', 'Slovak', 'Slovenian', 'Somali', 'Spanish', 'Spanish (Latin American)',
            'Sundanese', 'Swahili', 'Swedish', 'Tajik', 'Tamil', 'Tatar', 'Telugu', 'Thai', 'Tigrinya', 'Tonga',
            'Tshiluba', 'Tumbuka', 'Turkish', 'Turkmen', 'Twi', 'Uighur', 'Ukrainian', 'Urdu', 'Uzbek', 'Vietnamese',
            'Welsh', 'Wolof', 'Xhosa', 'Yiddish', 'Yoruba', 'Zulu')]
        [string]$SubtitleLanguage,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Audio language'
        )]
        [ValidateSet(
            'Afrikaans', 'Akan', 'Albanian', 'Amharic', 'Arabic', 'Armenian', 'Azerbaijani', 'Basque', 'Belarusian',
            'Bemba', 'Bengali', 'Bihari', 'Bork, bork, bork!', 'Bosnian', 'Breton', 'Bulgarian', 'Cambodian',
            'Catalan', 'Cherokee', 'Chichewa', 'Chinese (Simplified)', 'Chinese (Traditional)', 'Corsican',
            'Croatian', 'Czech', 'Danish', 'Dutch', 'Elmer Fudd', 'English', 'Esperanto', 'Estonian', 'Ewe',
            'Faroese', 'Filipino', 'Finnish', 'French', 'Frisian', 'Ga', 'Galician', 'Georgian', 'German', 'Greek',
            'Guarani', 'Gujarati', 'Hacker', 'Haitian Creole', 'Hausa', 'Hawaiian', 'Hebrew', 'Hindi', 'Hungarian',
            'Icelandic', 'Igbo', 'Indonesian', 'Interlingua', 'Irish', 'Italian', 'Japanese', 'Javanese', 'Kannada',
            'Kazakh', 'Kinyarwanda', 'Kirundi', 'Klingon', 'Kongo', 'Korean', 'Krio (Sierra Leone)', 'Kurdish',
            'Kurdish (Soranî)', 'Kyrgyz', 'Laothian', 'Latin', 'Latvian', 'Lingala', 'Lithuanian', 'Lozi', 'Luganda',
            'Luo', 'Macedonian', 'Malagasy', 'Malay', 'Malayalam', 'Maltese', 'Maori', 'Marathi', 'Mauritian Creole',
            'Moldavian', 'Mongolian', 'Montenegrin', 'Nepali', 'Nigerian Pidgin', 'Northern Sotho', 'Norwegian',
            'Norwegian (Nynorsk)', 'Occitan', 'Oriya', 'Oromo', 'Pashto', 'Persian', 'Pirate', 'Polish',
            'Portuguese (Brazil)', 'Portuguese (Portugal)', 'Punjabi', 'Quechua', 'Romanian', 'Romansh', 'Runyakitara',
            'Russian', 'Scots Gaelic', 'Serbian', 'Serbo-Croatian', 'Sesotho', 'Setswana', 'Seychellois Creole',
            'Shona', 'Sindhi', 'Sinhalese', 'Slovak', 'Slovenian', 'Somali', 'Spanish', 'Spanish (Latin American)',
            'Sundanese', 'Swahili', 'Swedish', 'Tajik', 'Tamil', 'Tatar', 'Telugu', 'Thai', 'Tigrinya', 'Tonga',
            'Tshiluba', 'Tumbuka', 'Turkish', 'Turkmen', 'Twi', 'Uighur', 'Ukrainian', 'Urdu', 'Uzbek', 'Vietnamese',
            'Welsh', 'Wolof', 'Xhosa', 'Yiddish', 'Yoruba', 'Zulu')]
        [string]$AudioLanguage,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Preferred audio language'
        )]
        [ValidateSet(
            'Afrikaans', 'Akan', 'Albanian', 'Amharic', 'Arabic', 'Armenian', 'Azerbaijani', 'Basque', 'Belarusian',
            'Bemba', 'Bengali', 'Bihari', 'Bork, bork, bork!', 'Bosnian', 'Breton', 'Bulgarian', 'Cambodian',
            'Catalan', 'Cherokee', 'Chichewa', 'Chinese (Simplified)', 'Chinese (Traditional)', 'Corsican',
            'Croatian', 'Czech', 'Danish', 'Dutch', 'Elmer Fudd', 'English', 'Esperanto', 'Estonian', 'Ewe',
            'Faroese', 'Filipino', 'Finnish', 'French', 'Frisian', 'Ga', 'Galician', 'Georgian', 'German', 'Greek',
            'Guarani', 'Gujarati', 'Hacker', 'Haitian Creole', 'Hausa', 'Hawaiian', 'Hebrew', 'Hindi', 'Hungarian',
            'Icelandic', 'Igbo', 'Indonesian', 'Interlingua', 'Irish', 'Italian', 'Japanese', 'Javanese', 'Kannada',
            'Kazakh', 'Kinyarwanda', 'Kirundi', 'Klingon', 'Kongo', 'Korean', 'Krio (Sierra Leone)', 'Kurdish',
            'Kurdish (Soranî)', 'Kyrgyz', 'Laothian', 'Latin', 'Latvian', 'Lingala', 'Lithuanian', 'Lozi', 'Luganda',
            'Luo', 'Macedonian', 'Malagasy', 'Malay', 'Malayalam', 'Maltese', 'Maori', 'Marathi', 'Mauritian Creole',
            'Moldavian', 'Mongolian', 'Montenegrin', 'Nepali', 'Nigerian Pidgin', 'Northern Sotho', 'Norwegian',
            'Norwegian (Nynorsk)', 'Occitan', 'Oriya', 'Oromo', 'Pashto', 'Persian', 'Pirate', 'Polish',
            'Portuguese (Brazil)', 'Portuguese (Portugal)', 'Punjabi', 'Quechua', 'Romanian', 'Romansh', 'Runyakitara',
            'Russian', 'Scots Gaelic', 'Serbian', 'Serbo-Croatian', 'Sesotho', 'Setswana', 'Seychellois Creole',
            'Shona', 'Sindhi', 'Sinhalese', 'Slovak', 'Slovenian', 'Somali', 'Spanish', 'Spanish (Latin American)',
            'Sundanese', 'Swahili', 'Swedish', 'Tajik', 'Tamil', 'Tatar', 'Telugu', 'Thai', 'Tigrinya', 'Tonga',
            'Tshiluba', 'Tumbuka', 'Turkish', 'Turkmen', 'Twi', 'Uighur', 'Ukrainian', 'Urdu', 'Uzbek', 'Vietnamese',
            'Welsh', 'Wolof', 'Xhosa', 'Yiddish', 'Yoruba', 'Zulu')]
        [string]$PreferredAudioLanguage,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'HTTP proxy'
        )]
        [string]$HttpProxy,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'HTTP proxy password'
        )]
        [string]$HttpProxyPassword,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Verbosity level'
        )]
        [ValidateRange(0, 2)]
        [int]$VerbosityLevel,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Subdirectory behavior'
        )]
        [ValidateSet('None', 'Collapse', 'Expand')]
        [string]$SubdirectoryBehavior,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Ignored extensions'
        )]
        [string]$IgnoredExtensions,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Path to VLC executable'
        )]
        [string]$VLCPath = "${env:ProgramFiles}\VideoLAN\VLC\vlc.exe",
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Replay gain mode'
        )]
        [ValidateSet('None', 'Track', 'Album')]
        [string]$ReplayGainMode,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Replay gain preamp'
        )]
        [ValidateRange(-20.0, 20.0)]
        [float]$ReplayGainPreamp,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Force detection of Dolby Surround'
        )]
        [ValidateSet('Auto', 'On', 'Off')]
        [string]$ForceDolbySurround,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Audio filters'
        )]
        [string[]]$AudioFilters,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Audio visualizations'
        )]
        [ValidateSet('None', 'Goom', 'ProjectM', 'Visual', 'GLSpectrum')]
        [string]$Visualization,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Deinterlace'
        )]
        [ValidateSet('Off', 'Automatic', 'On')]
        [string]$Deinterlace,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Deinterlace mode'
        )]
        [ValidateSet('Auto', 'Discard', 'Blend', 'Mean', 'Bob', 'Linear', 'X', 'Yadif', 'Yadif2x', 'Phosphor', 'IVTC')]
        [string]$DeinterlaceMode,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Video filter module'
        )]
        [string[]]$VideoFilters,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Video filter modules'
        )]
        [string[]]$VideoFilterModules,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Modules'
        )]
        [string[]]$Modules,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Audio filter modules'
        )]
        [string[]]$AudioFilterModules,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Audio visualization mode'
        )]
        [ValidateSet('None', 'Goom', 'ProjectM', 'Visual', 'GLSpectrum')]
        [string]$AudioVisualization,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Preferred subtitle language'
        )]
        [string]$PreferredSubtitleLanguage,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Ignored file extensions'
        )]
        [string]$IgnoredFileExtensions,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Additional arguments'
        )]
        [string]$Arguments,
        ###########################################################################
        [Alias('nb')]
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Removes the borders of the window'
        )]
        [switch] $NoBorders,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Place window on the left side of the screen'
        )]
        [switch] $Left,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Place window on the right side of the screen'
        )]
        [switch] $Right,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Place window on the top side of the screen'
        )]
        [switch] $Top,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Place window on the bottom side of the screen'
        )]
        [switch] $Bottom,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Place window in the center of the screen'
        )]
        [switch] $Centered,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Sends F11 to the window'
        )]
        [Alias('fs')]
        [switch]$FullScreen,

        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Returns the window helper for each process'
        )]
        [Alias('pt')]
        [switch]$PassThru,

        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Always on top'
        )]
        [switch]$AlwaysOnTop,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Play files randomly forever'
        )]
        [Alias('Shuffle')]
        [switch]$Random,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Repeat all'
        )]
        [switch]$Loop,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Repeat current item'
        )]
        [switch]$Repeat,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Start paused'
        )]
        [switch]$StartPaused,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Play and exit'
        )]
        [switch]$PlayAndExit,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Disable audio'
        )]
        [switch]$DisableAudio,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Disable subtitles'
        )]
        [switch]$DisableSubtitles,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Video Auto Scaling'
        )]
        [switch]$AutoScale,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Increase the priority of the process'
        )]
        [switch]$HighPriority,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Enable time stretching audio'
        )]
        [switch]$EnableTimeStretch,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Open new VLC mediaplayer instance'
        )]
        [switch] $NewWindow,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Enable video wallpaper mode'
        )]
        [switch]$EnableWallpaperMode,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Enable audio time stretching'
        )]
        [switch]$EnableAudioTimeStretch,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Close the VLC media player window'
        )]
        [switch] $Close,
        ###########################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Will either set the window fullscreen on a different monitor than Powershell, or ' +
            'side by side with Powershell on the same monitor'
        )]
        [Alias('sbs')]
        [switch]$SideBySide,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Focus the VLC window after opening'
        )]
        [Alias('fw', 'focus')]
        [switch] $FocusWindow,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Set the VLC window to foreground after opening'
        )]
        [Alias('fg')]
        [switch] $SetForeground,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Maximize the window'
        )]
        [switch] $Maximize,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Restore PowerShell window focus after opening VLC'
        )]
        [Alias('rf', 'bg')]
        [switch]$RestoreFocus,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Use alternative settings stored in session for AI preferences'
        )]
        [switch] $SessionOnly,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Clear alternative settings stored in session for AI preferences'
        )]
        [switch] $ClearSession,
        ###############################################################################
        [Parameter(
            Mandatory = $false,
            HelpMessage = 'Store settings only in persistent preferences without affecting session'
        )]
        [Alias('FromPreferences')]
        [switch] $SkipSession
        ###########################################################################
    )

    begin {

        # exit early if only closing vlc windows
        if ($Close) {

            Microsoft.PowerShell.Utility\Write-Verbose 'Closing VLC windows'

            # stop all vlc processes
            Microsoft.PowerShell.Management\Get-Process vlc `
                -ErrorAction SilentlyContinue |
                Microsoft.PowerShell.Management\Stop-Process -Force

            return
        }

        $positioningParams = @(
            "Monitor",
            "NoBorders",
            "Width",
            "Height",
            "X",
            "Y",
            "Left",
            "Right",
            "Top",
            "Bottom",
            "Centered",
            "Fullscreen",
            "SideBySide",
            "FocusWindow",
            # "RestoreFocus",
            "SetForeground",
            "Minimize",
            "Maximize",
            "KeysToSend",
            "SendKeyEscape",
            "SendKeyHoldKeyboardFocus",
            "SendKeyUseShiftEnter",
            "SendKeyDelayMilliSeconds"
        );

        $haveOnlyPositioningParams = $true;
        foreach ($param in $PSBoundParameters.Keys) {
            if ($positioningParams -notcontains $param) {
                $haveOnlyPositioningParams = $false;
                break;
            }
        }

        if (-not $PSBoundParameters.ContainsKey('Monitor')) {
            $Monitor = -1
            $PSBoundParameters['Monitor'] = $Monitor
        }

        # Check if VLC is already running and we have no positioning parameters (just focus)
        $vlcWindow = GenXdev.Windows\Get-Window -ProcessName vlc -ErrorAction SilentlyContinue
        $hasPositioningParams = $PSBoundParameters.Keys | Microsoft.PowerShell.Core\Where-Object {
            $_ -in $positioningParams
        }
        $hasNonPositioningParams = $PSBoundParameters.Keys | Microsoft.PowerShell.Core\Where-Object {
            $_ -notin $positioningParams
        }

        # If VLC is running and we only have positioning params, just focus without repositioning
        if (($null -ne $vlcWindow) -and (-not $hasNonPositioningParams)) {
            Microsoft.PowerShell.Utility\Write-Verbose 'VLC already running with only positioning params, just focusing window without repositioning'

            # Just focus the existing VLC window without any repositioning
            GenXdev.Windows\Set-WindowPosition -WindowHelper $vlcWindow -FocusWindow -SetForeground

            return
        }

        # If VLC is running and we have non-positioning params, skip window positioning entirely
        $skipWindowPositioning = ($null -ne $vlcWindow) -and $hasNonPositioningParams -and (-not $hasPositioningParams)

        if ($haveOnlyPositioningParams) {

            $params = GenXdev.FileSystem\Copy-IdenticalParamValues `
                -BoundParameters $PSBoundParameters `
                -FunctionName 'GenXdev.Windows\Set-WindowPosition' `
                -DefaultValues (Microsoft.PowerShell.Utility\Get-Variable -Scope Local -ErrorAction SilentlyContinue)

            # Only add fullscreen keystroke if user explicitly requested Fullscreen
            # Don't use $FullScreen variable here as it may be set by default logic later
            if ($PSBoundParameters.ContainsKey('Fullscreen') -and $Fullscreen) {
                $params.KeysToSend = @("f") + $KeysToSend
                $params.RestoreFocus = $true
            }

            if ($params.ContainsKey(("KeysToSend"))) {

                $null = $params.Remove("KeysToSend")
            }

            GenXdev.Windows\Set-WindowPosition @params -ProcessName 'vlc'

            Microsoft.PowerShell.Utility\Write-Verbose `
                'Only positioning parameters specified, exiting...';
            return;
        }

        # ensure vlc is installed and install if needed
        if (-not (Microsoft.PowerShell.Management\Test-Path `
                    -LiteralPath "${env:ProgramFiles}\VideoLAN\VLC\vlc.exe")) {

            Microsoft.PowerShell.Utility\Write-Verbose `
                'VLC not found, installing via WinGet...'

            # check consent for VLC installation
            $vlcConsent = GenXdev.FileSystem\Confirm-InstallationConsent `
                -ApplicationName 'VLC Media Player' `
                -Source 'WinGet' `
                -Description 'Media player required for video/audio playback functionality' `
                -Publisher 'VideoLAN'

            if (-not $vlcConsent) {
                throw 'Installation consent denied for VLC Media Player. Cannot proceed without media player.'
            }

            # check and install winget module if not present
            if (-not (Microsoft.PowerShell.Core\Get-Module -ListAvailable `
                        -Name 'Microsoft.WinGet.Client')) {

                # check consent for WinGet client module installation
                $wingetConsent = GenXdev.FileSystem\Confirm-InstallationConsent `
                    -ApplicationName 'Microsoft.WinGet.Client' `
                    -Source 'PowerShell Gallery' `
                    -Description 'Required PowerShell module for installing VLC Media Player' `
                    -Publisher 'Microsoft'

                if (-not $wingetConsent) {
                    throw 'Installation consent denied for Microsoft.WinGet.Client module. Cannot install VLC without WinGet client.'
                }

                Microsoft.PowerShell.Utility\Write-Verbose `
                    'Installing WinGet client module'

                $null = PowerShellGet\Install-Module `
                    -Name 'Microsoft.WinGet.Client' `
                    -Force -Scope CurrentUser -AllowClobber -SkipPublisherCheck

                Microsoft.PowerShell.Utility\Write-Verbose `
                    'Importing WinGet client module'

                Microsoft.PowerShell.Core\Import-Module `
                    -Name 'Microsoft.WinGet.Client'
            }

            # install vlc media player using winget
            Microsoft.PowerShell.Utility\Write-Verbose `
                'Installing VLC media player'

            Microsoft.WinGet.Client\Install-WinGetPackage `
                -Id 'VideoLAN.VLC' -Scope System -Force

            # Configure VLC to not resize window on media change
            Microsoft.PowerShell.Utility\Write-Verbose `
                'Configuring VLC to prevent window auto-resizing'

            $vlcConfigPath = "${env:APPDATA}\vlc"
            $vlcrcPath = Microsoft.PowerShell.Management\Join-Path $vlcConfigPath 'vlcrc'

            # Ensure config directory exists
            if (-not (Microsoft.PowerShell.Management\Test-Path -LiteralPath $vlcConfigPath)) {
                $null = Microsoft.PowerShell.Management\New-Item `
                    -Path $vlcConfigPath -ItemType Directory -Force
            }

            # Configure settings to prevent window resizing
            if (Microsoft.PowerShell.Management\Test-Path -LiteralPath $vlcrcPath) {
                # Read existing config
                $vlcConfig = Microsoft.PowerShell.Management\Get-Content `
                    -Path $vlcrcPath -Raw

                # Update or add qt-video-autoresize setting
                if ($vlcConfig -match '#?qt-video-autoresize=') {
                    $vlcConfig = $vlcConfig -replace '#?qt-video-autoresize=.*', 'qt-video-autoresize=0'
                }
                else {
                    $vlcConfig += "`nqt-video-autoresize=0"
                }

                # Update or add autoscale setting
                if ($vlcConfig -match '#?autoscale=') {
                    $vlcConfig = $vlcConfig -replace '#?autoscale=.*', 'autoscale=0'
                }
                else {
                    $vlcConfig += "`nautoscale=0"
                }

                # Write updated config
                Microsoft.PowerShell.Management\Set-Content `
                    -Path $vlcrcPath -Value $vlcConfig -Force
            }
            else {
                # Create new config file with settings
                $newConfig = @"
# VLC media player preferences
qt-video-autoresize=0
autoscale=0
"@

                Microsoft.PowerShell.Management\Set-Content `
                    -Path $vlcrcPath -Value $newConfig -Force
            }

            Microsoft.PowerShell.Utility\Write-Verbose `
                'VLC configured: window auto-resize disabled'
        }

        # create vlc parameter conversion function
        function ConvertTo-VLCParameter {

            param (
                [string]$parameterName,
                $parameterValue
            )

            # convert powershell parameters to vlc command line arguments
            switch ($parameterName) {

                # parameters that need explicit off states
                'Random' {
                    return $parameterValue ? '--random' : '--no-random'
                }
                'Loop' {
                    return $parameterValue ? '--loop' : '--no-loop'
                }
                'Repeat' {
                    return $parameterValue ? '--repeat' : '--no-repeat'
                }
                'StartPaused' {
                    return $parameterValue ? '--start-paused' : `
                        '--no-start-paused'
                }
                'PlayAndExit' {
                    return $parameterValue ? '--play-and-exit' : `
                        '--no-play-and-exit'
                }
                'AlwaysOnTop' {
                    return $parameterValue ? '--video-on-top' : `
                        '--no-video-on-top'
                }
                'DisableAudio' {
                    return $parameterValue ? '--no-audio' : '--audio'
                }

                # parameters with value mappings
                'ReplayGainMode' {
                    return "--audio-replay-gain-mode=$($parameterValue.ToLower())"
                }
                'ReplayGainPreamp' {
                    return "--audio-replay-gain-preamp=$parameterValue"
                }
                'ForceDolbySurround' {
                    return "--force-dolby-surround=$($parameterValue.ToLower())"
                }
                'AudioFilters' {
                    return "--audio-filter=$($parameterValue -join ',')"
                }
                'Visualization' {
                    return "--audio-visual=$($parameterValue.ToLower())"
                }
                'Deinterlace' {
                    return "--deinterlace=$($parameterValue.ToLower())"
                }
                'DeinterlaceMode' {
                    return "--deinterlace-mode=$($parameterValue.ToLower())"
                }
                'AspectRatio' {
                    return "--aspect-ratio=$parameterValue"
                }
                'Crop' {
                    return "--crop=$parameterValue"
                }
                'AutoScale' {
                    if ($parameterValue) {
                        return '--autoscale'
                    }
                }
                'VideoFilters' {
                    return "--video-filter=$($parameterValue -join ',')"
                }
                'SubtitleFile' {
                    return "--sub-file=$parameterValue"
                }
                'DisableSubtitles' {
                    if ($parameterValue) {
                        return '--no-spu'
                    }
                }
                'SubtitleScale' {
                    return "--sub-text-scale=$parameterValue"
                }
                'SubtitleLanguage' {
                    $languageDict = GenXdev.Helpers\Get-WebLanguageDictionary
                    return "--sub-language=$($languageDict[$parameterValue])"
                }
                'AudioLanguage' {
                    $languageDict = GenXdev.Helpers\Get-WebLanguageDictionary
                    return "--audio-language=$($languageDict[$parameterValue])"
                }
                'PreferredAudioLanguage' {
                    $languageDict = GenXdev.Helpers\Get-WebLanguageDictionary
                    return "--preferred-audio-language=$($languageDict[$parameterValue])"
                }
                'HttpProxy' {
                    return "--http-proxy=$parameterValue"
                }
                'HttpProxyPassword' {
                    return "--http-proxy-pwd=$parameterValue"
                }
                'VerbosityLevel' {
                    return "--verbose=$parameterValue"
                }
                'SubdirectoryBehavior' {
                    return "--recursive=$($parameterValue.ToLower())"
                }
                'IgnoredExtensions' {
                    return "--ignore-filetypes=$parameterValue"
                }
                'HighPriority' {
                    if ($parameterValue) {
                        return '--high-priority'
                    }
                }
                'EnableTimeStretch' {
                    if ($parameterValue) {
                        return '--audio-time-stretch'
                    }
                }
                'EnableWallpaperMode' {
                    if ($parameterValue) {
                        return '--video-wallpaper'
                    }
                }
                'VideoFilterModules' {
                    return "--video-filter=$($parameterValue -join ',')"
                }
                'Modules' {
                    return "--modules=$($parameterValue -join ',')"
                }
                'AudioFilterModules' {
                    return "--audio-filter=$($parameterValue -join ',')"
                }
                'AudioVisualization' {
                    return "--audio-visual=$($parameterValue.ToLower())"
                }
                'PreferredSubtitleLanguage' {
                    return "--sub-language=$parameterValue"
                }
                'IgnoredFileExtensions' {
                    return "--ignore-filetypes=$parameterValue"
                }
                'EnableAudioTimeStretch' {
                    if ($parameterValue) {
                        return '--audio-time-stretch'
                    }
                }
            }
        }

        # check if vlc is already running (if not already checked above)
        $vlcProcess = $null
        if ($null -eq $vlcWindow) {
            $vlcWindow = GenXdev.Windows\Get-Window -ProcessName vlc `
                -ErrorAction SilentlyContinue
        }

        # initialize vlc argument list
        [System.Collections.Generic.List[string]]$vlcArgs = @()

        # Check if positioning parameters are supplied
        $hasPositioningParams = $PSBoundParameters.Keys | Microsoft.PowerShell.Core\Where-Object {
            $_ -in @('Monitor', 'Width', 'Height', 'X', 'Y',
                'Left', 'Right', 'Top', 'Bottom', 'Centered', 'Fullscreen',
                'SideBySide')
        }

        # Note: VLC's initial positioning arguments (--video-x, --video-y, --width, --height)
        # are unreliable for main window positioning. We'll rely entirely on post-launch
        # Set-WindowPosition for accurate positioning instead.

        # Only add --fullscreen if no positioning will occur, since positioning handles fullscreen via F11
        if ($FullScreen -and (-not $hasPositioningParams) -and ($null -eq $KeysToSend -or $KeysToSend.Count -eq 0)) {
            $vlcArgs.Add('--fullscreen')
            $FullScreen = $false
            $Maximize = $false
        }

        # configure instance mode
        if ($NewWindow) {

            $null = $vlcArgs.Add('--no-one-instance')
        }
        else {

            $null = $vlcArgs.Add('--one-instance')
        }

        # process each parameter and convert to vlc arguments
        $null = $PSBoundParameters.GetEnumerator() |
            Microsoft.PowerShell.Core\ForEach-Object {

                if ($_.Key -notin @('VLCPath', 'Path', 'Arguments', 'Close',
                        'SideBySide', 'FocusWindow', 'SetForeground',
                        'Maximize', 'RestoreFocus', 'SessionOnly',
                        'ClearSession', 'SkipSession', 'PassThru',
                        'KeysToSend', 'SendKeyEscape', 'SendKeyUseShiftEnter',
                        'SendKeyDelayMilliSeconds', 'SendKeyHoldKeyboardFocus',
                        'Monitor', 'NoBorders', 'Left', 'Right', 'Top',
                        'Bottom', 'Centered', 'Fullscreen', 'Width', 'Height',
                        'X', 'Y', 'NewWindow')) {

                    $vlcArgument = ConvertTo-VLCParameter -parameterName $_.Key `
                        -parameterValue $_.Value

                    if ($vlcArgument) {

                        $null = $vlcArgs.Add($vlcArgument)
                    }
                }
            }

        # add custom arguments if specified
        if ($Arguments) {

            $Arguments |
                Microsoft.PowerShell.Core\ForEach-Object {

                    $null = $vlcArgs.Add($_)
                }
        }

        # add media paths to argument list
        @($Path) |
            Microsoft.PowerShell.Core\ForEach-Object {

                if ($null -eq $_) {
                    return
                }

                $expandedPath = GenXdev.FileSystem\Expand-Path $_
                $null = $vlcArgs.Add("`"$expandedPath`"")
            }

        # build the process start arguments
        $processArgs = @{
            FilePath     = $VLCPath
            ArgumentList = $vlcArgs
            PassThru     = $true
            ErrorAction  = 'SilentlyContinue'
        }

        # Start VLC minimized if we'll be positioning it later to prevent visual jumping
        if ($hasPositioningParams) {

            Microsoft.PowerShell.Utility\Write-Verbose 'Starting VLC minimized since positioning will occur'
            $processArgs.WindowStyle = 'Minimized'
        }

        # handle existing vlc instance
        if ($null -eq $vlcWindow) {

            # ensure vlc executable exists
            if (-not (Microsoft.PowerShell.Management\Test-Path `
                        -LiteralPath $processArgs.FilePath -ErrorAction SilentlyContinue)) {

                throw 'VLC Media Player executable not found. Please ensure VLC is properly installed.'
            }

            # close any existing vlc processes
            Microsoft.PowerShell.Management\Get-Process vlc `
                -ErrorAction SilentlyContinue |
                Microsoft.PowerShell.Management\Stop-Process -Force
        }
        else {

            # get existing vlc process with main window
            $vlcProcess = Microsoft.PowerShell.Management\Get-Process `
                -Name vlc -ErrorAction SilentlyContinue |
                Microsoft.PowerShell.Core\Where-Object `
                    -Property MainWindowHandle -NE 0
        }

        # start vlc if needed
        # Only restart VLC if:
        # 1. VLC is not running, OR
        # 2. We have media files to open (Path parameter provided), OR
        # 3. We have significant configuration changes (more than just --one-instance)
        $hasMediaFiles = ($null -ne $Path) -and ($Path.Count -gt 0)
        $hasSignificantArgs = ($processArgs.ArgumentList.Count -gt 1) -and $hasMediaFiles

        if (($null -eq $vlcWindow) -or $hasSignificantArgs) {

            # start vlc with configured arguments
            try {

                Microsoft.PowerShell.Utility\Write-Verbose `
                    "Starting VLC with arguments: $($vlcArgs -join ' ')"

                $vlcProcess = Microsoft.PowerShell.Management\Start-Process `
                    @processArgs

                Microsoft.PowerShell.Utility\Write-Verbose `
                    "VLC started with PID: $($vlcProcess.Id)"

                Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds 2500
            }
            catch {

                Microsoft.PowerShell.Utility\Write-Error `
                    "Failed to start VLC: $_"
            }
        }

        # wait up to 20 seconds for vlc window to appear
        $vlcWindow = $null
        for ($i = 0; $i -lt 20; $i++) {
            $vlcWindow = GenXdev.Windows\Get-Window -ProcessName vlc `
                -ErrorAction SilentlyContinue
            if ($vlcWindow) { break }
            Microsoft.PowerShell.Utility\Start-Sleep -Seconds 1
        }

        # verify vlc window was found
        if ($null -eq $vlcWindow) {

            Microsoft.PowerShell.Utility\Write-Warning `
                'Failed to find VLC window'

            return
        }

        # Check if any positioning param (other than KeysToSend and RestoreFocus) was explicitly provided
        $hasPositioningParams = $PSBoundParameters.Keys | Microsoft.PowerShell.Core\Where-Object {
            $_ -in @('Monitor', 'NoBorders', 'Width', 'Height', 'X', 'Y',
                'Left', 'Right', 'Top', 'Bottom', 'Centered', 'Fullscreen',
                'SideBySide', 'FocusWindow', 'SetForeground', 'Minimize', 'Maximize')
        }

        # Check if this is a "keys only" operation (no positioning, no new media)
        $isKeysOnlyOperation = ($null -ne $KeysToSend) -and ($KeysToSend.Count -gt 0) -and
        (-not $hasPositioningParams) -and
        (-not $PSBoundParameters.ContainsKey('Path'))

        # prepare window positioning parameters
        if ($PSBoundParameters.ContainsKey('Process')) {
            $null = $PSBoundParameters.Remove('Process')
        }

        # copy window positioning parameters using helper function, but exclude RestoreFocus for keys-only operations
        $parametersToCopy = $PSBoundParameters
        if ($isKeysOnlyOperation) {
            # Create a copy without RestoreFocus to prevent unwanted positioning
            $parametersToCopy = @{}
            $PSBoundParameters.GetEnumerator() | Microsoft.PowerShell.Core\ForEach-Object {
                if ($_.Key -ne 'RestoreFocus') {
                    $parametersToCopy[$_.Key] = $_.Value
                }
            }
        }

        # If we're skipping window positioning, exclude KeysToSend params since they'll be handled separately
        $invocationParams = GenXdev.FileSystem\Copy-IdenticalParamValues `
            -BoundParameters $PSBoundParameters `
            -FunctionName 'GenXdev.Windows\Set-WindowPosition' `
            -DefaultValues @((Microsoft.PowerShell.Utility\Get-Variable -Name 'Monitor' -Scope Local))

        $invocationParams.WindowHelper = $vlcWindow
        $invocationParams.SideBySide = $SideBySide

        # Only set default monitor and fullscreen if we have actual positioning params
        # OR if Path is provided (opening VLC, not just sending keys)
        # AND we're not skipping window positioning
        if ((-not $PSBoundParameters.ContainsKey('Monitor')) -and (-not $SideBySide) -and ($hasPositioningParams -or $PSBoundParameters.ContainsKey('Path')) -and
            ($null -eq $KeysToSend -or $KeysToSend.Count -eq 0) -and (-not $skipWindowPositioning)
        ) {
            $invocationParams.Monitor = -2
            $Fullscreen = $true
        }
        if ($FullScreen) {
            # $invocationParams.Maximize = $true
            $invocationParams.Fullscreen = $false
            # Only set fullscreen keystroke if user didn't provide KeysToSend
            if (-not $PSBoundParameters.ContainsKey('KeysToSend')) {
                $invocationParams.KeysToSend = @('f')
            }
            $invocationParams.RestoreFocus = $true
        }

        if ($invocationParams.ContainsKey(("KeysToSend"))) {

            $null = $invocationParams.Remove("KeysToSend")
        }

        # Only apply window positioning if not a keys-only operation AND not skipping window positioning
        if (-not $isKeysOnlyOperation -and -not $skipWindowPositioning) {
            # apply window positioning if parameters specified
            $null = GenXdev.Windows\Set-WindowPosition @invocationParams
        }

        Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds 500
    }


    process {

        # handle close request
        if ($Close) {

            Microsoft.PowerShell.Utility\Write-Verbose 'Closing VLC windows'

            if ($vlcProcess) {

                $null = $vlcProcess.CloseMainWindow()

                $null = $vlcProcess.WaitForExit(2000)
            }

            $null = Microsoft.PowerShell.Management\Get-Process vlc `
                -ErrorAction SilentlyContinue |
                Microsoft.PowerShell.Management\Stop-Process -Force

            return
        }

        if ($haveOnlyPositioningParams) {

            return
        }

        # exit if no keys to send
        if ($null -eq $KeysToSend -or ($KeysToSend.Count -eq 0)) {

            return
        }

        Microsoft.PowerShell.Utility\Write-Verbose `
            'Sending keystrokes to VLC window'

        # copy key sending parameters using helper function
        $invocationParams = GenXdev.FileSystem\Copy-IdenticalParamValues `
            -BoundParameters $PSBoundParameters `
            -FunctionName 'GenXdev.Windows\Send-Key'

        $invocationParams.WindowHandle = $vlcWindow.Handle

        # send keys to vlc window
        $null = GenXdev.Windows\Send-Key @invocationParams
    }

    end {

        if ($haveOnlyPositioningParams) {

            return
        }

        # restore focus to powershell window if requested
        if ($RestoreFocus) {

            Microsoft.PowerShell.Utility\Write-Verbose `
                'Restoring PowerShell window focus'

            # restore powershell window focus
            $null = GenXdev.Windows\Set-WindowPosition -FocusWindow -SetForeground
        }

        # return window helper if requested
        if ($PassThru) {

            return $vlcWindow
        }
    }
}
###############################################################################