An easy to use and highly customizable player.

To do a good job, he must sharpen his tools

Without further ado, let’s get straight to the dry stuff.

Q: The player is the player. Why do you emphasize the high degree of freedom? A: The reason for the high degree of freedom is that you can change all the visible elements on the player, and there are many callbacks to customize. Mainly reflected in the definition of this aspect. (you can copy blibli, Tencent player, etc.)

Q: What features or configurations are available for high freeform? A: One of the best examples of freedom is the player’s ability to customize extension elements, but this is often overlooked by integration developers because it is really convenient, but many players fail to do this. Second, the use of custom top control block can add many actions, through the custom extension element function to assist implementation; Finally, customize the bottom control bar to add or subtract control elements, change the style of the progress bar, and so on.

Q: What are the current capabilities of the player? A: It is still being improved, but the functions have been basically improved. The rest is to optimize and improve according to the feedback of the developers. The following is my list of features:

  • 1. Custom ICONS (all)
  • 2. Customize player configurations
    • Start position of the video
    • Auto play
    • Whether to loop
    • Video proportion
    • Whether the progress bar allows drag and drop
    • The number of seconds in which video is fast-forward/rewind
  • 3. Custom extension elements (infinite)
    • Subtitles (built-in subtitles can also be used)
    • barrage
    • Other elements (e.g., AD coverage; Custom video top back button; Fade in and out prompt for fast forward or fast back, etc.)
  • 4. Customize the player style
    • Whether the play button is displayed (the play button in the center of the view when the video is paused)
    • Custom Play button (play button in the center of view when video is paused)
    • Top control bar custom
      • Show or hide
      • Custom height
      • Custom margins
      • Custom background color
      • Custom return button
      • Expanding the Middle Element (Title)
      • Expand the right control element (more operations)
    • The control bar at the bottom is customized
      • Custom order (control elements with arrays: linear progress bar, rectangular progress bar, etc.)
      • Custom elements (order controlled by arrays)
      • Custom background color
      • Custom ICONS (Play, Pause, Fast forward, Fast Rewind, Full screen, cancel full screen)
      • Free configuration of progress bar styles (background color, cache area color, progress bar color, drag button color, drag button color, etc.)
      • Volume Control elements (not yet completed)
      • Built-in barrage (not yet finished, still customizable)
      • Control bar expansion (not yet completed)
    • Custom configuration of built-in subtitles (or rewrite subtitles by custom extension)
      • Set the font size of the main or subtitle
      • Set the font color for the main or subtitle
  • Gesture support
    • Click (menu bar show or hide)
    • Double click (pause or play)
    • Slide to fast forward or rewind
    • Slide to adjust video brightness (left area)
    • Slide to adjust volume size (right side area)
  • 6. Switch between vertical and horizontal screens
  • 7. Steady on Avoid screen lock

A rendering

Go to the source of happiness

  • Git address
  • The DEMO source code

Player properties

What are the attributes of the player?

attribute type describe
dataSource String The path to the video URL or media file
playOptions VideoPlayOptions Customize video playback Settings, including whether to automatically play and whether to loop (see below for details)Useage)
videoStyle VideoStyle Video player custom style, custom top control block style, custom bottom control block style, etc. (see below for detailsUseage)
children List Custom extended elements that need to use widgetsAlign(Subtitles, bullets, ads, covers and other custom elements)
The callback method type describe
oninit VideoCallback Initialization completes the callback
onplay VideoCallback Video starts playing back
onpause VideoCallback Video pause playback callback
ontimeupdate VideoCallback Video playback progress callback (subtitle matching by value returned)
onend VideoCallback Video playback ends callback
onvolume VideoCallback Play the sound size change callback
onbrightness VideoCallback Screen brightness change callback
onpop VideoCallback Top control bar back button click callback
onnetwork VideoCallback Network change callback
onfullscreen VideoCallback Whether to call back the video in full screen

Player customization (VideoPlayOptions)

attribute type describe
startPosition Duration Start playing node, for example: Duration(seconds: 0))
loop bool Whether to loop
seekSeconds num Sets the number of seconds for video fast forward/rewind. The default value is15s
autoplay bool Auto play
aspectRatio num Video playback ratio, for example: 16/9 or 4/3
allowScrubbing bool Whether to run progress bar drag

Player custom Styles (VideoStyle)

