diff --git a/VERIFICATION-0.75.0.md b/VERIFICATION-0.75.0.md new file mode 100644 index 0000000..2183572 --- /dev/null +++ b/VERIFICATION-0.75.0.md @@ -0,0 +1,7 @@ +# Orbit TV 0.75.0: longer film lists + +0.74 filled film channels by rating, and the picks weren't good enough: UFC events and wrestling shows in Action, and obscure films with a perfect score from a few votes. None had reached a schedule. That fill is removed, and its picks were deleted from the box. + +Each film channel except After Dark now has a longer hand-picked list, about 100 films where they can be found: Premiere, Action, Sci-Fi, Horror, VHS, Romance, Wonder, PixelZ, Detour and BritX. Each channel reads its list once more, then a week's refresh as before. What's already planned stays, so repeats fade out over about a week. + +Checked: build, lint and all unit tests pass, plus that none of 0.74's picks were planned. Not checked until installed: how many of the new titles the library holds, which is reported after the read. diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index edecf39..d45346d 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -9,8 +9,8 @@ android { applicationId = "tv.orbit.classic" minSdk = 26 targetSdk = 36 - versionCode = 78 - versionName = "0.74.0-film-fill" + versionCode = 79 + versionName = "0.75.0-bigger-film-lists" } buildFeatures { compose = true } compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 } diff --git a/android/app/src/main/java/tv/orbit/classic/ChannelPresets.kt b/android/app/src/main/java/tv/orbit/classic/ChannelPresets.kt index d22abca..475d2e0 100644 --- a/android/app/src/main/java/tv/orbit/classic/ChannelPresets.kt +++ b/android/app/src/main/java/tv/orbit/classic/ChannelPresets.kt @@ -55,10 +55,10 @@ internal val ChannelPresets = listOf( ChannelPreset(204, "Dark Files", DarkFilesCrime + DarkFilesMysteries + DarkFilesParanormal, smartOnly = true), ChannelPreset(308, "Detour", listOf("American Pie", "American Pie 2", "American Wedding", "American Reunion", "Road Trip", "EuroTrip", "Harold & Kumar Go to White Castle", "Harold & Kumar Escape from Guantanamo Bay", "A Very Harold & Kumar Christmas", "The Hangover", "The Hangover Part II", "The Hangover Part III", "Van Wilder", "National Lampoon's Van Wilder", "Van Wilder: The Rise of Taj", "Van Wilder 2: The Rise of Taj", "Old School", "Sex Drive", "Accepted", "Superbad", "Pineapple Express", - "Dude, Where's My Car?", "Without a Paddle", "The Girl Next Door", "Not Another Teen Movie", "Project X", "21 & Over", "Beerfest", "Grandma's Boy", "Waiting..."), smartOnly = true, films = true), + "Dude, Where's My Car?", "Without a Paddle", "The Girl Next Door", "Not Another Teen Movie", "Project X", "21 & Over", "Beerfest", "Grandma's Boy", "Waiting...", "Wedding Crashers", "Step Brothers", "Anchorman: The Legend of Ron Burgundy", "Talladega Nights: The Ballad of Ricky Bobby", "Dodgeball: A True Underdog Story", "Zoolander", "Tropic Thunder", "The 40 Year Old Virgin", "Bad Santa", "Borat", "Jackass: The Movie", "Jackass Number Two", "Jackass 3D", "Scary Movie", "Scary Movie 2", "Scary Movie 3", "American Pie Presents: Band Camp", "Sausage Party", "This Is the End", "Neighbors", "21 Jump Street", "22 Jump Street", "Ted", "Ted 2", "Bridesmaids", "Horrible Bosses", "We're the Millers", "Due Date", "Get Him to the Greek", "Dumb and Dumber", "Dumb and Dumber To", "Ace Ventura: Pet Detective", "Ace Ventura: When Nature Calls", "Liar Liar", "The Mask", "Happy Gilmore", "Billy Madison", "The Waterboy", "Big Daddy", "Clerks", "Mallrats", "Clerks II", "Zack and Miri Make a Porno", "Idiocracy", "Napoleon Dynamite", "Office Space", "Half Baked", "Friday", "Next Friday", "Scott Pilgrim vs. the World", "Team America: World Police", "Rat Race", "Blades of Glory", "Semi-Pro", "The Other Guys", "Hot Rod", "Hot Tub Time Machine", "Tommy Boy", "Black Sheep", "Kingpin", "BASEketball"), smartOnly = true, films = true), ChannelPreset(309, "BritX", listOf("Shaun of the Dead", "Hot Fuzz", "The World's End", "Lock, Stock and Two Smoking Barrels", "Snatch", "RocknRolla", "Layer Cake", "Trainspotting", "T2 Trainspotting", "Green Street", "Green Street Hooligans", "The Football Factory", "Dog Soldiers", "Dead Man's Shoes", "28 Days Later", "28 Weeks Later", "This Is England", "The Gentlemen", "The Business", "The Firm", "Rise of the Footsoldier", "The 51st State", "Sexy Beast", - "The Bank Job", "The Long Good Friday", "Human Traffic", "Twin Town", "Shallow Grave", "Four Lions", "Severance", "Attack the Block", "The Descent", "In Bruges", "Filth", "Calibre", "Sightseers", "Sweet Sixteen"), smartOnly = true, films = true), + "The Bank Job", "The Long Good Friday", "Human Traffic", "Twin Town", "Shallow Grave", "Four Lions", "Severance", "Attack the Block", "The Descent", "In Bruges", "Filth", "Calibre", "Sightseers", "Sweet Sixteen", "Withnail & I", "The Full Monty", "Billy Elliot", "Bend It Like Beckham", "Kes", "Get Carter", "The Italian Job", "Quadrophenia", "Scum", "Made in Britain", "Nil by Mouth", "Gangster No. 1", "Mean Machine", "Kidulthood", "Adulthood", "Harry Brown", "The Krays", "Legend", "Bronson", "Eden Lake", "Kill List", "A Field in England", "Fish Tank", "The Inbetweeners Movie", "The Inbetweeners 2", "Alan Partridge", "Monty Python and the Holy Grail", "Life of Brian", "Monty Python's The Meaning of Life", "Ratcatcher", "Control", "Cockneys vs Zombies", "The Guard", "Hunger", "Lock Up", "Rise of the Footsoldier: Part II", "St Trinian's", "Death at a Funeral", "Hot Fuzz", "Kingsman: The Golden Circle", "Brassed Off", "East Is East", "Secrets & Lies", "My Beautiful Laundrette", "Local Hero", "Gregory's Girl", "Rita, Sue and Bob Too", "Educating Rita", "Shirley Valentine", "The Wicker Man", "Pride", "Sing Street", "Starter for 10", "Tyrannosaur", "Wild Bill", "Yardie"), smartOnly = true, films = true), ChannelPreset(611, "Orbit Junior", listOf("Thomas the Tank Engine & Friends", "Thomas & Friends", "Fireman Sam", "Postman Pat", "Brum", "Rosie and Jim", "Bob the Builder", "Pingu", "Noddy", "Teletubbies", "Tweenies", "Tots TV", "Pingu in the City", "Peppa Pig", "Bluey", "Bagpuss", "The Clangers", "Camberwick Green", "Trumpton", "Button Moon", "Rainbow", "Balamory", "Fimbles"), smartOnly = true), ChannelPreset(203, "Orbit Wild", listOf("The Crocodile Hunter", "Crocodile Hunter Diaries", "Deadliest Catch", "River Monsters", "Man vs. Wild", "Running Wild with Bear Grylls", "Survivorman", "Dual Survival", "Naked and Afraid", "Ice Road Truckers", @@ -67,16 +67,16 @@ internal val ChannelPresets = listOf( "Red Dwarf", "The Crystal Maze", "Robot Wars", "Gladiators", "Takeshi's Castle", "Gadget Show", "Top Gear", "Time Team", "Scrapheap Challenge", "Countdown", "Have I Got News for You", "QI", "Would I Lie to You?", "Pointless", "Mastermind", "University Challenge", "Mythbusters", "How It's Made"), smartOnly = true), ChannelPreset(612, "Wonder", listOf("Snow White and the Seven Dwarfs", "Pinocchio", "Dumbo", "Bambi", "Cinderella", "Alice in Wonderland", "Peter Pan", "Lady and the Tramp", "Sleeping Beauty", "One Hundred and One Dalmatians", "The Jungle Book", "The Aristocats", "Robin Hood", "The Fox and the Hound", "The Little Mermaid", "Beauty and the Beast", "Aladdin", "The Lion King", "Pocahontas", "The Hunchback of Notre Dame", "Hercules", "Mulan", "Tarzan", "The Emperor's New Groove", "Atlantis: The Lost Empire", "Lilo & Stitch", "Treasure Planet", "Brother Bear", "The Princess and the Frog", - "An American Tail", "The Land Before Time", "All Dogs Go to Heaven", "Anastasia", "The Secret of NIMH", "Thumbelina", "The Iron Giant", "The Prince of Egypt", "Spirited Away", "My Neighbor Totoro", "Kiki's Delivery Service", "Howl's Moving Castle", "Ponyo", "Princess Mononoke", "Castle in the Sky"), smartOnly = true, films = true), + "An American Tail", "The Land Before Time", "All Dogs Go to Heaven", "Anastasia", "The Secret of NIMH", "Thumbelina", "The Iron Giant", "The Prince of Egypt", "Spirited Away", "My Neighbor Totoro", "Kiki's Delivery Service", "Howl's Moving Castle", "Ponyo", "Princess Mononoke", "Castle in the Sky", "Fantasia", "Oliver & Company", "The Rescuers", "The Rescuers Down Under", "The Great Mouse Detective", "The Black Cauldron", "The Many Adventures of Winnie the Pooh", "Winnie the Pooh", "Fantasia 2000", "Home on the Range", "The Road to El Dorado", "Spirit: Stallion of the Cimarron", "Sinbad: Legend of the Seven Seas", "The Swan Princess", "Balto", "We're Back! A Dinosaur's Story", "A Goofy Movie", "Quest for Camelot", "Rock-a-Doodle", "The Pagemaster", "FernGully: The Last Rainforest", "Watership Down", "The Last Unicorn", "Charlotte's Web", "Whisper of the Heart", "Porco Rosso", "Pom Poko", "The Cat Returns", "Nausicaä of the Valley of the Wind", "The Secret World of Arrietty", "Song of the Sea", "The Secret of Kells", "Wolfwalkers", "Klaus", "The Nightmare Before Christmas", "Corpse Bride", "Coraline", "Kubo and the Two Strings", "ParaNorman", "Fantastic Mr. Fox", "Chicken Run", "Wallace & Gromit: The Curse of the Were-Rabbit", "Flushed Away", "The Wind Rises", "The Tale of Princess Kaguya", "From Up on Poppy Hill", "The Sword in the Stone", "The Hunchback of Notre Dame II", "An American Tail: Fievel Goes West", "The Land Before Time II: The Great Valley Adventure"), smartOnly = true, films = true), ChannelPreset(613, "PixelZ", listOf("Toy Story", "Toy Story 2", "Toy Story 3", "Toy Story 4", "A Bug's Life", "Monsters, Inc.", "Monsters University", "Finding Nemo", "Finding Dory", "The Incredibles", "Incredibles 2", "Cars", "Cars 2", "Cars 3", "Ratatouille", "WALL·E", "Up", "Brave", "Inside Out", "Coco", "Luca", "Soul", - "Shrek", "Shrek 2", "Shrek the Third", "Shrek Forever After", "Puss in Boots", "Madagascar", "Madagascar: Escape 2 Africa", "Kung Fu Panda", "Kung Fu Panda 2", "How to Train Your Dragon", "How to Train Your Dragon 2", "Megamind", "Antz", "Ice Age", "Ice Age: The Meltdown", "Despicable Me", "Despicable Me 2", "Minions", "The Lego Movie", "Tangled", "Frozen", "Moana", "Zootopia", "Big Hero 6", "Wreck-It Ralph", "Rio", "Robots"), smartOnly = true, films = true), + "Shrek", "Shrek 2", "Shrek the Third", "Shrek Forever After", "Puss in Boots", "Madagascar", "Madagascar: Escape 2 Africa", "Kung Fu Panda", "Kung Fu Panda 2", "How to Train Your Dragon", "How to Train Your Dragon 2", "Megamind", "Antz", "Ice Age", "Ice Age: The Meltdown", "Despicable Me", "Despicable Me 2", "Minions", "The Lego Movie", "Tangled", "Frozen", "Moana", "Zootopia", "Big Hero 6", "Wreck-It Ralph", "Rio", "Robots", "Cloudy with a Chance of Meatballs", "Hotel Transylvania", "Hotel Transylvania 2", "Trolls", "Sing", "The Secret Life of Pets", "Despicable Me 3", "Monsters vs Aliens", "Meet the Robinsons", "Chicken Little", "Bolt", "The Croods", "Turbo", "Rise of the Guardians", "Epic", "Ice Age: Dawn of the Dinosaurs", "Ice Age: Continental Drift", "Happy Feet", "Over the Hedge", "Shark Tale", "Bee Movie", "Puss in Boots: The Last Wish", "Madagascar 3: Europe's Most Wanted", "Kung Fu Panda 3", "How to Train Your Dragon: The Hidden World", "Frozen II", "Encanto", "Raya and the Last Dragon", "Ralph Breaks the Internet", "Onward", "Elemental", "Lightyear", "Turning Red", "The Good Dinosaur", "The Wild Robot", "The LEGO Batman Movie", "The Lego Ninjago Movie", "Storks", "Ferdinand", "The Boss Baby", "The Smurfs", "Open Season", "Surf's Up", "Dinosaur", "The Polar Express", "Monster House", "Rango", "Spider-Man: Into the Spider-Verse", "Spider-Man: Across the Spider-Verse", "The Mitchells vs. the Machines", "Luck"), smartOnly = true, films = true), ChannelPreset(306, "Orbit VHS", listOf("Back to the Future", "Back to the Future Part II", "Back to the Future Part III", "The Goonies", "Gremlins", "Gremlins 2: The New Batch", "Ghostbusters", "Ghostbusters II", "E.T. the Extra-Terrestrial", "Honey, I Shrunk the Kids", "Flight of the Navigator", "The NeverEnding Story", "Labyrinth", "Willow", "The Princess Bride", "Short Circuit", "Batteries Not Included", "Explorers", "Stand by Me", "The Karate Kid", "The Karate Kid Part II", - "Ferris Bueller's Day Off", "The Breakfast Club", "Weird Science", "Teen Wolf", "Bill & Ted's Excellent Adventure", "Bill & Ted's Bogus Journey", "Wayne's World", "Big", "Home Alone", "Home Alone 2: Lost in New York", "Beetlejuice", "Hook", "Jumanji", "Mrs. Doubtfire", "Mac and Me", "Police Academy", "Top Gun", "Crocodile Dundee", "Who Framed Roger Rabbit", "Howard the Duck", "Masters of the Universe", "Innerspace", "Big Trouble in Little China", "Three Amigos", "Spaceballs"), smartOnly = true, films = true), - ChannelPreset(303, "Orbit Sci-Fi", listOf("2001: A Space Odyssey", "Star Wars", "The Empire Strikes Back", "Return of the Jedi", "Alien", "Aliens", "Blade Runner", "The Terminator", "Terminator 2: Judgment Day", "RoboCop", "Total Recall", "Predator", "Stargate", "Starship Troopers", "The Fifth Element", "Contact", "Gattaca", "Dark City", "The Matrix", "Pitch Black", "Event Horizon", "Sunshine", "Moon", "District 9", "Inception", "Interstellar", "Gravity", "The Martian", "Arrival", "Ex Machina", "Dune", "Edge of Tomorrow", "Minority Report", "Looper", "Children of Men", "Star Trek II: The Wrath of Khan", "Star Trek: First Contact", "Star Trek", "Tron", "Close Encounters of the Third Kind", "The Abyss", "Independence Day", "Men in Black", "Serenity", "Planet of the Apes", "Soylent Green", "Logan's Run", "Primer"), smartOnly = true, films = true), - ChannelPreset(304, "Orbit Horror", listOf("A Nightmare on Elm Street", "Friday the 13th", "The Texas Chain Saw Massacre", "Night of the Living Dead", "Dawn of the Dead", "The Exorcist", "The Omen", "The Shining", "Carrie", "Pet Sematary", "It", "Misery", "Child's Play", "Candyman", "Jaws", "The Blair Witch Project", "The Ring", "Saw", "Hostel", "The Descent", "Insidious", "The Conjuring", "Sinister", "Hereditary", "Midsommar", "The Witch", "It Follows", "Get Out", "A Quiet Place", "Rosemary's Baby", "Psycho", "The Birds", "Black Christmas", "Sleepaway Camp", "Maniac", "The Hills Have Eyes", "Critters", "Leprechaun", "Pumpkinhead", "Army of Darkness", "Evil Dead II", "Braindead", "The Mist", "Drag Me to Hell", "The Babadook", "Train to Busan", "Ringu", "Barbarian"), smartOnly = true, films = true), - ChannelPreset(302, "Orbit Action", listOf("Die Hard", "Die Hard 2", "Die Hard with a Vengeance", "Lethal Weapon", "Lethal Weapon 2", "Commando", "Rambo: First Blood", "First Blood", "Rocky", "Cobra", "Tango & Cash", "Demolition Man", "Speed", "The Rock", "Con Air", "Face/Off", "Heat", "Point Break", "Bad Boys", "Enter the Dragon", "Rush Hour", "Police Story", "Bloodsport", "Kickboxer", "Under Siege", "Hard Target", "Mortal Kombat", "Blade", "John Wick", "John Wick: Chapter 2", "Taken", "The Raid", "Mad Max", "Mad Max 2", "Mad Max: Fury Road", "The Bourne Identity", "The Bourne Supremacy", "The Bourne Ultimatum", "Casino Royale", "GoldenEye", "Mission: Impossible", "Gladiator", "The Fast and the Furious", "The Transporter", "Crank", "Kill Bill: Vol. 1", "Kill Bill: Vol. 2", "The Expendables", "Dredd", "Sicario"), smartOnly = true, films = true), - ChannelPreset(307, "Orbit Romance", listOf("Pretty Woman", "When Harry Met Sally...", "Sleepless in Seattle", "You've Got Mail", "Notting Hill", "Four Weddings and a Funeral", "Love Actually", "Bridget Jones's Diary", "About Time", "Titanic", "Ghost", "Dirty Dancing", "The Notebook", "Crazy, Stupid, Love.", "10 Things I Hate About You", "She's All That", "Clueless", "The Holiday", "The Proposal", "Hitch", "Maid in Manhattan", "Runaway Bride", "My Best Friend's Wedding", "While You Were Sleeping", "Serendipity", "How to Lose a Guy in 10 Days", "13 Going on 30", "The Wedding Singer", "50 First Dates", "There's Something About Mary", "La La Land", "The Princess Diaries", "Mamma Mia!", "Grease", "Casablanca", "Roman Holiday", "Breakfast at Tiffany's", "Amélie", "Pride & Prejudice", "Sense and Sensibility", "Crazy Rich Asians", "Me Before You", "Forrest Gump", "Jerry Maguire", "Shakespeare in Love"), smartOnly = true, films = true), - ChannelPreset(301, "Orbit Premiere", listOf("Jurassic Park", "The Lost World: Jurassic Park", "Raiders of the Lost Ark", "Indiana Jones and the Temple of Doom", "Indiana Jones and the Last Crusade", "Superman", "Batman", "Batman Returns", "Batman Begins", "The Dark Knight", "The Dark Knight Rises", "Spider-Man", "Spider-Man 2", "X-Men", "X2", "Iron Man", "The Avengers", "Avengers: Infinity War", "Avengers: Endgame", "Black Panther", "Guardians of the Galaxy", "The Lord of the Rings: The Fellowship of the Ring", "The Lord of the Rings: The Two Towers", "The Lord of the Rings: The Return of the King", "Harry Potter and the Philosopher's Stone", "Pirates of the Caribbean: The Curse of the Black Pearl", "Avatar", "Transformers", "Armageddon", "Twister", "Top Gun: Maverick", "The Mummy", "The Mask of Zorro", "Braveheart", "Skyfall", "Mission: Impossible - Fallout", "King Kong", "Godzilla", "Pacific Rim", "Wonder Woman", "Oppenheimer"), smartOnly = true, films = true), + "Ferris Bueller's Day Off", "The Breakfast Club", "Weird Science", "Teen Wolf", "Bill & Ted's Excellent Adventure", "Bill & Ted's Bogus Journey", "Wayne's World", "Big", "Home Alone", "Home Alone 2: Lost in New York", "Beetlejuice", "Hook", "Jumanji", "Mrs. Doubtfire", "Mac and Me", "Police Academy", "Top Gun", "Crocodile Dundee", "Who Framed Roger Rabbit", "Howard the Duck", "Masters of the Universe", "Innerspace", "Big Trouble in Little China", "Three Amigos", "Spaceballs", "Short Circuit 2", "Adventures in Babysitting", "Uncle Buck", "Planes, Trains and Automobiles", "National Lampoon's Vacation", "National Lampoon's European Vacation", "National Lampoon's Christmas Vacation", "Airplane!", "The Naked Gun: From the Files of Police Squad!", "The Naked Gun 2½: The Smell of Fear", "Hot Shots!", "Police Academy 2: Their First Assignment", "Trading Places", "Coming to America", "Beverly Hills Cop", "Beverly Hills Cop II", "48 Hrs.", "Twins", "Kindergarten Cop", "Honey, I Blew Up the Kid", "Dragnet", "Caddyshack", "Stripes", "Tootsie", "The Blues Brothers", "Sixteen Candles", "Pretty in Pink", "St. Elmo's Fire", "Say Anything...", "Heathers", "Better Off Dead", "Can't Buy Me Love", "Back to School", "Real Genius", "D.A.R.Y.L.", "The Last Starfighter", "Cocoon", "The Dark Crystal", "Time Bandits", "Legend", "Krull", "Conan the Barbarian", "Red Sonja", "Highlander", "Mannequin", "Harry and the Hendersons", "The Witches", "Hocus Pocus", "Jumanji", "The Mighty Ducks", "Cool Runnings"), smartOnly = true, films = true), + ChannelPreset(303, "Orbit Sci-Fi", listOf("2001: A Space Odyssey", "Star Wars", "The Empire Strikes Back", "Return of the Jedi", "Alien", "Aliens", "Blade Runner", "The Terminator", "Terminator 2: Judgment Day", "RoboCop", "Total Recall", "Predator", "Stargate", "Starship Troopers", "The Fifth Element", "Contact", "Gattaca", "Dark City", "The Matrix", "Pitch Black", "Event Horizon", "Sunshine", "Moon", "District 9", "Inception", "Interstellar", "Gravity", "The Martian", "Arrival", "Ex Machina", "Dune", "Edge of Tomorrow", "Minority Report", "Looper", "Children of Men", "Star Trek II: The Wrath of Khan", "Star Trek: First Contact", "Star Trek", "Tron", "Close Encounters of the Third Kind", "The Abyss", "Independence Day", "Men in Black", "Serenity", "Planet of the Apes", "Soylent Green", "Logan's Run", "Primer", "Blade Runner 2049", "Dune: Part Two", "Alien 3", "Alien Resurrection", "Prometheus", "Terminator 3: Rise of the Machines", "Terminator Salvation", "The Matrix Reloaded", "The Matrix Revolutions", "Twelve Monkeys", "Brazil", "A Clockwork Orange", "V for Vendetta", "Her", "Rogue One: A Star Wars Story", "Solo: A Star Wars Story", "Star Wars: Episode I - The Phantom Menace", "Star Wars: Episode II - Attack of the Clones", "Star Wars: Episode III - Revenge of the Sith", "Star Wars: The Force Awakens", "Star Wars: The Last Jedi", "Star Wars: The Rise of Skywalker", "Star Trek: The Motion Picture", "Star Trek III: The Search for Spock", "Star Trek IV: The Voyage Home", "Star Trek Into Darkness", "Star Trek Beyond", "Elysium", "Oblivion", "Source Code", "In Time", "I, Robot", "A.I. Artificial Intelligence", "War of the Worlds", "Predator 2", "RoboCop 2", "Deep Impact", "Annihilation", "Upgrade", "Tenet", "Ad Astra", "Passengers", "Lucy", "Limitless", "Galaxy Quest", "Flash Gordon", "Silent Running", "The Day the Earth Stood Still", "Forbidden Planet", "Westworld", "The Andromeda Strain", "Serenity"), smartOnly = true, films = true), + ChannelPreset(304, "Orbit Horror", listOf("A Nightmare on Elm Street", "Friday the 13th", "The Texas Chain Saw Massacre", "Night of the Living Dead", "Dawn of the Dead", "The Exorcist", "The Omen", "The Shining", "Carrie", "Pet Sematary", "It", "Misery", "Child's Play", "Candyman", "Jaws", "The Blair Witch Project", "The Ring", "Saw", "Hostel", "The Descent", "Insidious", "The Conjuring", "Sinister", "Hereditary", "Midsommar", "The Witch", "It Follows", "Get Out", "A Quiet Place", "Rosemary's Baby", "Psycho", "The Birds", "Black Christmas", "Sleepaway Camp", "Maniac", "The Hills Have Eyes", "Critters", "Leprechaun", "Pumpkinhead", "Army of Darkness", "Evil Dead II", "Braindead", "The Mist", "Drag Me to Hell", "The Babadook", "Train to Busan", "Ringu", "Barbarian", "A Nightmare on Elm Street 3: Dream Warriors", "Friday the 13th Part 2", "Halloween II", "Scream 2", "Scream 3", "Sinister 2", "Insidious: Chapter 2", "The Conjuring 2", "Annabelle", "Annabelle: Creation", "The Nun", "It Chapter Two", "Saw II", "Saw III", "The Cabin in the Woods", "Cloverfield", "[REC]", "The Orphanage", "Let the Right One In", "Let Me In", "Paranormal Activity", "Paranormal Activity 2", "The Purge", "Us", "Nope", "Smile", "Talk to Me", "Final Destination", "Final Destination 2", "Final Destination 3", "Wrong Turn", "House of 1000 Corpses", "The Devil's Rejects", "Jeepers Creepers", "The Strangers", "You're Next", "Hush", "The Autopsy of Jane Doe", "Gerald's Game", "Doctor Sleep", "1408", "The Others", "The Sixth Sense", "Sleepy Hollow", "Pet Sematary Two", "Children of the Corn", "The Amityville Horror", "The Texas Chainsaw Massacre", "Hellbound: Hellraiser II", "Ghostwatch", "The Innocents", "The Haunting"), smartOnly = true, films = true), + ChannelPreset(302, "Orbit Action", listOf("Die Hard", "Die Hard 2", "Die Hard with a Vengeance", "Lethal Weapon", "Lethal Weapon 2", "Commando", "Rambo: First Blood", "First Blood", "Rocky", "Cobra", "Tango & Cash", "Demolition Man", "Speed", "The Rock", "Con Air", "Face/Off", "Heat", "Point Break", "Bad Boys", "Enter the Dragon", "Rush Hour", "Police Story", "Bloodsport", "Kickboxer", "Under Siege", "Hard Target", "Mortal Kombat", "Blade", "John Wick", "John Wick: Chapter 2", "Taken", "The Raid", "Mad Max", "Mad Max 2", "Mad Max: Fury Road", "The Bourne Identity", "The Bourne Supremacy", "The Bourne Ultimatum", "Casino Royale", "GoldenEye", "Mission: Impossible", "Gladiator", "The Fast and the Furious", "The Transporter", "Crank", "Kill Bill: Vol. 1", "Kill Bill: Vol. 2", "The Expendables", "Dredd", "Sicario", "Léon: The Professional", "Live Free or Die Hard", "A Good Day to Die Hard", "Lethal Weapon 3", "Lethal Weapon 4", "Rambo: First Blood Part II", "Rambo III", "Rambo", "Rocky II", "Rocky III", "Rocky IV", "Creed", "Bad Boys II", "Rush Hour 2", "Rush Hour 3", "2 Fast 2 Furious", "Fast Five", "Furious 7", "John Wick: Chapter 3 - Parabellum", "John Wick: Chapter 4", "The Equalizer", "Man on Fire", "Taken 2", "Collateral", "Ronin", "Hard Boiled", "The Killer", "Drunken Master", "Project A", "The Way of the Dragon", "Fist of Fury", "The Big Boss", "Ong-Bak", "The Raid 2", "Escape Plan", "The Expendables 2", "Kingsman: The Secret Service", "Tomorrow Never Dies", "The World Is Not Enough", "Die Another Day", "Quantum of Solace", "Goldfinger", "Dr. No", "From Russia with Love", "Thunderball", "Licence to Kill", "The Living Daylights", "Mr. & Mrs. Smith", "Olympus Has Fallen", "London Has Fallen", "White House Down", "Air Force One", "Cliffhanger", "Passenger 57", "Timecop", "Universal Soldier", "Road House", "Crank"), smartOnly = true, films = true), + ChannelPreset(307, "Orbit Romance", listOf("Pretty Woman", "When Harry Met Sally...", "Sleepless in Seattle", "You've Got Mail", "Notting Hill", "Four Weddings and a Funeral", "Love Actually", "Bridget Jones's Diary", "About Time", "Titanic", "Ghost", "Dirty Dancing", "The Notebook", "Crazy, Stupid, Love.", "10 Things I Hate About You", "She's All That", "Clueless", "The Holiday", "The Proposal", "Hitch", "Maid in Manhattan", "Runaway Bride", "My Best Friend's Wedding", "While You Were Sleeping", "Serendipity", "How to Lose a Guy in 10 Days", "13 Going on 30", "The Wedding Singer", "50 First Dates", "There's Something About Mary", "La La Land", "The Princess Diaries", "Mamma Mia!", "Grease", "Casablanca", "Roman Holiday", "Breakfast at Tiffany's", "Amélie", "Pride & Prejudice", "Sense and Sensibility", "Crazy Rich Asians", "Me Before You", "Forrest Gump", "Jerry Maguire", "Shakespeare in Love", "Moulin Rouge!", "Bridget Jones: The Edge of Reason", "Hope Floats", "Sweet Home Alabama", "The Wedding Planner", "Legally Blonde", "Miss Congeniality", "Never Been Kissed", "A Walk to Remember", "The Lake House", "P.S. I Love You", "Dear John", "Valentine's Day", "New Year's Eve", "He's Just Not That Into You", "27 Dresses", "Knocked Up", "Forgetting Sarah Marshall", "(500) Days of Summer", "Eternal Sunshine of the Spotless Mind", "Before Sunrise", "Before Sunset", "Sabrina", "An Officer and a Gentleman", "Top Hat", "Singin' in the Rain", "West Side Story", "My Fair Lady", "The Sound of Music", "Gone with the Wind", "City of Angels", "The Bodyguard", "French Kiss", "Green Card", "Working Girl", "Moonstruck", "Annie Hall", "Mamma Mia! Here We Go Again", "About a Boy", "Music and Lyrics", "Two Weeks Notice", "Just Like Heaven", "What Women Want", "Something's Gotta Give", "It's Complicated", "Easy A", "Love & Basketball", "The Best Man", "Pride and Prejudice", "Emma", "Atonement", "Brooklyn", "The Big Sick"), smartOnly = true, films = true), + ChannelPreset(301, "Orbit Premiere", listOf("Jurassic Park", "The Lost World: Jurassic Park", "Raiders of the Lost Ark", "Indiana Jones and the Temple of Doom", "Indiana Jones and the Last Crusade", "Superman", "Batman", "Batman Returns", "Batman Begins", "The Dark Knight", "The Dark Knight Rises", "Spider-Man", "Spider-Man 2", "X-Men", "X2", "Iron Man", "The Avengers", "Avengers: Infinity War", "Avengers: Endgame", "Black Panther", "Guardians of the Galaxy", "The Lord of the Rings: The Fellowship of the Ring", "The Lord of the Rings: The Two Towers", "The Lord of the Rings: The Return of the King", "Harry Potter and the Philosopher's Stone", "Pirates of the Caribbean: The Curse of the Black Pearl", "Avatar", "Transformers", "Armageddon", "Twister", "Top Gun: Maverick", "The Mummy", "The Mask of Zorro", "Braveheart", "Skyfall", "Mission: Impossible - Fallout", "King Kong", "Godzilla", "Pacific Rim", "Wonder Woman", "Oppenheimer", "Spider-Man: No Way Home", "Deadpool", "Logan", "Captain America: The Winter Soldier", "Captain America: Civil War", "Thor: Ragnarok", "Guardians of the Galaxy Vol. 2", "Avengers: Age of Ultron", "Doctor Strange", "Spider-Man: Homecoming", "Spider-Man 3", "Jurassic World", "Jurassic Park III", "Man of Steel", "Aquaman", "X-Men: Days of Future Past", "X-Men: First Class", "Harry Potter and the Chamber of Secrets", "Harry Potter and the Prisoner of Azkaban", "Harry Potter and the Goblet of Fire", "Harry Potter and the Order of the Phoenix", "Harry Potter and the Half-Blood Prince", "Harry Potter and the Deathly Hallows: Part 1", "Harry Potter and the Deathly Hallows: Part 2", "Pirates of the Caribbean: Dead Man's Chest", "Pirates of the Caribbean: At World's End", "The Hobbit: An Unexpected Journey", "The Hobbit: The Desolation of Smaug", "The Hobbit: The Battle of the Five Armies", "Top Gun", "Mission: Impossible - Ghost Protocol", "Mission: Impossible - Rogue Nation", "The Mummy Returns", "Transformers: Revenge of the Fallen", "Transformers: Dark of the Moon", "World War Z", "I Am Legend", "Ready Player One", "Jumanji: Welcome to the Jungle", "National Treasure", "The Da Vinci Code", "Ocean's Eleven", "Ocean's Twelve", "Ocean's Thirteen", "Cast Away", "Spectre", "No Time to Die", "The Greatest Showman", "Saving Private Ryan", "Apollo 13", "The Fugitive", "Sherlock Holmes", "Inglourious Basterds", "The Revenant", "Dunkirk", "Joker", "Barbie"), smartOnly = true, films = true), ChannelPreset(202, "Odyssey", listOf("Cosmos", "Cosmos: A Spacetime Odyssey", "Wonders of the Universe", "Wonders of the Solar System", "The Universe", "How the Universe Works", "Civilisation", "Civilizations", "Connections", "The Ascent of Man", "The World at War", "Band of Brothers", "The Vietnam War", "The Civil War", "Apollo 11", "Horizon", "Seconds from Disaster", "Air Crash Investigation", "Mayday", "Engineering the Impossible", "Impossible Engineering", "Extreme Engineering", "Big Bigger Biggest", "Ancient Apocalypse", "Rome's Greatest Battles", "The Story of India", "Egypt's Lost Cities", "Long Way Round", "Long Way Down", "Parts Unknown", "An Idiot Abroad", "Michael Palin's Himalaya", "Pole to Pole", "Around the World in 80 Days", "James May's Man Lab", "The Story of Maths", "Walking with Dinosaurs"), smartOnly = true), ChannelPreset(401, "Ring X", RingXMondayNight + RingXImpact + RingXAew + RingXVault, smartOnly = true)) diff --git a/android/app/src/main/java/tv/orbit/classic/ChannelSchedule.kt b/android/app/src/main/java/tv/orbit/classic/ChannelSchedule.kt index 85203b8..bdb2791 100644 --- a/android/app/src/main/java/tv/orbit/classic/ChannelSchedule.kt +++ b/android/app/src/main/java/tv/orbit/classic/ChannelSchedule.kt @@ -59,7 +59,7 @@ internal val SmartChannels = listOf( "Hostile Planet", "Africa", "Wild China", "South Pacific", "Great Barrier Reef", "The Hunt", "The Life of Mammals", "The Life of Birds", "Nature's Great Events", "Green Planet", "Prehistoric Planet"), seriesCount = 20, finishTogether = true, exactTitles = true), ChannelProgramming(106, "Paradox", ChannelPresets.first { it.number == 106 }.searches)) + - ChannelPresets.filter { it.smartOnly }.map { ChannelProgramming(it.number, it.name, it.searches, seriesCount = 60, finishTogether = !it.films, exactTitles = true, + ChannelPresets.filter { it.smartOnly }.map { ChannelProgramming(it.number, it.name, it.searches, seriesCount = if (it.films) it.searches.size else 60, finishTogether = !it.films, exactTitles = true, filmRestMs = if (it.films) 7 * 24 * 60 * 60_000L else null, suggestionRules = SmartChannelRules[it.number].orEmpty(), dayParts = SmartChannelParts[it.number].orEmpty()) } @@ -86,9 +86,6 @@ private val SmartChannelRules: Map> get() = mapOf( 302 to listOf(SuggestionRule("all", "Action", "Movie", listOf("Action"), 1980..2025, 6.5f, emptySet(), 60, setOf("Animation", "Documentary", "Family", "Horror"), 70)), 307 to listOf(SuggestionRule("all", "Romantic comedy", "Movie", listOf("Romance", "Comedy"), 1985..2025, 6.5f, emptySet(), 60, setOf("Animation", "Documentary", "Horror"), 70)), 301 to listOf(SuggestionRule("all", "Big event films", "Movie", listOf("Adventure", "Action"), 1975..2025, 7.5f, emptySet(), 40, setOf("Animation", "Documentary"), 80)), - 612 to listOf(SuggestionRule("all", "Classic family animation", "Movie", listOf("Animation", "Family"), 1937..2000, 6.5f, setOf("NC-17", "X", "R"), 60, setOf("Documentary"), 55)), - 613 to listOf(SuggestionRule("all", "Modern family animation", "Movie", listOf("Animation", "Family"), 2001..2025, 6.5f, setOf("NC-17", "X", "R"), 60, setOf("Documentary", "Anime"), 55)), - 308 to listOf(SuggestionRule("all", "Teen and road comedy", "Movie", listOf("Comedy"), 1995..2015, 5.5f, setOf("G", "PG", "TV-G", "U"), 70, setOf("Family", "Animation", "Documentary", "Horror", "Drama"), 70, 7.8f)), 202 to listOf(SuggestionRule("all", "History and science", "Series", listOf("Documentary", "History"), 1970..2025, 7f, emptySet(), 30, setOf("Crime", "Animation"))), 107 to listOf(SuggestionRule("all", "Crime drama", "Series", listOf("Crime", "Drama"), 1985..2022, 7f, emptySet(), 40, setOf("Documentary", "Animation")))) diff --git a/android/app/src/main/java/tv/orbit/classic/ChannelScheduler.kt b/android/app/src/main/java/tv/orbit/classic/ChannelScheduler.kt index cfadfec..121dbc9 100644 --- a/android/app/src/main/java/tv/orbit/classic/ChannelScheduler.kt +++ b/android/app/src/main/java/tv/orbit/classic/ChannelScheduler.kt @@ -4,15 +4,6 @@ import android.util.Log internal const val POOL_REFRESH_MS = 7 * 24 * 60 * 60_000L -/** About a week of films back to back, so one needn't repeat before its rest is up. */ -internal const val FILM_POOL_TARGET = 100 - -/** Biggest channels first, as a film goes to whichever channel takes it first. */ -internal val FilmFillOrder = listOf(301, 302, 303, 304, 306, 307, 612, 613, 308) - -internal fun needsFilmFill(programming: ChannelProgramming, films: Int) = - programming.filmRestMs != null && programming.suggestionRules.isNotEmpty() && films < FILM_POOL_TARGET - /** Only counts and times, so it's safe to log. Never titles, addresses or the account. */ internal class SchedulerReport(val programmes: Int, val episodes: Int, val shows: List, val requests: Int, val fetchMs: Long, val planMs: Long, val bytes: Long, val fromCache: Boolean, val endMs: Long) { @@ -49,30 +40,6 @@ internal class ChannelScheduler(private val store: ScheduleStore, private val cl return plan } - /** - * Fills a film channel from the library until it has enough for a week with no repeats, by its own rules. New titles join from its - * next top-up, and what's already planned stays. Anything can be taken out under Titles, and then never comes back. Once a week at most. - */ - fun fillFilmPool(session: EmbySampleSession, userId: String, programming: ChannelProgramming, loop: SampleChannel): Boolean { - val number = programming.number - val now = clock() - val pool = store.loadPool(userId, number) ?: return false - if (!needsFilmFill(programming, pool.series.size)) return false - if (now - store.loadFilled(userId)[number].orZero() < POOL_REFRESH_MS) return false - val choices = store.loadChoices(userId, number) - val taken = SmartChannels.filter { it.filmRestMs != null && it.number != number }.flatMap { store.loadPool(userId, it.number)?.series.orEmpty() }.map { seriesKey(it.title) }.toSet() - val read = session.suggestFor(programming.suggestionRules, pool.series.map { it.id }.toSet() + choices.accepted.map { it.id }, choices.rejected, taken) - val added = read.suggestions.take(FILM_POOL_TARGET - pool.series.size) - store.saveFilled(userId, store.loadFilled(userId) + (number to now)) - if (added.isEmpty()) return false - store.saveChoices(userId, number, ChannelChoices(choices.accepted + added, choices.rejected)) - topUp(session, userId, programming, loop) - Log.i("OrbitSchedule", "channel=$number filmsAdded=${added.size} requests=${read.requests}") - return true - } - - private fun Long?.orZero() = this ?: 0L - /** A file that wouldn't play. It stays in what's already planned, and is left out from here on. */ fun markFailed(userId: String, itemId: String) { store.saveFailed(userId, store.loadFailed(userId) + itemId) diff --git a/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt b/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt index 5d4fa8a..bba1944 100644 --- a/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt +++ b/android/app/src/main/java/tv/orbit/classic/EmbyClient.kt @@ -66,7 +66,7 @@ internal class HttpsEmbyTransport(internal val deviceId: String = UUID.randomUUI connection.connectTimeout = 10_000 connection.readTimeout = request.readTimeoutMs ?: if (request.path == "/Sessions/Logout") 5_000 else 15_000 connection.setRequestProperty("Accept", "application/json") - connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.74.0\"") + connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.75.0\"") request.token?.let { connection.setRequestProperty("X-Emby-Token", it) } if (request.method == "POST") { val bytes = request.body.orEmpty().toByteArray(Charsets.UTF_8) diff --git a/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt b/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt index 7149a85..5a11943 100644 --- a/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt +++ b/android/app/src/main/java/tv/orbit/classic/EmbyConnectionScreen.kt @@ -263,18 +263,6 @@ internal fun EmbyConnectionScreen(modifier: Modifier = Modifier, visible: Boolea try { driveInPlan = withContext(Dispatchers.IO) { scheduler.topUpDriveIn(active.accountId) } } catch (cancelled: CancellationException) { throw cancelled } catch (_: Exception) { /* Tried again next hour. */ } - // Quiet, and one at a time, so the provider is never rushed. - for (programming in FilmFillOrder.mapNotNull { number -> SmartChannels.firstOrNull { it.number == number } }) { - val loop = smartLoop(programming) ?: continue - try { - val filled = withContext(Dispatchers.IO) { scheduler.fillFilmPool(active, active.accountId, programming, loop) } - if (filled) { - withContext(Dispatchers.IO) { scheduleStore.loadPlan(active.accountId, programming.number) }?.let { fresh -> scheduledChannels[programming.number]?.plan = fresh } - delay(20_000) - } - } catch (cancelled: CancellationException) { throw cancelled } - catch (_: Exception) { /* Tried again next week. */ } - } delay(60 * 60_000L) } } diff --git a/android/app/src/main/java/tv/orbit/classic/ScheduleStore.kt b/android/app/src/main/java/tv/orbit/classic/ScheduleStore.kt index 8af2a38..b5ad229 100644 --- a/android/app/src/main/java/tv/orbit/classic/ScheduleStore.kt +++ b/android/app/src/main/java/tv/orbit/classic/ScheduleStore.kt @@ -140,14 +140,6 @@ internal class ScheduleStore(private val directory: File) { (0 until items.length()).map { validId(items.getString(it)) }.toSet() }.orEmpty() - /** When each channel's films were last filled in automatically. */ - fun saveFilled(userId: String, filled: Map) = - write(file("filled", 0), root(userId, 0).put("filled", JSONObject().also { saved -> filled.forEach { (number, at) -> saved.put(number.toString(), at) } })) - fun loadFilled(userId: String): Map = read(file("filled", 0), userId, 0) { root -> - val saved = root.getJSONObject("filled") - saved.keys().asSequence().associate { it.toInt() to saved.getLong(it) } - }.orEmpty() - /** Drive-In tickets, by the bill's start time, with how far their reminders have got. */ fun saveTickets(userId: String, tickets: Map) = write(file("tickets", 0), root(userId, 0).put("tickets", JSONObject().also { saved -> tickets.forEach { (start, stage) -> saved.put(start.toString(), stage) } })) diff --git a/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt b/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt index fc268be..bfa766c 100644 --- a/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt +++ b/android/app/src/main/java/tv/orbit/classic/SecureMediaDataSource.kt @@ -33,7 +33,7 @@ internal class SecureMediaDataSource(private val session: EmbySampleSession) : B next.instanceFollowRedirects = false next.connectTimeout = 10_000 next.readTimeout = 20_000 - next.setRequestProperty("User-Agent", "OrbitTV/0.74.0") + next.setRequestProperty("User-Agent", "OrbitTV/0.75.0") next.setRequestProperty("Accept-Encoding", "identity") session.mediaHeaders(address).forEach { (key, value) -> next.setRequestProperty(key, value) } if (dataSpec.position != 0L || dataSpec.length != C.LENGTH_UNSET.toLong()) { diff --git a/android/app/src/test/java/tv/orbit/classic/ChannelPresetsTest.kt b/android/app/src/test/java/tv/orbit/classic/ChannelPresetsTest.kt index 1968bd1..1c8f35b 100644 --- a/android/app/src/test/java/tv/orbit/classic/ChannelPresetsTest.kt +++ b/android/app/src/test/java/tv/orbit/classic/ChannelPresetsTest.kt @@ -242,4 +242,9 @@ class ChannelPresetsTest { migrateChannelNumbers(folder) assertEquals("orbit 2", read(folder, "schedule-102.json").getString("marker")) } + + @Test fun aFilmChannelCanUseItsWholeList() { + SmartChannels.filter { it.filmRestMs != null && it.number != AFTER_DARK_NUMBER }.forEach { assertEquals(it.searches.size, it.seriesCount) } + assertTrue(SmartChannels.first { it.number == 302 }.searches.size >= 100) + } } diff --git a/android/app/src/test/java/tv/orbit/classic/ChannelSuggestionsTest.kt b/android/app/src/test/java/tv/orbit/classic/ChannelSuggestionsTest.kt index 454b330..6b60d61 100644 --- a/android/app/src/test/java/tv/orbit/classic/ChannelSuggestionsTest.kt +++ b/android/app/src/test/java/tv/orbit/classic/ChannelSuggestionsTest.kt @@ -174,18 +174,4 @@ class ChannelSuggestionsTest { val read = findSuggestions(reply(*rows), user, { "t" }, listOf(rule), emptySet(), emptySet(), takenTitles = setOf(seriesKey("Taken Film"))) assertEquals(listOf("b"), read.suggestions.map { it.id }) } - - @Test fun onlyFilmChannelsWithRulesAndRoomAreFilled() { - val premiere = SmartChannels.first { it.number == 301 } - assertTrue(needsFilmFill(premiere, 41)) - assertFalse(needsFilmFill(premiere, FILM_POOL_TARGET)) - assertFalse(needsFilmFill(SmartChannels.first { it.number == 102 }, 5)) - FilmFillOrder.forEach { number -> assertTrue("$number has no rule", SmartChannels.first { it.number == number }.suggestionRules.isNotEmpty()) } - } - - @Test fun fillDatesSurviveARestart() { - val folder = java.nio.file.Files.createTempDirectory("filled").toFile() - ScheduleStore(folder).saveFilled(user, mapOf(301 to 5L)) - assertEquals(mapOf(301 to 5L), ScheduleStore(folder).loadFilled(user)) - } } diff --git a/docs/refinement-notes.md b/docs/refinement-notes.md index 2b62aa2..615c325 100644 --- a/docs/refinement-notes.md +++ b/docs/refinement-notes.md @@ -7,6 +7,8 @@ Paul's approach, 2 November 2026: build in pieces, learn by using it, and note e - **Rules let in misfits.** Family films, shorts, blockbusters and foreign films reached After Dark until year, rating, genre and score rules tightened. A new user should get channels that fit first time, and never have to judge a long list. - **Lists of well-known titles work best.** Curated lists found nearly everything in Paul's library (Orbit 2 31 of 31, Sci-Fi 48 of 48). Rules are for growing a pool, not starting one. - **Reviewing is tiring.** Paul said he'd need to go through each one again, and can't judge every title. Filling automatically and taking out what's wrong suits better than ticking what's right. +- **Rating alone is not a signal.** Filling by highest rating in 0.74 brought UFC events, wrestling and obscure films with a 10 from a few votes. Emby's type and genre don't separate a film from a recorded event. A director needs popularity or vote counts, an event filter, and a check against title lists. Until then, lists are better. +- **Titles still suggests by rating**, and ticks new suggestions by default. Fix this before a new user sees it. - **A film channel needs about 100 films** to go a week without a repeat. With 45 it repeats in 3 to 4 days. Tell the user if their library falls short. - **Library details have limits.** Nothing tells a British film or hand-drawn animation apart, so those need title lists or other sources. - **Names vary by library.** WWE Raw and IMPACT! Wrestling were found under different names from those guessed. Matching should cope with this, and show what it couldn't find. diff --git a/docs/roadmap.md b/docs/roadmap.md index bb591be..cb3e121 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -92,7 +92,7 @@ Paul's ideas, 1 November 2026. Not fixes and not scheduled. - The highlighted left-menu item could reflect the channel or theme, while yellow stays the clear focus signal. - Orbit Drive-In gets its own full-screen destination, opened from the teaser card. - **Rings around the planet (Paul, 1 November 2026):** Orbit 1's background had its rings off to one side of the planet. The app's copy is fixed, from orbit-1/sources/orbit_1_background_v2.svg. Orbit 1's ident and the other channels built from the same planet layout (Orbit 2, Orbit Sci-Fi and any others on that theme) still need checking and the same fix before they join the app. -- **Film pools fill themselves (Paul, 2 November 2026):** in 0.74, the first piece of the programming director. Each film channel fills to 100 films by its own rules, and anything can be taken out under Titles. The rest of the director is to be ironed out with Paul. +- **Bigger film pools (Paul, 2 November 2026):** filling by rating in 0.74 picked poor titles, so 0.75 uses longer hand-picked lists instead. A real programming director needs a better signal than rating, to be ironed out with Paul. - **Build your own network (Paul, 2 November 2026):** for anyone else using the app. On first sign-in, Orbit checks our channels against their library and ticks the ones it can fill, with those channels on by default. They can then edit any channel, adding or removing titles, turn channels on or off, and create new channels of their own. It's about people building what they want, as Paul did. In the pipeline, not scheduled. - **Seamless idents (Paul, 2 November 2026):** when idents arrive, the next show loads silently behind the ident and takes over as it ends, so there's no loading gap. To test: whether the box can decode two videos at once (otherwise draw the ident in the app), and a second Emby stream for a few seconds against the plan's limit of 3. - **Settings (Paul, 2 November 2026):** built in 0.72, then cut back in 0.73 to Channels, Watching and Emby account, as Paul wants only what's mandatory and a simple flow. The demo guide, old menu and test tools are gone.