#!/usr/bin/perl
use strict;
use warnings;
no warnings 'redefine';
use utf8;
use Data::Dumper;
use URI::Escape();
use DateTime();
use utf8();
use params();
use config();
use entry();
use log();
use entry();
use template();
use calendar();
use auth();
use uac();
use project();
use studios();
use events();
use series();
use series_dates();
use markup();
use localization();
use studio_timeslot_dates();
use work_dates();
use playout();
use user_settings();
use audio_recordings();
use audio();
use user_day_start();
binmode STDOUT, ":utf8";
my $r = shift;
( my $cgi, my $params, my $error ) = params::get($r);
my $config = config::get('../config/config.cgi');
my ( $user, $expires ) = auth::get_user( $config, $params, $cgi );
return if ( !defined $user ) || ( $user eq '' );
$config->{user} = $user;
my $user_presets = uac::get_user_presets(
$config,
{
user => $user,
project_id => $params->{project_id},
studio_id => $params->{studio_id}
}
);
$params->{default_studio_id} = $user_presets->{studio_id};
$params = uac::setDefaultStudio( $params, $user_presets );
$params->{expires} = $expires;
my $scriptName = 'calendar.cgi';
#add "all" studio to select box
unshift @{ $user_presets->{studios} },
{
id => -1,
name => '-all-'
};
# select studios, TODO: do in JS
if ( $params->{studio_id} eq '-1' ) {
for my $studio ( @{ $user_presets->{studios} } ) {
delete $studio->{selected};
$studio->{selected} = 1 if $params->{studio_id} eq $studio->{id};
}
}
my $request = {
url => $ENV{QUERY_STRING} || '',
params => {
original => $params,
checked => check_params( $config, $params ),
},
};
$request = uac::prepare_request( $request, $user_presets );
$params = $request->{params}->{checked};
if (
(
( defined $params->{action} ) && ( ( $params->{action} eq 'show' )
|| ( $params->{action} eq 'edit_event' ) )
)
|| ( $params->{part} == 1 )
)
{
print "Content-type:text/html; charset=UTF-8;\n\n";
} else {
#process header
my $headerParams = uac::set_template_permissions( $request->{permissions}, $params );
$headerParams->{loc} = localization::get( $config, { user => $user, file => 'menu' } );
template::process( $config, 'print', template::check( $config, 'calendar-header.html' ),
$headerParams );
if ( $params->{list} eq '1' ) {
print q{
};
}
}
if ( defined $user_presets->{error} ) {
print "
";
uac::print_error( $user_presets->{error} );
return;
}
$config->{access}->{write} = 0;
unless ( defined $params->{project_id} ) {
uac::print_error("Please select a project");
return;
}
if ( $params->{project_id} ne '-1' ) {
if ( project::check( $config, { project_id => $params->{project_id} } ) ne '1' ) {
uac::print_error("invalid project");
return;
}
}
unless ( defined $params->{studio_id} ) {
uac::print_error("Please select a studio");
return;
}
if ( $params->{studio_id} ne '-1' ) {
if ( studios::check( $config, { studio_id => $params->{studio_id} } ) ne '1' ) {
uac::print_error("invalid studio");
return;
}
}
my $start_of_day = $params->{day_start};
my $end_of_day = $start_of_day;
$end_of_day += 24 if ( $end_of_day <= $start_of_day );
our $hour_height = 60;
our $yzoom = 1.5;
showCalendar(
$config, $request,
{
hour_height => $hour_height,
yzoom => $yzoom,
start_of_day => $start_of_day,
end_of_day => $end_of_day,
}
);
sub showCalendar {
my $config = shift;
my $request = shift;
my $cal_options = shift;
my $hour_height = $cal_options->{hour_height};
my $yzoom = $cal_options->{yzoom};
my $start_of_day = $cal_options->{start_of_day};
my $end_of_day = $cal_options->{end_of_day};
my $params = $request->{params}->{checked};
my $permissions = $request->{permissions} || {};
unless ( $permissions->{read_series} == 1 ) {
uac::permissions_denied('read_series');
return;
}
#get range from user settings
my $user_settings = user_settings::get( $config, { user => $params->{presets}->{user} } );
$params->{range} = $user_settings->{range} unless defined $params->{range};
$params->{range} = 28 unless defined $params->{range};
#get colors from user settings
print user_settings::getColorCss( $config, { user => $params->{presets}->{user} } )
if $params->{part} == 0;
$params->{loc} =
localization::get( $config, { user => $params->{presets}->{user}, file => 'all,calendar' } );
my $language = $user_settings->{language} || 'en';
$params->{language} = $language;
print localization::getJavascript( $params->{loc} ) if $params->{part} == 0;
my $calendar = getCalendar( $config, $params, $language );
my $options = {};
my $events = [];
if ( ( $params->{part} == 1 ) || ( $params->{list} == 1 ) ) {
#set date range
my $from = $calendar->{from_date};
my $till = $calendar->{till_date};
my $project_id = $params->{project_id};
my $studio_id = $params->{studio_id};
#build event filter
$options = {
project_id => $project_id,
template => 'html',
limit => 600,
#get => 'no_content',
from_date => $from,
till_date => $till,
date_range_include => 1,
archive => 'all',
};
# set options depending on switches
if ( $params->{studio_id} ne '-1' ) {
$options->{studio_id} = $studio_id;
my $location = $params->{presets}->{studio}->{location};
$options->{location} = $location if $location =~ /\S/;
}
if ( $params->{project_id} ne '-1' ) {
$options->{project_id} = $project_id;
my $project = $params->{presets}->{project}->{name};
$options->{project} = $project if $project =~ /\S/;
}
if ( defined $params->{series_id} ) {
$options->{series_id} = $params->{series_id};
delete $options->{from_date};
delete $options->{till_date};
delete $options->{date_range_include};
}
if ( $params->{search} =~ /\S/ ) {
if ( $params->{list} == 1 ) {
$options->{search} = $params->{search};
delete $options->{from_date};
delete $options->{till_date};
delete $options->{date_range_include};
}
}
$options->{from_time} = '00:00' if defined $options->{from_date};
$options->{draft} = 0 unless $params->{list} == 1;
#get events sorted by date
$events = getSeriesEvents( $config, $request, $options, $params );
unless ( $params->{list} == 1 ) {
for my $event (@$events) {
$event->{origStart} = $event->{start};
$event->{origContent} = $event->{origContent};
}
$events = break_dates( $events, $start_of_day );
}
# recalc after break (for list only?)
for my $event (@$events) {
delete $event->{day};
delete $event->{start_date};
delete $event->{end_date};
$event = events::calc_dates( $config, $event );
}
my $events_by_start = {};
for my $event (@$events) {
$events_by_start->{ $event->{start} } = $event;
}
#build series filter
$options = {
project_id => $project_id,
studio_id => $studio_id,
from => $from,
till => $till,
date_range_include => 1,
exclude => 0
};
if ( defined $params->{series_id} ) {
$options->{series_id} = $params->{series_id};
delete $options->{from};
delete $options->{till};
delete $options->{date_range_include};
}
if ( $params->{search} =~ /\S/ ) {
$options->{search} = $params->{search};
if ( $params->{list} == 1 ) {
delete $options->{from};
delete $options->{till};
delete $options->{date_range_include};
}
}
#get all series dates
my $series_dates = series_dates::get_series( $config, $options );
my $id = 0;
for my $date (@$series_dates) {
$date->{schedule} = 1;
#$date->{event_id}=-1;
$date->{event_id} = $id;
$date->{origStart} = $date->{start};
delete $date->{day};
delete $date->{start_date};
delete $date->{end_date};
$id++;
}
unless ( $params->{list} == 1 ) {
$series_dates = break_dates( $series_dates, $start_of_day );
}
#merge series and events
for my $date (@$series_dates) {
$date = events::calc_dates( $config, $date );
push @$events, $date;
}
#get timeslot_dates
my $studio_dates = studio_timeslot_dates::get( $config, $options );
$id = 0;
for my $date (@$studio_dates) {
$date->{grid} = 1;
$date->{series_id} = -1;
#$date->{event_id}=-1;
$date->{event_id} = $id;
$date->{origStart} = $date->{start};
delete $date->{day};
delete $date->{start_date};
delete $date->{end_date};
$id++;
}
unless ( $params->{list} == 1 ) {
$studio_dates = break_dates( $studio_dates, $start_of_day );
}
for my $date (@$studio_dates) {
$date = events::calc_dates( $config, $date );
push @$events, $date;
}
#get work_dates
my $work_dates = work_dates::get( $config, $options );
for my $date (@$work_dates) {
$date->{work} = 1;
$date->{series_id} = -1;
$date->{event_id} = -1;
$date->{origStart} = $date->{start};
delete $date->{day};
delete $date->{start_date};
delete $date->{end_date};
}
unless ( $params->{list} == 1 ) {
$work_dates = break_dates( $work_dates, $start_of_day );
}
for my $date (@$work_dates) {
$date = events::calc_dates( $config, $date );
push @$events, $date;
}
#get playout
delete $options->{exclude};
my $playout_dates = playout::get_scheduled( $config, $options );
$id = 0;
for my $date (@$playout_dates) {
my $format = undef;
if ( defined $date->{'format'} ) {
$format =
( $date->{'format'} || '' ) . " "
. ( $date->{'format_version'} || '' ) . " "
. ( $date->{'format_profile'} || '' );
$format =~ s/MPEG Audio Version 1 Layer 3/MP3/g;
$format .= ' ' . ( $date->{'format_settings'} || '' )
if defined $date->{'format_settings'};
$format .= '
';
}
$date->{play} = 1;
$date->{series_id} = -1;
$date->{event_id} = $id;
$date->{title} = '';
$date->{title} .= 'errors: ' . $date->{errors} . '
'
if defined $date->{errors};
$date->{title} .= audio::formatDuration(
$date->{duration},
$date->{event_duration},
sprintf( "duration: %.1g h", $date->{duration} / 3600 ) . "
",
sprintf( "%d s", $date->{duration} )
) if defined $date->{duration};
$date->{title} .= audio::formatLoudness( $date->{rms_left}, 'L: ' ) . ', '
if defined $date->{rms_left};
$date->{title} .= audio::formatLoudness( $date->{rms_right}, 'R: ' ) . '
'
if defined $date->{rms_right};
$date->{title} .= audio::formatBitrate( $date->{bitrate} ) if defined $date->{bitrate};
$date->{title} .= ' ' . audio::formatBitrateMode( $date->{bitrate_mode} ) . '
'
if defined $date->{bitrate_mode};
$date->{title} .=
'replay gain ' . sprintf( "%.1f", $date->{replay_gain} ) . '
'
if defined $date->{replay_gain};
$date->{title} .= audio::formatSamplingRate( $date->{sampling_rate} )
if defined $date->{sampling_rate};
$date->{title} .= audio::formatChannels( $date->{channels} ) . '
'
if defined $date->{channels};
$date->{title} .= int( ( $date->{'stream_size'} || '0' ) / ( 1024 * 1024 ) ) . 'MB
'
if defined $date->{'stream_size'};
$date->{title} .= $format if defined $format;
$date->{title} .= 'library: ' . ( $date->{writing_library} || '' ) . '
'
if defined $date->{'writing_library'};
$date->{title} .= 'path: ' . ( $date->{file} || '' ) . '
'
if defined $date->{file};
$date->{title} .= 'updated_at: ' . ( $date->{updated_at} || '' ) . '
'
if defined $date->{updated_at};
$date->{title} .= 'modified_at: ' . ( $date->{modified_at} || '' ) . '
'
if defined $date->{modified_at};
$date->{rms_image} = URI::Escape::uri_unescape( $date->{rms_image} )
if defined $date->{rms_image};
$date->{origStart} = $date->{start};
# set end date seconds to 00 to handle error at break_dates/join_dates
$date->{end} =~ s/(\d\d\:\d\d)\:\d\d/$1\:00/;
delete $date->{day};
delete $date->{start_date};
delete $date->{end_date};
$id++;
}
unless ( $params->{list} == 1 ) {
$playout_dates = break_dates( $playout_dates, $start_of_day );
}
for my $date (@$playout_dates) {
$date = events::calc_dates( $config, $date );
if ( defined $events_by_start->{ $date->{start} } ) {
$events_by_start->{ $date->{start} }->{duration} = $date->{duration} || 0;
$events_by_start->{ $date->{start} }->{event_duration} =
$date->{event_duration} || 0;
$events_by_start->{ $date->{start} }->{rms_left} = $date->{rms_left} || 0;
$events_by_start->{ $date->{start} }->{rms_right} = $date->{rms_right} || 0;
$events_by_start->{ $date->{start} }->{playout_modified_at} = $date->{modified_at};
$events_by_start->{ $date->{start} }->{playout_updated_at} = $date->{updated_at};
$events_by_start->{ $date->{start} }->{file} = $date->{file};
}
push @$events, $date;
}
# series dates
if ($params->{list} == 1 and defined $options->{series_id}){
my $series = series::get(
$config,
{
#project_id => $project_id,
#studio_id => $studio_id,
series_id => $options->{series_id}
}
);
if ( defined $series->[0] and $series->[0]->{predecessor_id}
and $series->[0]->{predecessor_id} ne $series->[0]->{id} ){
my $events2 = getSeriesEvents( $config, $request, {
series_id => $series->[0]->{predecessor_id}
}, $params );
for my $event (@$events2) {
delete $event->{day};
delete $event->{start_date};
delete $event->{end_date};
push @$events, events::calc_dates( $config, $event );
}
}
}
}
#output
printToolbar( $config, $params, $calendar ) if $params->{part} == 0;
#if($params->{part}==1){
print qq{
};
#}
#filter events by time
unless ( $params->{list} == 1 ) {
$events = filterEvents( $events, $options, $start_of_day );
}
#sort events by start
@$events = sort { $a->{start} cmp $b->{start} } @$events;
#separate by day (e.g. to 6 pm)
my $events_by_day = {};
for my $event (@$events) {
my $day =
time::datetime_to_date( time::add_hours_to_datetime( $event->{start}, -$start_of_day ) );
push @{ $events_by_day->{$day} }, $event;
}
#get min and max hour from all events
unless ( $params->{list} == 1 ) {
my $min_hour = 48;
my $max_hour = 0;
for my $event (@$events) {
if ( $event->{start} =~ /(\d\d)\:\d\d\:\d\d$/ ) {
my $hour = $1;
$hour += 24 if $hour < $start_of_day;
$min_hour = $hour if ( $hour < $min_hour ) && ( $hour >= $start_of_day );
}
if ( $event->{end} =~ /(\d\d)\:\d\d\:\d\d$/ ) {
my $hour = $1;
$hour += 24 if $hour <= $start_of_day;
$max_hour = $hour if ( $hour > $max_hour ) && ( $hour <= $end_of_day );
}
}
$cal_options->{min_hour} = $min_hour;
$cal_options->{max_hour} = $max_hour;
}
# calculate positions and find schedule errors (depending on position)
for my $date ( sort ( keys %$events_by_day ) ) {
my $events = $events_by_day->{$date};
calc_positions( $events, $cal_options );
find_errors($events);
}
for my $event (@$events) {
next unless defined $event->{uploaded_at};
next
if ( defined $event->{playout_updated_at} )
&& ( $event->{uploaded_at} lt $event->{playout_updated_at} );
}
if ( $params->{list} == 1 ) {
showEventList( $config, $permissions, $params, $events_by_day );
} else {
if ( $params->{part} == 0 ) {
print qq{