caprica/vlcj

vlcj 4.x breaking API changes

caprica opened this issue · 36 comments

All (well, best effort for all) changes that break API backwards compatibility will be referenced here.

#690 and #700 are the issues to blame for most of this.

#677

  • getTitleDescriptions now returns List<TitleDescription> instead of List<TrackDescription>
  • getExtendedTitleDescriptions is removed (it effectively becomes getTitleDescriptions)
  • The type of the titles property in MediaDetails is changed from TrackDescription to TitleDescription
  • getChapterDescriptions now returns List<ChapterDescription> instead of List<String>
  • getExtendedChapterDescriptions is removed (it effectively becomes getChapterDescriptions)
  • The type of the chapters property in MediaDetails is changed from String to ChapterDescription

#678

  • toggleTeletext() has been removed from MediaPlayer with no replacement

#676

  • getFps() has been removed from MediaPlayer with no replacement, it simply does not exist in the native API anymore

#670

  • anything related to the VLM (media manager) API has been removed (setting up broadcasts, VOD etc) with no replacement (this was always marked as experimental and subject to removal in vlcj)

These changes are likely to have the most impact if migrating client applications previously using vlcj-3 to vlcj-4. This is likely to be a significant pain point when migrating applications.

#690 simplified/improved MediaPlayer/MediaPlayerFactory

  • removing LibVlcFactory
  • not using a single LibVlc native library instance
  • implementing default NativeDiscovery directly in the factory, a custom NativeDiscovery can be used if required

Significant and extensive changes to factory and media player API, each component has been broken down into various sub-components (tentatively called Services or Aspects, but not AOP) so whereas MediaPlayer for example had many methods, they have been moved to subcomponents, some examples:

  • mediaPlayer.play() becomes mediaPlayer.controls().play()
  • mediaPlayer.playMedia(...) becomes mediaPlayer.media().playMedia(...)
  • mediaPlayer.toggleFullScreen() becomes mediaPlayer.fullScreen().toggle()
  • factory.newEmbeddedMediaPlayer() becomes factory.mediaPlayers().newEmbeddedMediaPlayer()
    ...and so on.

Other small changes include:

  • removed the FullScreenStrategy parameter when creating an EmbeddedMediaPlayer via the factory, you must now set the strategy after creating the media player
  • getting media statistics now no longer exposes the internal libvlc_media_stats_t structure, instead you pass in an instance of a new MediaStatistics object and the method will fill it for you
  • mrl parameter has been removed from the mediaChanged event and the corresponding listener
  • various methods that used a getX()/setX() pattern have been renamed to a more object-oriented flavour (mostly dropping the "get" prefix).

And this particularly very important change:

  • not automatically pushing native events to a background thread, see #694

But why have you done this you madman?

Media player and factory implementation classes were unwieldy mega classes with thousands of lines of code that were gradually added over ten years of incremental development. DefaultMediaPlayer itself was 2500 lines of code. Reworking those components and splitting them into smaller, more manageable chunks, was becoming vital for the long term continued maintenance of this project.

Also, the vlcj implementation is very mature and has been stable for a long time now, so doing a major refactoring now is quite low risk. Almost all of the fundamental implementation remains, the changes are more about reorganising things to make life easier.

No major refactoring exercise has been done previously, so one per ten years is forgivable I think.

#412

  • CanvasVideoSurface has been removed and replaced by ComponentVideoSurface

You can now use any AWT Component as a video surface, Canvas remains optimal, but now Window is possible, and even Button if you want.

The ability to use a Window rather than a Canvas as a video surface has important implications for vlcj on OSX. Since JDK 7+ on OSX removed heavyweight AWT it has not been possible to use the embedded media player (i.e. the optimal media player) on OSX. This is because LibVLC requires a native window handle to render video into, and without a heavyweight component no such window handle was available (lightweight components are all rendered by the toolkit, similar to Java2D rendering in Swing, they have no corresponding native component).

But, a Window should work - because an AWT Window has a native heavyweight Window backing it. We just need to be able to grab the native handle to that Window and it will work.

Having said that, a Window is not an ideal solution because the video will render over the entire window - but nevertheless, it may now be feasible for some client applications to work better on OSX.

#475

  • media discovery has been simplified and brought up to spec with the latest native API
  • factory methods like newVideoMediaDiscoverer, newAudioMediaDiscoverer and newMediaDiscoverer(name) have been removed
  • replaced by discoverers() and discoverer(name) API on the factory