attribute type describe
playIcon Widget ShowPlayIcon Is the icon displayed in the center when a video is pausedfalseIs invalid.
showPlayIcon bool Whether to display the play button when paused
videoTopBarStyle VideoTopBarStyle Custom styles at the top of the video (see below for details)Useage)
videoControlBarStyle VideoControlBarStyle Control bar custom styles (see below for detailsUseage)
videoSubtitlesStyle VideoSubtitles Custom subtitle styles (see below for detailsUseage)

Customize the top control bar (VideoTopBarStyle) :

attribute type describe
show bool Whether to display the control bar
barBackgroundColor Color Control bar background color, default isColor. FromRGBO (0, 0, 0, 0.5)
height double Custom control bar height
padding EdgeInsets Custom margins
popIcon Widget Custom return button
contents List Expand the middle element of the control bar (width adaptive:RowIn theExpanded)
actions List Expand the control element on the right side of the control bar
customBar Widget Override control bar (if setcustomBar, in addition toshowProperties None of the above properties take effectAlignandPositioned

Customize the bottom control bar style (VideoControlBarStyle) :

attribute type describe
height double Control bar height, default is30
padding EdgeInsets Control bar margin, default isEdgeInsets.symmetric(vertical: 8, horizontal: 10)
progressStyle VideoProgressStyle Custom control progress bar style
barBackgroundColor Color Control bar background color, default isColor. FromRGBO (0, 0, 0, 0.5)
timePadding EdgeInsets The inner margin of the video time. The default isEdgeInsets.symmetric(horizontal: 5)
timeFontSize double Video time font size, default is8
timeFontColor Color The color of the video time, default isColor.fromRGBO(255, 255, 255, 1)
playIcon Widget Control bar play icon (nextFigure 3Details)
pauseIcon Widget Control bar pause icon (belowFigure 3Details)
rewindIcon Widget Control bar fast rewind icon (underFigure 3Details)
forwardIcon Widget Control bar fast forward icon (belowFigure 3Details)
fullscreenIcon Widget Control bar full screen icon (belowFigure 3Details)
fullscreenExitIcon Widget Control bar to cancel the full screen icon (belowFigure 3Details)
itemList List Control bar custom function (belowFigure 4.), default to [“rewind”, “play”, “forward”, “position-time”, “progress”, “duration-time”, “fullscreen”]. If we need to adjust the display order of the control bar, we only need to adjust the order of the strings in the list. If we need to delete, we can directly remove the changed strings from the list, such as remove fast forward and fast back. Set list to [“play”, “progress”,”position-time”, “progress”,” duration-time”, “fullscreen”]. Custom elements will come later, where you add your elements to the list.

Custom Progress bar Style (VideoProgressStyle) :

attribute type describe
padding EdgeInsets Progress bar margins (itemListContained in theprogressValid)
height double Progress bar height (itemListContained in theprogressValid)
dragHeight double Progress bar drag button height (itemListContained in theprogressValid)
progressRadius double Rounded Corner of progress bar (itemListContained in theprogressValid)
playedColor Color The color of the progress bar that has been played (see below)
bufferedColor Color Buffered progress bar color (see below)
backgroundColor Color Progress bar background color (see below)
dragBarColor Color Progress bar drag button demo (itemListContained in theprogressValid)

Customize control bar functions (itemList) :

attribute type describe
rewind String Fast rewind function, corresponding toVideoControlBarStyletherewindIconicon
play String Play/pause function, corresponding toVideoControlBarStyletheplayIcon pauseIconicon
forward String Fast forward, correspondingVideoControlBarStyletheforwardIconicon
progress String Linear progress bar (or ‘basic-progress’), byVideoControlBarStyletheprogressStyleControl style
basic-progress String Rectangular progress bar (or ‘Progress’), byVideoControlBarStyletheprogressStyleControl style
time String Time format: current time/total video duration (andposition-timeandduration-timeChoose one of the twoVideoControlBarStylethetimePadding timeFontSize timeFontColorControl style
position-time String Current playback time, style control withtimeThe same
duration-time String Total video duration, style control withtimeThe same
fullscreen String The full-screen/small-screen function corresponds toVideoControlBarStylethefullscreenIcon fullscreenExitIconicon

How to use it?

Install & Set up

  1. To add dependencies, open the pubspec.yaml file in the root directory and add the following code under Dependencies:

    awsome_video_player: #latest
    Copy the code
  2. Install dependencies (ignore if already installed automatically)

    CD Project directory Flutter Packagesget
    Copy the code
  3. Import the library in the page

    import 'package:awsome_video_player/awsome_video_player.dart';
    Copy the code

Useage

This is a full DEMO

main.dart

import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  String mainSubtitles = "Main title";
  String subSubtitles = "Subtitle";

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Awsome video player'),
        ),
        body: Center(
          child: AwsomeVideoPlayer(
            "https://www.runoob.com/try/demo_source/movie.mp4"./// Video Playback Configuration
            playOptions: VideoPlayOptions(
              seekSeconds: 30,
              aspectRatio: 16 / 9,
              loop: true,
              autoplay: true,
              allowScrubbing: true,
              startPosition: Duration(seconds: 0)),
            /// Custom video styles
            videoStyle: VideoStyle(
            	/// Customize the play button in the middle of a video when it is paused
              playIcon: Icon(
                Icons.play_circle_outline,
                size: 100,
                color: Colors.white,
              ),
              /// Whether to display the middle play button when pausing
              showPlayIcon: true./// Customize the bottom control bar
              videoControlBarStyle: VideoControlBarStyle(
                /// Custom colors
                //barBackgroundColor: Colors.blue,
                /// Custom progress bar styles
                progressStyle: VideoProgressStyle(
                  // padding: EdgeInsets.all(0),
                  playedColor: Colors.red,
                  bufferedColor: Colors.yellow,
                  backgroundColor: Colors.green,
                  dragBarColor: Colors.white,// Progress bar 'progress' is valid, if 'basic-progress' is invalid
                  height: 4,
                  progressRadius: 2.// Progress bar 'progress' is valid, if 'basic-progress' is invalid
                  dragHeight: 5// Progress bar 'progress' is valid, if 'basic-progress' is invalid
                ),
                /// Change the play button in the progress bar
                playIcon: Icon(
                  Icons.play_arrow,
                  color: Colors.white,
                  size: 16
                ),
                /// Change the pause button in the progress bar
                pauseIcon: Icon(
                  Icons.pause,
                  color: Colors.red,
                  size: 16,),/// Change the rewind button in the progress bar
                rewindIcon: Icon(
                  Icons.replay_30,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the fast forward button in the progress bar
                forwardIcon: Icon(
                  Icons.forward_30,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the full screen button in the progress bar
                fullscreenIcon: Icon(
                  Icons.fullscreen,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the progress bar exit full screen button
                fullscreenExitIcon: Icon(
                  Icons.fullscreen_exit,
                  size: 16,
                  color: Colors.red,
                ),
                /// Determine the elements and order of the control bar, as shown in Figure 3 above
                itemList: [
                  "rewind"."play"."forward"."position-time".// Current playback time
                  "progress".// Linear progress bar
                  //"basic-progress",// rectangle progress bar
                  "duration-time".// Total video duration
                  // "time", // Format: current time/total video duration
                  "fullscreen"],),/// Custom subtitles
              videoSubtitlesStyle: VideoSubtitles(
              	mianTitle: Align(
                  alignment: Alignment.bottomCenter,
                  child: Container(
                    padding: EdgeInsets.fromLTRB(10.0.10.30),
                    child: Text(
                    		mainSubtitles,
                        maxLines: 2,
                        textAlign: TextAlign.center,
                        style: TextStyle(
                            color: Colors.white, fontSize: 14)),
                  ),
                ),
                subTitle: Align(
                  alignment: Alignment.bottomCenter,
                  child: Container(
                    padding: EdgeInsets.all(10),
                    child: Text(
                    		subSubtitles,
                        maxLines: 2,
                        textAlign: TextAlign.center,
                        style: TextStyle(
                            color: Colors.white, fontSize: 14() (() (() (() (() (/// Custom extension elements
            children: [
              /// This will overwrite the content of the video, since this level is the highest, so gestures will be disabled (caution)
              /// This could be used for video ads
              // Positioned(
              // top: 0,
              // left: 0,
              // bottom: 0,
              // right: 0,
              // child: Text("data", style: TextStyle(color: Colors.white),),
              // ),]./// Video initialization completes the callback
            oninit: (val) {
              print("video oninit");
            },
            /// Video playback callback
            onplay: (value) {
              print("video played");
            },
            /// Video pause callback
            onpause: (value) {
              print("video paused");
            },
            /// Video playback ends callback
            onended: (value) {
              print("video ended");
            },
            /// Video playback progress callback
            /// Can be used to match subtitles
            ontimeupdate: (value) {
              print("timeupdate $value");
              var position = value.position.inMilliseconds / 1000;
              // Determine the currently displayed subtitle according to position
            },
            /// Sound change callbacks
            onvolume: (value) {
              print("onvolume $value");
            },
            /// Brightness change callback
            onbrightness: (value) {
              print("onbrightness $value");
            },
            /// Network change callback
            onnetwork: (value) {
              print("onbrightness $value");
            },
            /// Click the back button on the top control bar
            onpop: (value) {
              print("Return to previous page"); },),),),); }}Copy the code

The DEMO sample

1. Customize the control bar icon

First I’ll take a look at the control bar icon customization (see figure 1) :

DEMO: main.dart

import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Awsome video player'),
        ),
        body: Center(
          child: AwsomeVideoPlayer(
            "https://www.runoob.com/try/demo_source/movie.mp4"./// Video Playback Configuration
            playOptions: VideoPlayOptions(
              seekSeconds: 30,
              aspectRatio: 16 / 9,
              loop: true,
              autoplay: true,
              allowScrubbing: true,
              startPosition: Duration(seconds: 0)),
            /// Custom video styles - notice I'm highlighting them
            videoStyle: VideoStyle(
              /// Customize the bottom control bar - that's the point
              videoControlBarStyle: VideoControlBarStyle(
                /// Change the play button in the progress bar
                playIcon: Icon(
                  Icons.play_arrow,
                  color: Colors.white,
                  size: 16
                ),
                /// Change the pause button in the progress bar
                pauseIcon: Icon(
                  Icons.pause,
                  color: Colors.red,
                  size: 16,),/// Change the rewind button in the progress bar
                rewindIcon: Icon(
                  Icons.replay_30,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the fast forward button in the progress bar
                forwardIcon: Icon(
                  Icons.forward_30,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the full screen button in the progress bar
                fullscreenIcon: Icon(
                  Icons.fullscreen,
                  size: 16,
                  color: Colors.white,
                ),
                /// Change the progress bar exit full screen button
                fullscreenExitIcon: Icon(
                  Icons.fullscreen_exit,
                  size: 16, color: Colors.red, ), ), ), ), ), ), ); }}Copy the code

2. Customize control bar elements and order

We can customize the style of the control bar according to videoStyle videoControlBarStyle: Reorder (see Figure 3 above) just reorder the strings in the itemList; Control the display of elements by removing elements from the itemList that do not need to be temporary.

DEMO: main.dart

import 'package:flutter/material.dart';

import 'package:awsome_video_player/awsome_video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Awsome video player'),
        ),
        body: Center(
          child: AwsomeVideoPlayer(
            "https://www.runoob.com/try/demo_source/movie.mp4"./// Video Playback Configuration
            playOptions: VideoPlayOptions(
              seekSeconds: 30,
              aspectRatio: 16 / 9,
              loop: true,
              autoplay: true,
              allowScrubbing: true,
              startPosition: Duration(seconds: 0)),
            /// Custom video styles - notice I'm highlighting them
            videoStyle: VideoStyle(
              /// Customize the bottom control bar - that's the point
              videoControlBarStyle: VideoControlBarStyle(
                /// Determine the elements and order of the control bar, as shown in Figure 3 above
                itemList: [
                  "progress".// The progress bar is brought forward here, so it looks like figure 3
                  "rewind".// If you want to delete the fast back button, comment it or delete it
                  "play"."forward"."time"."fullscreen"],),),),),),); }}Copy the code

3. Customize the background colors of the progress bar and control bar

Again we customize the color of the progress bar with videoStyle videoControlBarStyle (see Figure 3 above).

DEMO: main.dart

import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Awsome video player'),
        ),
        body: Center(
          child: AwsomeVideoPlayer(
            "https://www.runoob.com/try/demo_source/movie.mp4"./// Video Playback Configuration
            playOptions: VideoPlayOptions(
              seekSeconds: 30,
              aspectRatio: 16 / 9,
              loop: true,
              autoplay: true,
              allowScrubbing: true,
              startPosition: Duration(seconds: 0)),
            /// Custom video styles
            videoStyle: VideoStyle(
              /// Customize the bottom control bar
              videoControlBarStyle: VideoControlBarStyle(
                /// Custom colors
                barBackgroundColor: Colors.blue,// Control the background color of the bar

                /// Custom progress bar styles
                progressStyle: VideoProgressStyle(
                  // padding: EdgeInsets.all(0),
                  playedColor: Colors.red,
                  bufferedColor: Colors.yellow,
                  backgroundColor: Colors.green,
                  dragBarColor: Colors.white,// Progress bar 'progress' is valid, if 'basic-progress' is invalid
                  height: 4,
                  progressRadius: 2.// Progress bar 'progress' is valid, if 'basic-progress' is invalid
                  dragHeight: 5// Progress bar 'progress' is valid, if 'basic-progress' is invalid),),),),),),); }}Copy the code

4. Customize the top control bar

Customize the top control bar with videoTopBarStyle.

DEMO

DEMO: main.dart

import 'package:flutter/material.dart';
import 'package:awsome_video_player/awsome_video_player.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String videoUrl = "https://www.runoob.com/try/demo_source/movie.mp4";
  bool showAdvertCover = false;// Whether to display ads

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Awsome video player'), ), body: Center( child: videoUrl ! =""
              ? AwsomeVideoPlayer(
                  videoUrl,

                  /// Video Playback Configuration
                  playOptions: VideoPlayOptions(
                      seekSeconds: 30,
                      aspectRatio: 16 / 9,
                      loop: true,
                      autoplay: true,
                      allowScrubbing: true,
                      startPosition: Duration(seconds: 0)),

                  /// Custom video styles
                  videoStyle: VideoStyle(

                    /// Custom top control bar
                    videoTopBarStyle: VideoTopBarStyle(
                      show: true.// Whether to display
                      height: 30,
                      padding:
                          EdgeInsets.symmetric(vertical: 8, horizontal: 10),
                      barBackgroundColor: Color.fromRGBO(0.0.0.0.5),
                      popIcon: Icon(
                        Icons.arrow_back,
                        size: 16,
                        color: Colors.white,
                      ),
                      contents: [
                        Center(
                          child: Container(
                            margin: EdgeInsets.symmetric(horizontal: 10),
                            child: Text(
                              '123',
                              style: TextStyle(color: Colors.white),
                            ),
                          ),
                        )
                      ], // Customize the display area in the middle of the top control bar
                      actions: [
                        GestureDetector(
                          onTap: () {
                            ///1.Can be used with custom extension elements, such as ads
                            setState(() {
                              showAdvertCover = true;
                            });
                            ///
                          },
                          child: Icon(
                            Icons.more_horiz,
                            size: 16,
                            color: Colors.white,
                          ),
                        )
                      ], // Customize the display area to the right of the top control bar
                      /// After cusotmBar is set, none of the above properties are valid (except`show`)
                      // customBar: Text("123123132")),),/// Click the back button on the top control bar
                  onpop: (value) {
                    print("Return to previous page");
                  },
                )
              : AspectRatio(
                  aspectRatio: 16 / 9,
                  child: Center(
                    child: CircularProgressIndicator(strokeWidth: 2.0),),),),),); }}Copy the code

Notes (Q&A)

  • You cannot use safeArea if you want to use vertical or horizontal video

  • The top control block or the bottom control block text or icon is clipped, adjust the font or icon size, can also adjust the control block height

  • The dataSoure of the video cannot be empty. If the dataSoure is empty, use the load view; otherwise, the player will report an error

    import 'package:flutter/material.dart';
    import 'package:awsome_video_player/awsome_video_player.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatefulWidget {
      @override
      _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
    
      String videoUrl = "https://www.runoob.com/try/demo_source/movie.mp4";
    
      @override
      void initState() {
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Awsome video player'),
            ),
            body: Center(
            	/// Normally videoUrl is returned from the server, and before it is returned,
            	/// We can use the load view to hold the spacechild: videoUrl ! ="" ? AwsomeVideoPlayer(
                videoUrl,
                /// Video Playback Configuration
                playOptions: VideoPlayOptions(
                  seekSeconds: 30,
                  aspectRatio: 16 / 9,
                  loop: true,
                  autoplay: true,
                  allowScrubbing: true,
                  startPosition: Duration(seconds: 0)),
              ) : AspectRatio(
                aspectRatio: 16 / 9,
                child: Center(
                  child: CircularProgressIndicator(strokeWidth: 2.0),),),),),); }}Copy the code
  • The children under AwsomeVideoPlayer only provides Align and tourists, the number of children will be higher than the lower one, and this will be continuously updated with some advanced documentation for custom expansion.

Write in the last

If you encounter any problems during the development process, please contact me through the following ways and I will reply to you as soon as possible:

  • Contact me on QQ: 604748948 QQ group: 160612343 wechat: Cheampie

  • Report

    • BUG

    • demand

    • advice

License

Copyright © 2020, Mark Chen. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.