// // JWPlayerManager.swift // WOKA // // Created by MacBook Pro on 24/06/24. // import UIKit import JWPlayerKit enum VideoContentType{ case liveStream case webSeries case trailer case continueWatching case audioBooks case games case songs } struct JwPlayerItemCreate{ var url : String var poster : String? var titles : String? } class JWPlayerManager { static let shared = JWPlayerManager() private init() {} func presentPlayer(from viewController: UIViewController,playerItems : [JwPlayerItemCreate], startIndex: Int = 0, contentType : VideoContentType , videoIDs : [Int],catID : Int? = nil, completion: (() -> Void)? = nil) { let sb = UIStoryboard(name: K.StoryBoard.theme, bundle: nil) let playerVC = sb.instantiateViewController(identifier: K.StoryBoardID.Theme.playerVC) as! PlayerVC do { // Create an array to hold the JWPlayerItems var items: [JWPlayerItem] = [] // Ensure the liveStreamURLs and titles arrays have the same count, if titles are provided // if let titles = titles, titles.count != liveStreamURLs.count { // print("Titles count does not match URLs count") // Utilities.dismissProgressHUD() // return // } switch contentType{ case .webSeries,.songs: // Iterate over the liveStreamURLs to create JWPlayerItems for (index, singleItem) in playerItems.enumerated() { guard let url = URL(string: singleItem.url) else { print("Invalid live stream URL at index \(index)") continue } let item = try JWPlayerItemBuilder() .file(url) .title(singleItem.titles ?? "") .posterImage(URL(string: singleItem.poster ?? "")!) .build() items.append(item) } case .liveStream: guard let liveStreamItem = playerItems.first else { print("Invalid live stream URL") return } let item = try JWPlayerItemBuilder() .file(URL(string: liveStreamItem.url)!) .title(liveStreamItem.titles ?? "Trailer") .build() items.append(item) case .trailer: guard let liveStreamItem = playerItems.first else { print("Invalid live stream URL") return } let item = try JWPlayerItemBuilder() .file(URL(string: liveStreamItem.url)!) .title(liveStreamItem.titles ?? "Trailer") .build() items.append(item) case .continueWatching, .audioBooks, .games: guard let liveStreamItem = playerItems.first else { print("Invalid live stream URL") return } let item = try JWPlayerItemBuilder() .file(URL(string: liveStreamItem.url)!) .title(liveStreamItem.titles ?? "Trailer") .build() items.append(item) } // Ensure there is at least one valid item guard !items.isEmpty else { print("No valid items to play") Utilities.dismissProgressHUD() return } // Create the ad break // let adBreakBuilder = JWAdBreakBuilder() // .offset(.preroll()) // .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=")!]) // // // // guard let adBreak = try? adBreakBuilder.build() else { // print("Ad error") // // Handle build error // return // } // // // Create the ad config // let adConfigBuilder = JWImaAdvertisingConfigBuilder() // .schedule([adBreak]) // guard let adConfig = try? adConfigBuilder.build() else { // // Handle build error // return // } // let adBreakBuilder1 = JWAdBreakBuilder() // .offset(.preroll()) // .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=")!]) // guard let adBreak1 = try? adBreakBuilder1.build() else { // // Handle build error // return // } // let adBreakBuilder = JWAdBreakBuilder() // .offset(.preroll()) // .tags([URL(string: generateAdTagUrl())!]) // guard let adBreak = try? adBreakBuilder.build() else { // print("Ad error") // // Handle build error // return // } // Create an ad break for 30% into the video let adBreakBuilder2 = JWAdBreakBuilder() .offset(.from(string: "pre")!) .tags([URL(string: generateAdTagUrl())!]) guard let adBreak2 = try? adBreakBuilder2.build() else { print("Ad error 1") // Handle build error return } // Create an ad break for 30% into the video let adBreakBuilder1 = JWAdBreakBuilder() .offset(.midroll(percent: 20)) // .offset(.from(string: "20%")!) .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250,728x90&gdfp_req=1&output=vast4&unviewed_position_start=1&env=vp&impl=s&correlator=7898879")!]) guard let adBreak1 = try? adBreakBuilder1.build() else { print("Ad error 2") // Handle build error return } let adBreakBuilder3 = JWAdBreakBuilder() .offset(.midroll(percent: 50)) // .offset(.from(string: "50%")!) .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=60")!]) guard let adBreak3 = try? adBreakBuilder3.build() else { print("Ad error 2") // Handle build error return } let adBreakBuilder4 = JWAdBreakBuilder() .offset(.midroll(percent: 80)) // .offset(.from(string: "50%")!) .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=90")!]) guard let adBreak4 = try? adBreakBuilder4.build() else { print("Ad error 2") // Handle build error return } // Create an ad break for 30% into the video // let adBreakBuilder3 = JWAdBreakBuilder() // .offset(.postroll()) // .tags([URL(string: "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250%2C728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=60")!]) // // guard let adBreak3 = try? adBreakBuilder3.build() else { // // Handle build error // return // } let adConfigBuilder = JWImaAdvertisingConfigBuilder() .schedule([adBreak1,adBreak3, adBreak4]) guard let adConfig = try? adConfigBuilder.build() else { // Handle build error return } let finalConfig : JWPlayerConfiguration? switch contentType{ case .audioBooks: finalConfig = try JWPlayerConfigurationBuilder() .playlist(items: items) .autostart(true) .build() case .webSeries: finalConfig = try JWPlayerConfigurationBuilder() .playlist(items: items) .autostart(false) .advertising(adConfig) // .playerId("X57dFDmV") .build() case .trailer: finalConfig = try JWPlayerConfigurationBuilder() .playlist(items: items) .autostart(true) .build() default: // Create a JWPlayerConfiguration with the playlist finalConfig = try JWPlayerConfigurationBuilder() .playlist(items: items) .autostart(false) .build() } DispatchQueue.main.async { playerVC.videoIndex = startIndex playerVC.contentType = contentType playerVC.config = finalConfig playerVC.vm.videoIDs = videoIDs playerVC.vm.catID = catID playerVC.modalPresentationStyle = .fullScreen playerVC.modalTransitionStyle = .crossDissolve // Present the PlayerVC Utilities.dismissProgressHUD() viewController.present(playerVC, animated: true) { if contentType == .webSeries{ playerVC.player.loadPlayerItemAt(index: startIndex) } completion?() // playerVC.transitionToFullScreen(animated: true) { // print("FullScreen") // } } } } catch { print("Error creating JWPlayer configuration: \(error)") Utilities.dismissProgressHUD() } } } func generateAdTagUrl() -> String { let correlatorValue = Int(Date().timeIntervalSince1970 * 1000) return "https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/single_preroll_skippable&sz=640x480&ciu_szs=300x250,728x90&gdfp_req=1&output=vast&unviewed_position_start=1&env=vp&impl=s&correlator=\(correlatorValue)" }