Also as part of this task and #690, the MediaListPlayer mega class has undergone the same refactoring as for MediaPlayer. Notable API breakages as a result of this are:

  • any events related to Media in the media list player have been removed
  • the mediaListPlayerPlayed event (that was never used) has been removed
  • a new mediaListPlayerFinished event has been added, it fires when the last item in the list has finished playing (LibVLC code actually re-purposes mediaListPlayerPlayed for this)

These changes are likely to have the most impact if migrating client applications previously using vlcj-3 to vlcj-4. This is likely to be a significant pain point when migrating applications.

#700 simplified/improved media and sub-items handling

  • media and sub-items have been unpicked from media player to become a top-level component in its own right - this facilitates moving a lot of media and sub-item related code out of the base media player class, greatly simplifying that class
  • methods like playMedia, prepareMedia, startMedia (all of which had taken an MRL and media options parameter) have been removed from MediaPlayer. You are now expected to create a Media object on the MediaPlayerFactory, you can then add options as needed, before you set that Media object on your media player. A subsequent call is required to play the media via the media player controls API
  • methods related to meta data, track information, and parsing have been removed from MediaPlayer. The replacements are all now accessible via the new Media component
  • events related to Media have been removed from MediaPlayerEventListener, the associated adapter and the media player components - they are now associated with the new Media component
  • so-called "synthetic" or "semantic" events previously on the MediaPlayerEventListener have been removed with no replacement - this is things like sub-item played and so on. These events are no longer required as the media player uses a native media list player behind the scenes to deal with sub-items
  • when using the new Media component, the application is responsible for maintaining its lifecycle, in particular a hard reference must be kept (same as was always the case with MediaPlayer for example) and each Media instance must be explicitly released when no longer needed

There were a lot of knock-on changes as a result of this.

These changes are likely to have a significant impact on client applications that use the media player components (e.g. EmbeddedMediaPlayerComponent).

#698 changes to the media player component mini-framework

  • components are now created with a MediaPlayerComponentBuilder - this uses an implementation of a type-safe builder pattern
  • components can still be created directly, without using the builder
  • all template methods that were invoked from the component constructors have been removed (if used improperly these methods could cause subtle and confusing problems for client applications), anything previously set via these template methods is now a constructor parameter
  • a client application is responsible for releasing a shared MediaPlayerFactory if one is used, the most common case is that a component creates its own factory that is automatically released when the component is released

Happily this change closes four really old tickets too.

#685 changes to native enums

  • vlcj API was exposing some internal enums, as it turns out those enums were not really used internally at all, so they have been moved from the internal binding package into the vlcj core API
  • the affected enums were also renamed to remove reference to libvlc in both the enum name itself and the individual enum members
  • all enums that are part of the vlcj public API have been moved to a separate enums package

#611 Hue (video adjustment) is changed from float to int

  • the getter/setter now take float rather than int
  • LibVlcConst has been changed to use a float rather than int
  • LibVlcConst has been changed to reflect the new range of allowable Hue values, -180.0f to 180.0f

#688 remove deprecated set_subtitle_file method

  • subtitles should be added via the new media slave api on either media or media player

#726 MediaDetails aggregate class removed

  • this class simply wrapped a whole bunch of vlcj title/description/track information, client applications now should just ask for the specific data they want

#727 FileFilter classes moved to separate project

  • these FileFilter classes were used to specify the types of files that could be opened by vlcj/VLC in a File Open dialog box
  • the classes have been removed from the vlcj core project into an optional vlcj-file-filters project
  • the package has also been renamed to "filefilters" from "filter"

#728 MRL implementation classes moved to separate project

  • these MRL classes were used to help build valid Media Resource Locator strings
  • the classes have been removed from the vlcj core project into an optional vlcj-mrls project
  • the package has been renamed to "mrls" from "mrl"

#710 meta data simplifications

  • removed MetaData interface and DefaultMetaData implementation - the implementation is now in the top-level Media component
  • renamed MediaMetaData value object to MetaData and moved to "model" package
  • no longer individual setter/getter for each meta property, replaced by a single get/set pair that takes a Meta type
  • length removed from meta data, it was never a native meta type, and is only actually available via media player, not media

#697 changes to native discovery

  • the NativeDiscoveryStrategy interface has changed, so if clients made their own implementations they will be impacted by this
  • the provided Linux, OSX and Windows strategies have been removed and reimplemented, they are still extensible by sub-classes, but have moved packages (consolidated to the same package rather than per OS) and been renamed (dropping the Default prefix)

