1286 lines
32 KiB
Perl
1286 lines
32 KiB
Perl
#!/usr/bin/perl
|
|
#----------------------------------------------------------
|
|
#
|
|
# @APPLE_LICENSE_HEADER_START@
|
|
#
|
|
#
|
|
# Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
|
|
#
|
|
# This file contains Original Code and/or Modifications of Original Code
|
|
# as defined in and that are subject to the Apple Public Source License
|
|
# Version 2.0 (the 'License'). You may not use this file except in
|
|
# compliance with the License. Please obtain a copy of the License at
|
|
# http://www.opensource.apple.com/apsl/ and read it before using this
|
|
# file.
|
|
#
|
|
# The Original Code and all software distributed under the License are
|
|
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
|
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
|
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
|
# Please see the License for the specific language governing rights and
|
|
# limitations under the License.
|
|
#
|
|
# @APPLE_LICENSE_HEADER_END@
|
|
#
|
|
#---------------------------------------------------------
|
|
|
|
# playlist-lib.pl
|
|
# Common functions for handling playlist broadcaster files
|
|
|
|
package playlistlib;
|
|
|
|
# FixFileGroup(theFile)
|
|
# On Mac OS X, attempt to switch the group of the file to admin.
|
|
sub FixFileGroup {
|
|
if ($^O eq 'darwin') {
|
|
my $filename = $_[0];
|
|
my $gid;
|
|
|
|
if ((-e $filename) && ($gid = getgrnam('admin'))) {
|
|
my @fileStats = stat($filename);
|
|
my $uid = $fileStats[4];
|
|
chown $uid, $gid, $filename;
|
|
}
|
|
}
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# GetGenreOptions($selectedItemName, $defaultItem, \@genreArrayRef)
|
|
#
|
|
# Encode a playlist name into our internal format.
|
|
#
|
|
# returns encoded name.
|
|
# -------------------------------------------------
|
|
sub GetGenreOptions {
|
|
my $selectedItemName = $_[0];
|
|
my $defaultItem = $_[1];
|
|
my $genreArrayRef = $_[2];
|
|
my @genreArray = @$genreArrayRef;
|
|
my $str = '';
|
|
my $item = '';
|
|
|
|
foreach $item (@genreArray) {
|
|
$str .= "\t\t<option value=\"$item\"";
|
|
if (($item eq $selectedItemName) or (($selectedItemName eq '') and ($item eq $defaultItem))) {
|
|
$str .= ' selected';
|
|
}
|
|
$str .= ">$item</option>\r";
|
|
}
|
|
return $str;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# EncodePLName(name)
|
|
#
|
|
# Encode a playlist name into our internal format.
|
|
#
|
|
# returns encoded name.
|
|
# -------------------------------------------------
|
|
sub EncodePLName {
|
|
my $name = $_[0];
|
|
|
|
# convert whitespace to underscore
|
|
$name =~ s/[ \t]/_/g;
|
|
|
|
# convert double quote to escape sequence
|
|
$name =~ s/\"/%22/g;
|
|
|
|
# convert single quote to escape sequence
|
|
$name =~ s/\'/%27/g;
|
|
|
|
# convert dot to escape sequence
|
|
$name =~ s/\./%2e/g;
|
|
|
|
# convert slash to escape sequence
|
|
$name =~ s/\//%2f/g;
|
|
|
|
# drop any non-alphanumeric chars
|
|
$name =~ s/[^0-9a-zA-Z]//g;
|
|
|
|
return $name;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# DecodePLName(name)
|
|
#
|
|
# Decode a playlist name from our internal format.
|
|
#
|
|
# returns decoded name.
|
|
# -------------------------------------------------
|
|
sub DecodePLName {
|
|
my $name = $_[0];
|
|
|
|
# convert underscore or plus to whitespace
|
|
$name =~ s/[+_]/ /g;
|
|
|
|
# convert the hex characters back to ASCII
|
|
$name =~ s/%(..)/pack("c",hex($1))/ge;
|
|
|
|
return $name;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# ParentDir(dirname)
|
|
#
|
|
# return the parent directory of the given dirname.
|
|
#
|
|
# returns parent directory name.
|
|
# -------------------------------------------------
|
|
sub ParentDir {
|
|
my $dir = $_[0];
|
|
my $parent = "";
|
|
|
|
if ($dir eq "/") {
|
|
# root directory's parent is itself
|
|
return $dir;
|
|
}
|
|
elsif ($dir =~ /(.+)[\/]$/) {
|
|
# remove trailing slash if it's there
|
|
$dir = $1;
|
|
}
|
|
if ($dir =~ /^[\/][^\/]+$/) {
|
|
# one below root, root is our parent
|
|
return "/";
|
|
}
|
|
# find the parent directory
|
|
$dir =~ /(.+)[\/][^\/]+$/;
|
|
$parent = $1;
|
|
return $parent;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# PushCurrPlayList(name)
|
|
#
|
|
# Save the current encoded playlist name so we can
|
|
# recover it later.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub PushCurrPlayList {
|
|
my $name = $_[0];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $targ = "$plroot" . "broadcast_curname";
|
|
|
|
if (!open(NAMFILE, "> $targ")) {
|
|
# can't open a file to hold the current playlist name.
|
|
return 0;
|
|
}
|
|
print NAMFILE "$name\n";
|
|
close(NAMFILE);
|
|
FixFileGroup($targ);
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# PopCurrPlayList()
|
|
#
|
|
# Return the current encoded playlist name that we
|
|
# previously saved with PushCurrPlayList().
|
|
#
|
|
# returns name on success or "none" on failure.
|
|
# -------------------------------------------------
|
|
sub PopCurrPlayList {
|
|
my $name = "none";
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $targ = "$plroot" . "broadcast_curname";
|
|
|
|
if (open(NAMFILE, "< $targ")) {
|
|
$name = <NAMFILE>;
|
|
chop $name;
|
|
close(NAMFILE);
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# PushCurrPWDir(name)
|
|
#
|
|
# Save the current working dir name so we can
|
|
# recover it later.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub PushCurrPWDir {
|
|
my $name = $_[0];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $targ = "$plroot" . "broadcast_pwd";
|
|
|
|
if (!open(NAMFILE, "> $targ")) {
|
|
# can't open a file to hold the current playlist name.
|
|
return 0;
|
|
}
|
|
print NAMFILE "$name\n";
|
|
close(NAMFILE);
|
|
FixFileGroup($targ);
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# PopCurrPWDir()
|
|
#
|
|
# Return the current working dir name that we
|
|
# previously saved with PushCurrPWDir().
|
|
#
|
|
# returns name on success or "none" on failure.
|
|
# -------------------------------------------------
|
|
sub PopCurrPWDir {
|
|
my $name = "none";
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $targ = "$plroot" . "broadcast_pwd";
|
|
|
|
if (open(NAMFILE, "< $targ")) {
|
|
$name = <NAMFILE>;
|
|
chop $name;
|
|
close(NAMFILE);
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# GetPLRootDir()
|
|
#
|
|
# returns the name of the root play list directory.
|
|
# -------------------------------------------------
|
|
sub GetPLRootDir {
|
|
my $plroot;
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
|
|
$plroot = $ENV{"PLAYLISTS_ROOT"};
|
|
|
|
# make sure path is terminated with platform file delimeter
|
|
if (!($plroot =~ /\/$/) && !($plroot =~ /\\$/)) {
|
|
$plroot .= $filedelim;
|
|
}
|
|
|
|
return $plroot;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# SortPlayList(\@order_array, \@pl_name_array)
|
|
#
|
|
# Sort a playlist name array according to the integer
|
|
# order array.
|
|
#
|
|
# returns reference to sorted list.
|
|
# -------------------------------------------------
|
|
sub SortPlayList {
|
|
my $ordref = $_[0];
|
|
my $plaref = $_[1];
|
|
my $n = scalar @$ordref;
|
|
my $tmp1;
|
|
my $tmp2;
|
|
my $i;
|
|
my $j;
|
|
#
|
|
# simple insertion sort algorithm
|
|
#
|
|
for ($i=1; $i<$n; $i+=1) {
|
|
$tmp1 = $$ordref[$i];
|
|
$tmp2 = $$plaref[$i];
|
|
$j = $i-1;
|
|
while (($j>-1)&&($$ordref[$j]>$tmp1)) {
|
|
$$ordref[$j+1] = $$ordref[$j];
|
|
$$plaref[$j+1] = $$plaref[$j];
|
|
$j-=1;
|
|
}
|
|
$$ordref[$j+1] = $tmp1;
|
|
$$plaref[$j+1] = $tmp2;
|
|
}
|
|
return $plaref;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# RemoveMovieFromList(\@mlist, $movie)
|
|
#
|
|
# returns the list minus the movie removed.
|
|
# -------------------------------------------------
|
|
sub RemoveMovieFromList {
|
|
my $arref = $_[0];
|
|
my $movie = $_[1];
|
|
my @mlist = ();
|
|
my $x;
|
|
|
|
foreach $x (@$arref) {
|
|
$x =~ /^(.+)[:]/;
|
|
if ($movie eq $1) {
|
|
#this matches so we don't append it;
|
|
}
|
|
else {
|
|
# no match so append to list
|
|
push @mlist, $x;
|
|
}
|
|
}
|
|
return \@mlist;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# GetFileDelimChar ()
|
|
#
|
|
# returns the correct file delimeter character for
|
|
# this platform.
|
|
# -------------------------------------------------
|
|
sub GetFileDelimChar {
|
|
my $filedelim;
|
|
if($^O ne "MSWin32") {
|
|
$filedelim = "/";
|
|
}
|
|
else {
|
|
$filedelim = "\\";
|
|
}
|
|
return $filedelim;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# EmitPlayListErrLogFile(name)
|
|
#
|
|
# Output the contents of the playlist error log.
|
|
# returns the content of the error log file as HTML.
|
|
# -------------------------------------------------
|
|
sub EmitPlayListErrLogFile {
|
|
my $name = $_[0];
|
|
$name = &playlistlib::EncodePLName($name);
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
# setup HTML header string.
|
|
my $htmlstr = "<tt>\n";
|
|
|
|
if (!open(ERRFILE, "< $plroot$name$filedelim$name.err")) {
|
|
# failed to open error log file
|
|
$htmlstr .= " Log not found!<br></tt>\n";
|
|
return $htmlstr;
|
|
}
|
|
# read each line of the log file and turn it
|
|
# into valid HTML strings.
|
|
while(<ERRFILE>) {
|
|
chomp;
|
|
# replace special characters
|
|
$_ =~ s/</</g;
|
|
$_ =~ s/>/>/g;
|
|
$_ =~ s/&/&/g;
|
|
$htmlstr .= " $_<br>\n";
|
|
}
|
|
close(ERRFILE);
|
|
# append HTML footer.
|
|
$htmlstr .= "</tt>\n";
|
|
|
|
return $htmlstr;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# CreatePlaylistFile (name, plarref)
|
|
#
|
|
# Creates the play list file from playlist array ref.
|
|
# The filename parameter must include the path if we
|
|
# are not in the pwd.
|
|
# Each entry in the arry must be in the form:
|
|
# "moviename:10" where the number is the
|
|
# play weight of the movie.
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub CreatePlaylistFile {
|
|
my $name = $_[0]; # full pathname of PL file
|
|
my $plarref = $_[1];
|
|
my $movie;
|
|
my $wt;
|
|
# support for dynamic playlists
|
|
my $replacelistName = $name;
|
|
my $playlistText = '';
|
|
$replacelistName =~ s/.playlist$/.replacelist/;
|
|
|
|
my $playlistText = "*PLAY-LIST*\n";
|
|
$playlistText .= "#\n";
|
|
$playlistText .= "# Created by QTSS Admin CGI Server\n";
|
|
$playlistText .= "#\n";
|
|
foreach my $item (@$plarref) {
|
|
$item =~ /(.+)[:]([0-9]+)$/;
|
|
$movie = $1;
|
|
$wt = $2;
|
|
if ($wt == "") {
|
|
$wt = 10;
|
|
}
|
|
$movie =~ s/\"/\"\"/g;
|
|
$playlistText .= "\"$movie\" $wt\n";
|
|
}
|
|
if (!open(PLFILE, "> $name")) {
|
|
# failed to create playlist file
|
|
return 0;
|
|
}
|
|
#if (!open (REPLACEFILE, "> $replacelistName")) {
|
|
# close (PLFILE);
|
|
# return 0;
|
|
#}
|
|
|
|
print PLFILE $playlistText;
|
|
#print REPLACEFILE $playlistText;
|
|
|
|
close (PLFILE);
|
|
#close (REPLACEFILE);
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# ParsePlaylistFile(filename)
|
|
#
|
|
# Opens the play list file and parse it.
|
|
# The filename parameter must include the path if we
|
|
# are not in the pwd.
|
|
#
|
|
# Each entry in the array will be in the form:
|
|
# "moviename:10" where the number is the
|
|
# play weight of the movie.
|
|
# returns array reference to the movie list.
|
|
# -------------------------------------------------
|
|
sub ParsePlaylistFile {
|
|
my $name = $_[0]; # full pathname of PL file
|
|
my $arg1;
|
|
my $arg2;
|
|
my $i = 0;
|
|
my @movieList = ();
|
|
|
|
if (!open(PLFILE, "< $name")) {
|
|
# failed to open playlist file
|
|
return \@movieList;
|
|
}
|
|
# first line must be: "*PLAY-LIST*"
|
|
$_ = <PLFILE>;
|
|
if (! /\*PLAY-LIST\*/) {
|
|
return \@movieList;
|
|
}
|
|
# start with empty movie list
|
|
# and add entries as we parse them.
|
|
while(<PLFILE>) {
|
|
$arg1 = "";
|
|
$arg2 = "";
|
|
chomp; # no newline
|
|
s/^#.*//; # no comments (at beginning of line)
|
|
s/\s+$//; # no trailing whitespace
|
|
next unless length; # anything left?
|
|
if (/([0-9]*)$/o) {
|
|
$arg1 = $_;
|
|
$arg2 = $1;
|
|
$arg1 =~ s/[ \t]*[0-9]*$//o;
|
|
$arg1 =~ s/^"//o;
|
|
$arg1 =~ s/"$//o;
|
|
$arg1 =~ s/""/"/go;
|
|
}
|
|
next unless length $arg1;
|
|
if (!length $arg2) {
|
|
# the default weight is 10.
|
|
$arg2 = 10;
|
|
}
|
|
$movieList[$i] = "$arg1:$arg2";
|
|
$i++;
|
|
}
|
|
close(PLFILE);
|
|
return \@movieList;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# CreateNewPlaylistDir(dirname, plarref)
|
|
#
|
|
# Creates the play list directory inside $plroot.
|
|
# we will also put a playlist in this directory.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub CreateNewPlaylistDir {
|
|
my $plroot = &GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $name = $_[0];
|
|
my $plarref = $_[1];
|
|
my $result = 0;
|
|
|
|
# if the top-level playlists dir doesn't exist try and create it.
|
|
if (!(-e "$plroot")) {
|
|
if ((mkdir "$plroot", 0770) == 0) {
|
|
return $result;
|
|
}
|
|
}
|
|
# create the playlistfile after creating the dir for it.
|
|
if ((-e "$plroot$name") || (mkdir "$plroot$name", 0770)) {
|
|
$result = &playlistlib::CreatePlaylistFile("$plroot$name$filedelim$name.playlist", $plarref);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# RemovePlaylistDir(dirname)
|
|
#
|
|
# Removes the play list directory inside $plroot.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub RemovePlaylistDir {
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $dir = "$plroot" . "$_[0]";
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $name = "$_[0]";
|
|
my $result = 0;
|
|
|
|
if (!(-e "$dir")) {
|
|
# directory doesn't exist; nothing to delete.
|
|
# assume this is not an error.
|
|
return 1;
|
|
}
|
|
if (&playlistlib::GetPlayListState($name) == 1) {
|
|
&playlistlib::StopPlayList($name);
|
|
}
|
|
if (opendir(DIR, $dir)) {
|
|
while( defined ($file = readdir DIR) ) {
|
|
# delete all the files in this directory.
|
|
# NOTE: we assume there are no sub-directories.
|
|
if ($file =~ m/[^.]/go) {
|
|
$file = "$dir$filedelim$file";
|
|
if (!(unlink($file))) {
|
|
|
|
# die($!);
|
|
# error: couldn't delete the file.
|
|
closedir(DIR);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
closedir(DIR);
|
|
# remove the empty directory.
|
|
$result = rmdir $dir;
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# SearchDirForRefMov(dirloc)
|
|
#
|
|
# Create all the files for a particular playlist
|
|
# entry.
|
|
#
|
|
# returns a reference movie name.
|
|
# -------------------------------------------------
|
|
sub SearchDirForRefMov {
|
|
use DirHandle;
|
|
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $d = new DirHandle $_[0];
|
|
my $file = '';
|
|
my $fd;
|
|
if (defined($d)) {
|
|
while (defined($f = $d->read)) {
|
|
if ($f =~ /^\./) {
|
|
next;
|
|
}
|
|
else {
|
|
if (defined($fd = new DirHandle $f)) {
|
|
$file = SearchDirForRefMov($f);
|
|
if ($file ne '') {
|
|
return $_[0].$filedelim.$file;
|
|
}
|
|
}
|
|
else {
|
|
return $_[0].$filedelim.$f;
|
|
}
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
else {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
|
|
# -------------------------------------------------
|
|
# SearchArrayForRefMov(\@plarrref, $movdir)
|
|
#
|
|
# Create all the files for a particular playlist
|
|
# entry.
|
|
#
|
|
# returns a reference movie name.
|
|
# -------------------------------------------------
|
|
sub SearchArrayForRefMov {
|
|
my $file;
|
|
my $plr = $_[0];
|
|
my $movdir = $_[1];
|
|
# default to sample movie
|
|
my $mov = $movdir;
|
|
$mov .= "sample.mov";
|
|
# traverse to find first actual movie
|
|
if ($mode eq "weighted_random" ) {
|
|
print PLDFILE "recent_movies_list_size $mr\n";
|
|
}
|
|
foreach $item (@$plr) {
|
|
$file = $item;
|
|
$file =~ /(.+)[:]([0-9]+)$/;
|
|
$file = $1;
|
|
if (opendir(DIR, $file)) {
|
|
closedir(DIR);
|
|
$file = SearchDirForRefMov($file);
|
|
if ($file ne '') {
|
|
return $file;
|
|
}
|
|
}
|
|
else {
|
|
return $file;
|
|
last;
|
|
}
|
|
}
|
|
return $mov;
|
|
}
|
|
|
|
|
|
# -------------------------------------------------
|
|
# CreatePlayListEntry($plname, \@plarref, $movdir, $serverBroadcastPassword)
|
|
#
|
|
# Create all the files for a particular playlist
|
|
# entry.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub CreatePlayListEntry {
|
|
my $plname = $_[0];
|
|
my $arref = $_[1];
|
|
my $movdir = $_[2];
|
|
my $serverBroadcastPassword = $_[3];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $uname;
|
|
my $mode;
|
|
my $logging;
|
|
my $mr;
|
|
my $plr;
|
|
my $mov;
|
|
my $fname;
|
|
my $genre;
|
|
my $destipaddr;
|
|
my $broadcastusername;
|
|
my $broadcastpassword;
|
|
my $title;
|
|
my $item;
|
|
|
|
($uname, $mode, $logging, $plr, $mr, $genre, $destipaddr, $broadcastusername, $broadcastpassword, $title) = @$arref;
|
|
$plname = &playlistlib::EncodePLName($plname);
|
|
if (!(-e $plroot)) {
|
|
my $newdir = $plroot;
|
|
$newdir =~ s/\/$//;
|
|
mkdir "$newdir", 0770;
|
|
}
|
|
mkdir "$newdir", 0770;
|
|
$fname = "$plroot$plname$filedelim$plname";
|
|
|
|
if ($destipaddr eq '') {
|
|
$destipaddr = '127.0.0.1';
|
|
}
|
|
|
|
# die($mode);
|
|
|
|
# make sure path is terminated with platform file delimeter
|
|
if (!($movdir =~ /\/$/) && !($movdir =~ /\\$/)) {
|
|
$movdir .= $filedelim;
|
|
}
|
|
|
|
# make sure $uname ends with .sdp
|
|
if (($genre eq '') and ($uname !~ /[.][Ss][Dd][Pp]$/)) {
|
|
$uname .= ".sdp";
|
|
}
|
|
|
|
if (&playlistlib::CreateNewPlaylistDir($plname, \@$plr) != 1) {
|
|
return 0;
|
|
}
|
|
|
|
# replace any escaped character in URL name with underscore
|
|
$uname =~ s/%(..)/_/ge;
|
|
|
|
if (!open(PLDFILE, "> $fname.config")) {
|
|
# failed to create playlist description file
|
|
return 0;
|
|
}
|
|
if ($fname =~ /\s/) {
|
|
print PLDFILE "playlist_file \"$fname.playlist\"\n";
|
|
}
|
|
else {
|
|
print PLDFILE "playlist_file $fname.playlist\n";
|
|
}
|
|
print PLDFILE "play_mode $mode\n";
|
|
print PLDFILE "destination_ip_address $destipaddr\n";
|
|
if ($genre eq '') { # not a mp3 file
|
|
print PLDFILE "#broadcast_name \"$title\"\n";
|
|
if ($mode eq "weighted_random" ) {
|
|
print PLDFILE "recent_movies_list_size $mr\n";
|
|
}
|
|
#$mov = SearchArrayForRefMov($plr, $movdir);
|
|
#if ($mov eq '') {
|
|
# my @pl = @$plr;
|
|
# $mov = $pl[0];
|
|
# $mov =~ m/(.+)[:]([0-9]+)$/;
|
|
# $mov = $1;
|
|
#}
|
|
#print PLDFILE "sdp_reference_movie \"$mov\"\n";
|
|
print PLDFILE "sdp_file \"$fname.sdp\"\n";
|
|
print PLDFILE "destination_sdp_file \"$uname\"\n";
|
|
print PLDFILE "broadcast_SDP_is_dynamic enabled\n";
|
|
if ($logging eq 'enabled') {
|
|
print PLDFILE "logging enabled\n";
|
|
print PLDFILE "log_file $fname.log\n";
|
|
}
|
|
if (($destipaddr ne '127.0.0.1') and ($destipaddr ne '')) {
|
|
print PLDFILE "broadcaster_name \"$broadcastusername\"\n";
|
|
print PLDFILE "broadcaster_password \"$broadcastpassword\"\n";
|
|
}
|
|
}
|
|
else { # mp3 file
|
|
if ($mode eq "weighted_random" ) {
|
|
print PLDFILE "recent_songs_list_size $mr\n";
|
|
}
|
|
print PLDFILE "destination_base_port 554\n";
|
|
print PLDFILE "broadcast_mount_point \"$uname\"\n";
|
|
print PLDFILE "broadcast_name \"$title\"\n";
|
|
# temporary
|
|
print PLDFILE "broadcast_sample_rate -1\n";
|
|
print PLDFILE "broadcast_genre $genre\n";
|
|
print PLDFILE "working_dir \"$fname\"\n";
|
|
if ($logging eq 'enabled') {
|
|
print PLDFILE "logging enabled\n";
|
|
}
|
|
if ($destipaddr ne '127.0.0.1') {
|
|
print PLDFILE "broadcast_password \"$broadcastpassword\"\n";
|
|
}
|
|
else {
|
|
print PLDFILE "broadcast_password \"$serverBroadcastPassword\"\n";
|
|
}
|
|
}
|
|
print PLDFILE "pid_file \"$fname.pid\"\n";
|
|
close(PLDFILE);
|
|
FixFileGroup("$fname.config");
|
|
chmod(0640, "$fname.config");
|
|
chmod(0644, "$fname.playlist");
|
|
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# ParsePlayListEntry(name, $messHash)
|
|
#
|
|
# Parse the playlist entry name and return it's
|
|
# contents as an array ref.
|
|
# -------------------------------------------------
|
|
sub ParsePlayListEntry {
|
|
my $name = $_[0];
|
|
my $messHash = $_[1];
|
|
my %messages = %$messHash;
|
|
$name = &playlistlib::EncodePLName($name);
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my @datarray = ("none", "weighted_random", "disabled", "", "1", "", "127.0.0.1", "", "", $name);
|
|
my $arg1;
|
|
my $arg2;
|
|
|
|
if (!open(PLDFILE, "< $plroot$name$filedelim$name.config")) {
|
|
# failed to open playlist description file
|
|
return \@datarray;
|
|
}
|
|
|
|
# start with empty movie list
|
|
# and add entries as we parse them.
|
|
while(<PLDFILE>) {
|
|
$arg1 = "";
|
|
$arg2 = "";
|
|
chomp; # no newline
|
|
#s/#.*//; # (we want comments now -- playlist name is in a comment)
|
|
s/\s+$//; # no trailing whitespace
|
|
next unless length; # anything left?
|
|
if (/^([^ ]+)[ \t]+(.+)$/) {
|
|
$arg1 = $1;
|
|
$arg2 = $2;
|
|
}
|
|
# remove any double quotes surrounding the second arg
|
|
$arg2 =~ s/\"//g;
|
|
if (($arg1 =~ /sdp_file/) or ($arg1 =~ /broadcast_mount_point/))
|
|
{
|
|
$datarray[0] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /play_mode/)
|
|
{
|
|
$datarray[1] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /logging/)
|
|
{
|
|
$datarray[2] = $arg2;
|
|
}
|
|
elsif (($arg1 =~ /recent_movies_list_size/) or ($arg1 =~ /recent_songs_list_size/))
|
|
{
|
|
$datarray[4] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /broadcast_genre/)
|
|
{
|
|
$datarray[5] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /destination_ip_address/) {
|
|
$datarray[6] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /broadcaster_name/)
|
|
{
|
|
$datarray[7] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /broadcaster_password/)
|
|
{
|
|
$datarray[8] = $arg2;
|
|
}
|
|
elsif ($arg1 =~ /broadcast_password/)
|
|
{
|
|
$datarray[8] = $arg2;
|
|
}
|
|
elsif (($arg1 =~ /broadcast_name/) or ($arg1 =~ /#broadcast_name/))
|
|
{
|
|
$datarray[9] = $arg2;
|
|
}
|
|
}
|
|
close(PLDFILE);
|
|
$datarray[3] = &playlistlib::ParsePlaylistFile("$plroot$name$filedelim$name.playlist");
|
|
|
|
return \@datarray;
|
|
}
|
|
|
|
# CheckIfPidExists
|
|
# returns 0 - stopped, 1 - running
|
|
# on all platforms, if pid file does not exist => return 0
|
|
# on all platforms, if pid file exists and has value 0 => return 1
|
|
# on win32, if pid file exists with a number != 0 => return 1
|
|
# on other platforms, if pid file exists with a number != 0
|
|
# check for pid validity and if process exists => return 1
|
|
# else if process doesn't exist => return 0
|
|
sub CheckIfPidExists
|
|
{
|
|
my $pidfile = $_[0];
|
|
my $pid = 0;
|
|
my $processExists = 0;
|
|
my $pidline = "";
|
|
|
|
if (open(PIDFILE, "< $pidfile"))
|
|
{
|
|
$pid = <PIDFILE>;
|
|
chop $pid;
|
|
close(PIDFILE);
|
|
|
|
if ($^O eq "MSWin32")
|
|
{
|
|
eval "require Win32::Process";
|
|
if (defined(&Win32::Process::Open)) {
|
|
my $obj;
|
|
$processExists = &Win32::Process::Open($obj, $pid, 0);
|
|
if ($processExists > 0) {
|
|
$processExists = 1;
|
|
}
|
|
}
|
|
else {
|
|
$processExists = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($^O eq "solaris") { $psOutput = `ps -o comm -p $pid`; }
|
|
else { $psOutput = `ps -o command -p $pid`; }
|
|
|
|
if ($psOutput =~ /PlaylistBroadcaster/s)
|
|
{
|
|
$processExists = 1;
|
|
}
|
|
elsif ($psOutput =~ /MP3Broadcaster/s)
|
|
{
|
|
$processExists = 1;
|
|
}
|
|
else
|
|
{
|
|
$processExists = 0;
|
|
unlink("$pidfile");
|
|
}
|
|
}
|
|
}
|
|
|
|
return $processExists;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# GetPlayListState(name)
|
|
#
|
|
# Returns the state of a play list.
|
|
#
|
|
# returns 0 --> stopped
|
|
# 1 --> playing
|
|
# 2 --> stopped with Errors
|
|
# 3 --> playing with Warnings
|
|
# -------------------------------------------------
|
|
sub GetPlayListState {
|
|
my $name = $_[0];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
$name = &playlistlib::EncodePLName($name);
|
|
my $targ = "$plroot$name$filedelim$name";
|
|
my $result = 0;
|
|
|
|
$processExists = CheckIfPidExists("$targ.pid");
|
|
|
|
# If error file is not present
|
|
if (!open(ERRFILE, "< $targ.err")) {
|
|
# since error file doesn't exist, warnings and errors cannot be reported
|
|
# always returns 0 (stopped) or 1 (playing)
|
|
return $processExists;
|
|
}
|
|
|
|
# If error file exists look for the following
|
|
# Errors: XX => errors during preflight
|
|
# Warnings: XX => warnings during preflight
|
|
# Broadcast Errors: XX => errors during broadcast
|
|
# Broadcast Warnings: XX => warnings during broadcast
|
|
|
|
$numPreflightErrors = 0; # in case there is no errors line
|
|
$numPreflightWarnings = 0; # in case there is no warnings line
|
|
$numBroadcastErrors = 0;
|
|
$numBroadcastWarnings = 0;
|
|
while ($line = <ERRFILE>) {
|
|
# $flag = 1 indicates we have no playlist problems
|
|
if ($line =~ /^Errors: (\d+)/) {
|
|
$numPreflightErrors = $1;
|
|
}
|
|
elsif($line =~ /^Warnings: (\d+)/) {
|
|
$numPreflightWarnings = $1;
|
|
}
|
|
elsif($line =~ /^Broadcast Errors: (\d+)/) {
|
|
$numBroadcastErrors = $1;
|
|
}
|
|
elsif($line =~ /^Broadcast Warnings: (\d+)/) {
|
|
$numBroadcastWarnings = $1;
|
|
}
|
|
}
|
|
|
|
close(ERRFILE);
|
|
|
|
# If process is not running
|
|
if ($processExists == 0)
|
|
{
|
|
# we don't care about warnings here, only errors
|
|
if ( ($numPreflightErrors == 0) && ($numBroadcastErrors == 0) )
|
|
{
|
|
$result = 0; # if there are no preflight or broadcast errors
|
|
}
|
|
else
|
|
{
|
|
$result = 2; # there are errors
|
|
}
|
|
}
|
|
else # process is running
|
|
{
|
|
#obviously there shouldn't have been any errors, so just check for warnings
|
|
if ( ($numPreflightWarnings == 0) && ($numBroadcastWarnings == 0) )
|
|
{
|
|
$result = 1; # if there are no preflight or broadcast warnings
|
|
}
|
|
else
|
|
{
|
|
$result = 3; # there are warnings
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# LaunchWin32Process (command, name, args, [0|1])
|
|
# input: command = path to the binary
|
|
# name = program name
|
|
# args = arguments to the program
|
|
# [0|1] = 0 if you want to return right away
|
|
# and 1 if you want to wait until the process exits
|
|
# returns: 1 => success
|
|
# 0 => failure
|
|
# -------------------------------------------------
|
|
sub LaunchWin32Process
|
|
{
|
|
my $command = $_[0];
|
|
my $name = $_[1];
|
|
my $args = $_[2];
|
|
my $wait = $_[3];
|
|
my $processObj;
|
|
my $exitCode = 0;
|
|
|
|
eval "require Win32::Process";
|
|
|
|
if (!$@)
|
|
{
|
|
Win32::Process::Create($processObj,"$command","$name $args",1,DETACHED_PROCESS,".");
|
|
$processObj->SetPriorityClass(NORMAL_PRIORITY_CLASS);
|
|
|
|
if ($wait == 0)
|
|
{
|
|
$processObj->Wait(0); # don't wait for process to complete
|
|
}
|
|
else
|
|
{
|
|
$processObj->Wait(INFINITE); # wait until the process completes
|
|
}
|
|
|
|
$processObj->GetExitCode($exitCode);
|
|
|
|
#if ($exitCode != 0)
|
|
#{
|
|
# return 0;
|
|
#}
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# PreflightPlayList(name, isMP3)
|
|
#
|
|
# Preflight a playlist and return the results of the preflight
|
|
# returns: 0 => no errors and no warnings
|
|
# 1 => warnings but no errors
|
|
# 2 => errors
|
|
# -------------------------------------------------
|
|
sub PreflightPlayList
|
|
{
|
|
my $name = $_[0];
|
|
my $isMP3 = $_[1];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
my $targ = "$plroot$name$filedelim$name";
|
|
my $program = "";
|
|
my $broadcaster = "";
|
|
my $args = "";
|
|
|
|
if ($isMP3 == 1)
|
|
{
|
|
$program = $ENV{"QTSSADMINSERVER_QTSSMP3BROADCASTER"};
|
|
$broadcaster = "MP3Broadcaster";
|
|
$args = "-x -e \"$targ.err\" -c";
|
|
}
|
|
else
|
|
{
|
|
$program = $ENV{"QTSSADMINSERVER_QTSSPLAYLISTBROADCASTER"};
|
|
$broadcaster = "PlaylistBroadcaster";
|
|
$args = "-p -f -d -e \"$targ.err\"";
|
|
}
|
|
|
|
# preflight the playlist
|
|
if ($^O eq "MSWin32")
|
|
{
|
|
$result = &playlistlib::LaunchWin32Process($program, $broadcaster, "$args \"$targ.config\"", 1);
|
|
if ($result == 0) # couldn't launch the process!
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
system "$program $args \"$targ.config\"";
|
|
}
|
|
|
|
|
|
# return the preflight status
|
|
return &playlistlib::PreflightStatus("$targ.err");
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# GetPreflightStatus ( errorFile )
|
|
# input: error filename
|
|
# returns: 0 => no errors and no warnings
|
|
# 1 => warnings but no errors
|
|
# 2 => errors
|
|
# -------------------------------------------------
|
|
sub PreflightStatus
|
|
{
|
|
my $errorFile = $_[0];
|
|
my $errorLineFound = 0;
|
|
my $count = 0;
|
|
my $numErrors = 1; # assume that there are errors if no errors line is found
|
|
my $numWarnings = 0;
|
|
my $line = "";
|
|
|
|
while ( ($errorLineFound == 0) && ($count < 5) )
|
|
{
|
|
if (open(ERRFILE, "< $errorFile"))
|
|
{
|
|
while ($line = <ERRFILE>)
|
|
{
|
|
if ($line =~ /Errors: (\d+)/) {
|
|
$numErrors = $1;
|
|
$errorLineFound = 1;
|
|
}
|
|
elsif($line =~ /Warnings: (\d+)/) {
|
|
$numWarnings = $1;
|
|
}
|
|
}
|
|
|
|
close(ERRFILE);
|
|
}
|
|
|
|
if ($errorLineFound == 1)
|
|
{
|
|
last;
|
|
}
|
|
|
|
$count++;
|
|
sleep(2);
|
|
}
|
|
|
|
if ($numErrors != 0)
|
|
{
|
|
return 2;
|
|
}
|
|
elsif ($numWarnings != 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# StartPlayList(name, isMP3)
|
|
# input: name = playlist name
|
|
# isMP3 = 1 for MP3, 0 for PLB
|
|
# returns: 1 => success
|
|
# 0 => failure
|
|
# -------------------------------------------------
|
|
sub StartPlayList
|
|
{
|
|
my $name = $_[0];
|
|
my $isMP3 = $_[1];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
$name = &playlistlib::EncodePLName($name);
|
|
my $targ = "$plroot$name$filedelim$name";
|
|
|
|
my $processObj;
|
|
my $program = "";
|
|
my $broadcaster = "";
|
|
my $args = "";
|
|
my $preflightResult = 0;
|
|
|
|
if ($isMP3 == 1)
|
|
{
|
|
$program = $ENV{"QTSSADMINSERVER_QTSSMP3BROADCASTER"};
|
|
$broadcaster = "MP3Broadcaster";
|
|
$args = "-e \"$targ.err\" -c";
|
|
}
|
|
else
|
|
{
|
|
$program = $ENV{"QTSSADMINSERVER_QTSSPLAYLISTBROADCASTER"};
|
|
$broadcaster = "PlaylistBroadcaster";
|
|
$args = "-a -f -e \"$targ.err\"";
|
|
|
|
}
|
|
|
|
# if pid file already exists => playlist already running, so return
|
|
if (CheckIfPidExists("$targ.pid") == 1) { return 0; }
|
|
|
|
# remove the previous local SDP file if it exists
|
|
if (-e "$targ.sdp") { unlink "$targ.sdp"; }
|
|
|
|
# delete the error file before starting the preflight
|
|
if (-e "$targ.err") { unlink "$targ.err"; }
|
|
|
|
$preflightResult = &playlistlib::PreflightPlayList($name, $isMP3);
|
|
|
|
if ($preflightResult == 2) { return 0; }
|
|
|
|
|
|
|
|
if ($^O eq "MSWin32")
|
|
{
|
|
$result = &playlistlib::LaunchWin32Process($program, $broadcaster, "$args \"$targ.config\"", 0);
|
|
if ($result == 0) # couldn't launch the process!
|
|
{
|
|
return 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
system "$program $args \"$targ.config\"";
|
|
}
|
|
|
|
# wait until the pid file gets written before returning
|
|
my $count = 0;
|
|
my $pidFileFound = 0;
|
|
while ($count < 5)
|
|
{
|
|
sleep(2);
|
|
if (-e "$targ.pid")
|
|
{
|
|
$pidFileFound = 1;
|
|
last;
|
|
}
|
|
$count++
|
|
}
|
|
|
|
# if pid file wasn't written even after waiting for 10seconds, return failure status
|
|
if ($pidFileFound == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
# -------------------------------------------------
|
|
# StopPlayList(name)
|
|
#
|
|
# Stop the playlist broadcast by name.
|
|
#
|
|
# returns 1 on success or 0 on failure.
|
|
# -------------------------------------------------
|
|
sub StopPlayList
|
|
{
|
|
my $name = $_[0];
|
|
my $plroot = &playlistlib::GetPLRootDir();
|
|
my $filedelim = &playlistlib::GetFileDelimChar();
|
|
$name = &playlistlib::EncodePLName($name);
|
|
my $targ = "$plroot$name$filedelim$name";
|
|
my $pid;
|
|
|
|
if (!open(PIDFILE, "< $targ.pid"))
|
|
{
|
|
# can't open the pid file to read the PID.
|
|
unlink "$targ.pid";
|
|
return 0;
|
|
}
|
|
|
|
$pid = <PIDFILE>;
|
|
chop $pid;
|
|
close(PIDFILE);
|
|
|
|
if ($^O eq "MSWin32")
|
|
{
|
|
eval "require Win32::Process";
|
|
if (!$@ && $pid != 0)
|
|
{
|
|
Win32::Process::KillProcess($pid, 0);
|
|
}
|
|
}
|
|
elsif ($pid != "" && $pid != 0)
|
|
{
|
|
kill 15, $pid;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (-e "$targ.sdp") { unlink "$targ.sdp"; }
|
|
|
|
if (-e "$targ.pid") { unlink "$targ.pid"; }
|
|
#if (-e "$targ.current") { unlink "$targ.current"; }
|
|
#if (-e "$targ.upcoming") { unlink "$targ.upcoming"; }
|
|
|
|
return 1;
|
|
}
|
|
|
|
1; #return true
|
|
|