See #697 for a more detailed explanation.

#465 changes to direct rendering

  • previously the API passed a JNA Memory object to gain access to the video buffers, this is now a ByteBuffer - this change will break API for clients that have implemented RenderCallback
  • the direct rendering media player now takes an additional "lockBuffers" initialisation parameter to enable locking (of virtual memory pages) for the native video buffer

#734 video surface adapter implementation clean-up - this should not affect client applications since there was no point client applications using these classes directly

  • OS-specific implementations consolidated into parent package
  • implementation classes made final
  • serialVersion removed, since there is no use-case for serialising these classes

#735 full-screen strategy implemenation clean-up

  • implementation classes moved to a new "fullscreen" package
  • renamed DefaultFullScreenStrategy to ExclusiveModeFullScreenStrategy since it is no longer a useful "default" (other strategies are better)

#736 WindowsRuntimeUtil

  • class has been removed, client applications should not have been using this class anyway

#737 LibXUtil

  • class has been removed, client applications should not have been using this class anyway

#738 HeadlessMediaPlayer

  • the headless media player interface and implementation class have been removed, they were both empty and simply extended the DefaultMediaPlayer
  • client applications that want a media player with a UI should simply use the base DefaultMediaPlayer instead

#739 "adaptive" full screen strategy

  • implementation class renamed to "AdaptiveFullScreenStrategy"
  • template methods for before/after full-screen renamed to "onBeforeEnterFullScreen" and "onAfterExitFullScreen"
  • sub-classes can no longer set per-OS strategies to use, instead a sub-class should provide the alternate strategies via the constructor (classes that provide sensible default strategies for each OS are provided and a client can use them for zero or more of their own strategies if needed)

#705 serialization changes

  • various data/value-object classes no longer implement Serializable (e.g. TrackInfo)
  • Java serialization sucks. Use JSON or XML instead.

#747 RuntimeUtil

  • moved the RuntimeUtil class to the internal "binding" package
  • this class is used internally by vlcj and was not intended to be public API
  • client applications may still use this newly moved class if necessary, it may be useful in certain specialist use-cases (like implementing a custom full-screen strategy depending on the OS, or implementing a new native discovery strategy)

#742 NativeStreams

  • this class was made available with vlcj, but never used by vlcj itself - it was used to capture/redirect native process input/output/error streams (mainly so the native logs could be captured)
  • this has now been removed from vlcj, if client applications depend on it there is a new github project for it (see #742 for details)

#730 conditional waiters mini-framework

  • this set of classes is used to provide a semblance of synchronous programming when working with media player (and now also media) events
  • changed packages, changed template method signatures in a base class - will impact any client applications that sub-classed these classes
  • renamed "condition" to "waiter"

#756 auto-playing of sub-items

  • auto-playing of sub-items is intrinsic to the media player now, playing e.g. a YouTube MRL will automatically play the stream sub-item, if you don't want to auto-play sub-items then you should prepare and parse media instead of playing it. The API-breakage here is that the API for auto-playing sub-items is now redundant and has been removed

#758 changes to "direct rendering" media players

  • DirectMediaPlayer and DirectMediaPlayerComponent are gone, functionality is re-implemented as a bespoke VideoSurface for the EmbeddedMediaPlayer, and a new CallbackMediaPlayerComponent with improved functionality and usability
  • RenderCallback API has changed to pass a MediaPlayer rather than DirectMediaPlayer, affecting any application that implements its own RenderCallback or RenderCallbackAdapter

#759 changes to "direct" audio players

  • DirectAudioPlayer and DirectAudioPlayerComponent are gone, functionality is re-implemented directly in the DefaultMediaPlayer audio service/aspect
  • AudioCallback interface and associated Adapter have changed to pass MediaPlayer rather than DirectAudioPlayer

The concept of "standard" media options on the media player that are automatically added when media is played no longer exists, manage this in the client application if you need it.

Updated README at a270d90.

#706 package reorganisation

#741 bindings package moved to a separate project

  • should not really affect clients as they should not be using this package directly anyway

There are no longer interfaces for media players, just the media player implementation classes themselves.

For example DefaultMediaPlayer becomes MediaPlayer, DefaultEmbeddedMediaPlayer because EmbeddedMediaPlayer, DefaultMediaListPlayer becomes MediaListPlayer.