From 60aa3387f0a9f690d7748321fce18f41160e632d Mon Sep 17 00:00:00 2001 From: Milan Date: Sun, 30 Jun 2019 01:26:06 +0200 Subject: [PATCH] verify uploads and playout check if attributes for uploaded audio match expected ranges and mark them by colors to help finding issues with duration, channels, RMS, mode (CBR, ABR), bitrate. increase upload limit to 400 MB for audio --- lib/calcms/audio.pm | 98 ++++++ lib/calcms/playout.pm | 105 ++++++ website/agenda/planung/audio_recordings.cgi | 36 +- website/agenda/planung/calendar.cgi | 321 +++++++++++------- website/agenda/planung/css/admin.css | 1 + .../agenda/planung/css/audio_recordings.css | 11 + website/agenda/planung/css/calendar.css | 15 + website/agenda/planung/js/audio_recordings.js | 4 +- website/agenda/planung/playout.cgi | 1 - website/agenda/planung/show-playout.cgi | 73 ++-- .../planung/templates/show_playout.html | 2 +- .../templates/upload_audio_recordings.html | 6 +- 12 files changed, 485 insertions(+), 188 deletions(-) create mode 100644 lib/calcms/audio.pm diff --git a/lib/calcms/audio.pm b/lib/calcms/audio.pm new file mode 100644 index 0000000..177bdc4 --- /dev/null +++ b/lib/calcms/audio.pm @@ -0,0 +1,98 @@ +package audio; +use warnings; +use strict; + +sub durationToSeconds($) { + my $duration = shift; + + if ( $duration =~ /(\d+):(\d\d):(\d\d).(\d\d)/ ) { + return $1 * 3600 + $2 * 60 + $3 + $4 / 100; + } + return $duration; +} + +sub formatDuration($$$) { + my $audioDuration = shift; + my $eventDuration = shift; + my $value = shift; + + return '' unless $audioDuration; + return '' unless $eventDuration; + return '' unless $value; + + $audioDuration = durationToSeconds($audioDuration); + $eventDuration = durationToSeconds($eventDuration); + + my $delta = 100 * $audioDuration / $eventDuration; + my $class = "ok"; + my $title = ''; + if ( $delta > 101 ) { + $class = "warn"; + $title = sprintf( + qq{ title="file is too long! It should be %d minutes, but is %d"}, + $eventDuration / 60, + $audioDuration / 60 + ); + } + if ( $delta < 99.99 ) { + $class = "error"; + $title = sprintf( + qq{ title="file is too short! should be %d minutes, but is %d"}, + $eventDuration / 60, + $audioDuration / 60 + ); + + } + + return sprintf( qq{
%s
}, $class, $title, $value ); +} + +sub formatChannels($) { + my $channels = shift; + return '' unless $channels; + my $class = "ok"; + $class = "error" if $channels != 2; + return sprintf( qq{
%d ch.
}, $class, $channels ); +} + +sub formatSamplingRate($) { + my $samplingRate = shift; + return '' unless $samplingRate; + my $class = "ok"; + $class = "error" if $samplingRate != 44100; + return sprintf( qq{
%s
}, $class, $samplingRate ); +} + +sub formatBitrate($) { + my $bitrate = shift; + return '' unless $bitrate; + my $class = 'ok'; + $class = 'warn' if $bitrate >= 200; + $class = 'error' if $bitrate < 192; + return sprintf( qq{
%s kBit/s
}, $class, $bitrate ); +} + +sub formatBitrateMode($) { + my $mode = shift; + return '' unless $mode; + my $class = 'ok'; + $class = 'error' if $mode ne 'CBR'; + return sprintf( qq{
%s
}, $class, $mode ); +} + +sub formatLoudness { + my $value = shift; + return '' unless $value; + + $value = sprintf( "%.1f", $value ); + my $class = 'ok'; + $class = 'warn' if $value > -18.5; + $class = 'error' if $value > -16.0; + $class = 'warn' if $value < -24.0; + $class = 'error' if $value < -27.0; + + return qq{
$value dB
}; +} + +# do not delete this line +1; diff --git a/lib/calcms/playout.pm b/lib/calcms/playout.pm index 8164b1b..d32e6ca 100644 --- a/lib/calcms/playout.pm +++ b/lib/calcms/playout.pm @@ -27,6 +27,111 @@ sub get_columns ($) { return $columns; } + + +# get playout entries +sub get_scheduled($$) { + my $config = shift; + my $condition = shift; + + return undef unless defined $condition->{studio_id}; + + my $date_range_include = 0; + $date_range_include = 1 + if ( defined $condition->{date_range_include} ) && ( $condition->{date_range_include} == 1 ); + + my $dbh = db::connect($config); + + my @conditions = (); + my @bind_values = (); + + if ( ( defined $condition->{project_id} ) && ( $condition->{project_id} ne '' ) ) { + push @conditions, 'p.project_id=?'; + push @bind_values, $condition->{project_id}; + } + + if ( ( defined $condition->{studio_id} ) && ( $condition->{studio_id} ne '' ) ) { + push @conditions, 'p.studio_id=?'; + push @bind_values, $condition->{studio_id}; + } + + if ( ( defined $condition->{start_at} ) && ( $condition->{start_at} ne '' ) ) { + push @conditions, 'p.start=?'; + push @bind_values, $condition->{start_at}; + } + + if ( ( defined $condition->{from} ) && ( $condition->{from} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'p.end_date>=?'; + push @bind_values, $condition->{from}; + } else { + push @conditions, 'p.start_date>=?'; + push @bind_values, $condition->{from}; + } + } + + if ( ( defined $condition->{till} ) && ( $condition->{till} ne '' ) ) { + if ( $date_range_include == 1 ) { + push @conditions, 'p.start_date<=?'; + push @bind_values, $condition->{till}; + } else { + push @conditions, 'p.end_date<=?'; + push @bind_values, $condition->{till}; + } + } + + my $limit = ''; + if ( ( defined $condition->{limit} ) && ( $condition->{limit} ne '' ) ) { + $limit = 'limit ' . $condition->{limit}; + } + + my $conditions = ''; + $conditions = " where " . join( " and ", @conditions ) if scalar @conditions > 0; + + my $order = 'start'; + $order = $condition->{order} if ( defined $condition->{order} ) && ( $condition->{order} ne '' ); + + my $query = qq{ + select date(p.start) start_date + , date(p.end) end_date + , dayname(p.start) weekday + , p.start_date day + , p.start + , p.end + , p.studio_id + , p.project_id + , p.duration + , p.file + , p.errors + , p.channels + , p.format + , p.format_version + , p.format_profile + , p.format_settings + , p.stream_size + , p.bitrate + , p.bitrate_mode + , p.sampling_rate + , p.writing_library + , p.rms_left + , p.rms_right + , p.rms_image + , p.modified_at + , p.updated_at + , TIMESTAMPDIFF(SECOND,e.start,e.end) "event_duration" + from calcms_playout p left join calcms_events e + on p.start = e.start + $conditions + order by $order + $limit + }; + + #print STDERR Dumper($query).Dumper(\@bind_values); + my $entries = db::get( $dbh, $query, \@bind_values ); + return $entries; +} + + # get playout entries sub get($$) { my $config = shift; diff --git a/website/agenda/planung/audio_recordings.cgi b/website/agenda/planung/audio_recordings.cgi index 0288306..ac1d80e 100755 --- a/website/agenda/planung/audio_recordings.cgi +++ b/website/agenda/planung/audio_recordings.cgi @@ -21,6 +21,7 @@ use series(); use template(); use audio_recordings(); use events(); +use audio(); use time(); #$|=1; @@ -33,7 +34,7 @@ our $debug = $config->{system}->{debug}; my $base_dir = $config->{locations}->{base_dir}; my $tempDir = '/var/tmp'; -my $uploadLimit = 300_000_000; +my $uploadLimit = 400_000_000; my %params = (); my $error = ''; @@ -108,7 +109,8 @@ if ( $params->{action} eq 'upload' ) { showAudioRecordings( $config, $request ); print STDERR "$0 ERROR: " . $params->{error} . "\n" if $params->{error} ne ''; -$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); +$params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); template::process( $config, 'print', $params->{template}, $params ); exit; @@ -302,10 +304,14 @@ sub showAudioRecordings { $recording->{mastered} = $recording->{mastered} ? 'yes' : 'no'; $recording->{eventDuration} = getDuration( $recording->{eventDuration} ); - $recording->{audioDuration} = getDuration( $recording->{audioDuration} ); + $recording->{audioDuration} = audio::formatDuration( + $recording->{audioDuration}, + $recording->{eventDuration}, + getDuration( $recording->{audioDuration} ) + ); - $recording->{rmsLeft} ||= '-'; - $recording->{rmsRight} ||= '-'; + $recording->{rmsLeft} = audio::formatLoudness( $recording->{rmsLeft} ); + $recording->{rmsRight} = audio::formatLoudness( $recording->{rmsRight} ); } my $now = time(); @@ -368,7 +374,8 @@ sub uploadFile { print STDERR "tempFile=$tempFile\n"; my $start = time(); - open DAT, '>', $tempFile or return { error => 'could not save upload. ' . $! . " " . $tempFile }; + open DAT, '>', $tempFile + or return { error => 'could not save upload. ' . $! . " " . $tempFile }; binmode DAT; my $size = 0; my $data = ''; @@ -495,14 +502,18 @@ sub checkFilename { if ( $filename =~ /\.([a-zA-Z]{3,5})$/ ) { my $extension = lc $1; unless ( grep( /$extension/, @validExtensions ) ) { - return { error => 'Following file formats are supported: ' . join( ",", @validExtensions ) . '!' }; + return {error => 'Following file formats are supported: ' + . join( ",", @validExtensions ) + . '!' }; } return { extension => $extension, error => '' }; } - return { error => 'Not matching file extension found! Supported are: ' . join( ",", @validExtensions ) . '!' }; + return {error => 'Not matching file extension found! Supported are: ' + . join( ",", @validExtensions ) + . '!' }; } # return event duration in seconds @@ -534,7 +545,8 @@ sub getEventDuration { print STDERR "getEventDuration: no event found with event_id=$eventId\n"; } my $event = $events->[0]; - my $duration = time::get_duration_seconds( $event->{start}, $event->{end}, $config->{date}->{time_zone} ); + my $duration = + time::get_duration_seconds( $event->{start}, $event->{end}, $config->{date}->{time_zone} ); return $duration; } @@ -544,11 +556,13 @@ sub check_params { my $checked = {}; $checked->{error} = ''; - $checked->{template} = template::check( $config, $params->{template}, 'upload_audio_recordings' ); + $checked->{template} = + template::check( $config, $params->{template}, 'upload_audio_recordings' ); #print Dumper($params); #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) { + for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) + { if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { $checked->{$param} = $params->{$param}; } diff --git a/website/agenda/planung/calendar.cgi b/website/agenda/planung/calendar.cgi index 199770c..297cfce 100755 --- a/website/agenda/planung/calendar.cgi +++ b/website/agenda/planung/calendar.cgi @@ -29,6 +29,7 @@ use work_dates(); use playout(); use user_settings(); use audio_recordings(); +use audio(); binmode STDOUT, ":utf8"; @@ -93,7 +94,8 @@ if ( #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, 'default.html' ), $headerParams ); + template::process( $config, 'print', template::check( $config, 'default.html' ), + $headerParams ); print q{ @@ -167,7 +169,7 @@ sub showCalendar { my $start_of_day = $cal_options->{start_of_day}; my $end_of_day = $cal_options->{end_of_day}; - my $params = $request->{params}->{checked}; + my $params = $request->{params}->{checked}; my $permissions = $request->{permissions} || {}; unless ( $permissions->{read_series} == 1 ) { uac::permissions_denied('read_series'); @@ -180,9 +182,11 @@ sub showCalendar { $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; + 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' } ); + $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; @@ -367,7 +371,7 @@ sub showCalendar { #get playout delete $options->{exclude}; - my $playout_dates = playout::get( $config, $options ); + my $playout_dates = playout::get_scheduled( $config, $options ); $id = 0; for my $date (@$playout_dates) { my $format = undef; @@ -377,7 +381,8 @@ sub showCalendar { . ( $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->{'format_settings'} || '' ) + if defined $date->{'format_settings'}; $format .= '
'; } @@ -386,32 +391,44 @@ sub showCalendar { $date->{series_id} = -1; $date->{event_id} = $id; $date->{title} = ''; - $date->{title} .= 'errors: ' . $date->{errors} . '
' if defined $date->{errors}; - $date->{title} .= formatDuration( $date->{duration} ) . "
" if defined $date->{duration}; - $date->{title} .= formatLoudness( "L:", $date->{rms_left} ) . ', ' if defined $date->{rms_left}; - $date->{title} .= formatLoudness( "R:", $date->{rms_right} ) . '
' if defined $date->{rms_right}; - $date->{title} .= formatBitrate( $date->{bitrate} ) . ' ' . $date->{bitrate_mode} . '
' - if defined $date->{bitrate}; - $date->{title} .= 'replay gain ' . sprintf( "%.1f", $date->{replay_gain} ) . '
' + $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 ) . "
" + ) if defined $date->{duration}; + $date->{title} .= "L:" . audio::formatLoudness( $date->{rms_left} ) . ', ' + if defined $date->{rms_left}; + $date->{title} .= "R:" . audio::formatLoudness( $date->{rms_right} ) . '
' + 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} .= ( ( $date->{sampling_rate} || '0' ) / 1000 ) . ' kHz
' + $date->{title} .= audio::formatSamplingRate( $date->{sampling_rate} ) if defined $date->{sampling_rate}; - $date->{title} .= ( $date->{channels} || '' ) . ' channels
' if defined $date->{channels}; + $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} .= '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}; - #print STDERR Dumper($date) if $date->{file}=~/180503/; - #$date->{title}.= 'rms_image: ' .($date->{rms_image}||'').'
' if defined $date->{rms_image}; +#print STDERR Dumper($date) if $date->{file}=~/180503/; +#$date->{title}.= 'rms_image: ' .($date->{rms_image}||'').'
' if defined $date->{rms_image}; - $date->{rms_image} = URI::Escape::uri_unescape( $date->{rms_image} ) if defined $date->{rms_image}; + $date->{rms_image} = URI::Escape::uri_unescape( $date->{rms_image} ) + if defined $date->{rms_image}; $date->{origStart} = $date->{start}; @@ -431,6 +448,7 @@ sub showCalendar { $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}; @@ -468,7 +486,8 @@ sub showCalendar { #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 ) ); + my $day = + time::datetime_to_date( time::add_hours_to_datetime( $event->{start}, -$start_of_day ) ); push @{ $events_by_day->{$day} }, $event; } @@ -506,7 +525,9 @@ sub showCalendar { next unless defined $event->{uploaded_at}; #print STDERR "uploadAt=$event->{uploaded_at}, playoutModified:$event->{playout_modified_at}, playoutUpdatedAt:$event->{playout_updated_at}\n"; - next if ( defined $event->{playout_updated_at} ) && ( $event->{uploaded_at} lt $event->{playout_updated_at} ); + next + if ( defined $event->{playout_updated_at} ) + && ( $event->{uploaded_at} lt $event->{playout_updated_at} ); #print STDERR Dumper($event); #$event->{upload} ='pending' ; @@ -520,7 +541,8 @@ sub showCalendar { print qq{
}; } if ( $params->{part} == 1 ) { - calcCalendarTable( $config, $permissions, $params, $calendar, $events_by_day, $cal_options ); + calcCalendarTable( $config, $permissions, $params, $calendar, $events_by_day, + $cal_options ); printTableHeader( $config, $permissions, $params, $cal_options ); printTableBody( $config, $permissions, $params, $cal_options ); } @@ -542,46 +564,6 @@ sub showCalendar { } } -sub formatLoudness { - my $label = shift; - my $value = shift; - return '' unless defined $value; - return '' if $value == 0; - return '' if $value eq ''; - - #print STDERR "'$value'\n"; - $value = sprintf( "%d", $value + 0.5 ); - my $class = 'ok'; - $class = 'warn' if $value > -18.5; - $class = 'error' if $value > -16.0; - $class = 'warn' if $value < -24.0; - $class = 'error' if $value < -27.0; - return qq{$label} . $value . qq{dB}; -} - -sub formatDuration { - my $duration = shift; - return '' unless defined $duration; - return '' if $duration eq ''; - my $result = int( ( $duration + 30.5 ) % 60 ) - 30; - my $class = "ok"; - $class = "warn" if abs($result) > 1; - $class = "error" if abs($result) > 2; - return sprintf( qq{%ds}, $class, $duration ); -} - -sub formatBitrate { - my $bitrate = shift; - return '' if $bitrate eq ''; - if ( $bitrate >= 200 ) { - return qq{$bitrate}; - } elsif ( $bitrate < 190 ) { - return qq{$bitrate}; - } else { - return qq{$bitrate}; - } -} - sub debugDate { my $date = shift; $date->{program} = '' unless defined $date->{program}; @@ -592,7 +574,7 @@ sub debugDate { my $da = ( $date->{start_date} || '' ) . " " . ( $date->{end_date} || '' ); my $type = "schedule:" . ( $date->{schedule} || "" ) . " grid:" . ( $date->{grid} || "" ); - #print STDERR "$dt $da count:$date->{splitCount} $type $date->{program}-$date->{series_name}-$date->{title}\n"; +#print STDERR "$dt $da count:$date->{splitCount} $type $date->{program}-$date->{series_name}-$date->{title}\n"; } # break dates at start_of_day @@ -730,9 +712,9 @@ sub showEventList { my $events_by_day = shift; my $language = $params->{language}; - my $rerunIcon = ''; - my $liveIcon = ''; - my $draftIcon = ''; + my $rerunIcon = ''; + my $liveIcon = ''; + my $draftIcon = ''; my $archiveIcon = ''; my $out = ''; @@ -785,14 +767,23 @@ sub showEventList { if ( $class =~ /(event|schedule)/ ) { $class .= ' scheduled' if defined $event->{scheduled}; $class .= ' error' if defined $event->{error}; - $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); + $class .= ' no_series' + if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); - for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', 'draft' ) { - $class .= ' ' . $filter if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); + for my $filter ( + 'rerun', 'archived', 'playout', 'published', + 'live', 'disable_event_sync', 'draft' + ) + { + $class .= ' ' . $filter + if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); } - $class .= ' preproduced' unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); - $class .= ' no_playout' unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); - $class .= ' no_rerun' unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); + $class .= ' preproduced' + unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); + $class .= ' no_playout' + unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); + $class .= ' no_rerun' + unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); } $event->{start} ||= ''; @@ -874,7 +865,8 @@ sub showEventList { ); $out .= q{}; @@ -1140,20 +1132,29 @@ sub printTableBody { $content = $event->{start} if $day eq '0'; $event->{project_id} = $project_id unless defined $event->{project_id}; $event->{studio_id} = $studio_id unless defined $event->{studio_id}; - $event->{content} = $content unless ( ( defined $event->{class} ) && ( $event->{class} eq 'time now' ) ); - $event->{class} = 'event' if $day ne '0'; - $event->{class} = 'grid' if ( ( defined $event->{grid} ) && ( $event->{grid} == 1 ) ); - $event->{class} = 'schedule' if ( ( defined $event->{schedule} ) && ( $event->{schedule} == 1 ) ); - $event->{class} = 'work' if ( ( defined $event->{work} ) && ( $event->{work} == 1 ) ); - $event->{class} = 'play' if ( ( defined $event->{play} ) && ( $event->{play} == 1 ) ); + $event->{content} = $content + unless ( ( defined $event->{class} ) && ( $event->{class} eq 'time now' ) ); + $event->{class} = 'event' if $day ne '0'; + $event->{class} = 'grid' if ( ( defined $event->{grid} ) && ( $event->{grid} == 1 ) ); + $event->{class} = 'schedule' + if ( ( defined $event->{schedule} ) && ( $event->{schedule} == 1 ) ); + $event->{class} = 'work' if ( ( defined $event->{work} ) && ( $event->{work} == 1 ) ); + $event->{class} = 'play' if ( ( defined $event->{play} ) && ( $event->{play} == 1 ) ); if ( $event->{class} eq 'event' ) { $event->{content} .= '
'; - $event->{content} .= formatDuration( $event->{duration} ) . ' ' if defined $event->{duration}; - $event->{content} .= formatLoudness( 'L', $event->{rms_left} ) . ' ' if defined $event->{rms_left}; - $event->{content} .= formatLoudness( 'R', $event->{rms_right} ) if defined $event->{rms_right}; + $event->{content} .= + audio::formatDuration( $event->{duration}, $event->{event_duration}, + sprintf("%d min", (($event->{duration}+0.5)/60)) ) + . ' ' + if defined $event->{duration}; + $event->{content} .= 'L' . audio::formatLoudness( $event->{rms_left} ) . ' ' + if defined $event->{rms_left}; + $event->{content} .= + 'R' . audio::formatLoudness( $event->{rms_right} ) + if defined $event->{rms_right}; - #$event->{content} .= formatBitrate( $event->{bitrate} ) if defined $event->{bitrate}; + #$event->{content} .= formatBitrate( $event->{bitrate} ) if defined $event->{bitrate}; $event->{content} .= ''; } @@ -1205,9 +1206,11 @@ sub printSeries { if ( ( $params->{studio_id} ne '' ) && ( $params->{studio_id} ne '-1' ) ) { $out .= q{}; } @@ -1283,7 +1286,14 @@ sub addSeries { $name = $params->{loc}->{single_events} if $serie->{has_single_events} eq '1'; $title = ' - ' . $title if $title ne ''; - $out .= '' . "\n"; + $out .= + '' . "\n"; } #print Dumper($series); @@ -1338,7 +1348,14 @@ sub addEventsToSeries { my $title = $serie->{title} || ''; $name = $params->{loc}->{single_events} if $serie->{has_single_events} == 1; $title = ' - ' . $title if $title ne ''; - $out .= '' . "\n"; + $out .= + '' . "\n"; } #print Dumper($series); @@ -1416,16 +1433,22 @@ sub print_event { my $class = $event->{class} || ''; my $showIcons = 0; if ( $class =~ /(event|schedule)/ ) { - $class .= ' scheduled' if defined $event->{scheduled}; - $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); + $class .= ' scheduled' if defined $event->{scheduled}; + $class .= ' no_series' if ( ( $class eq 'event' ) && ( $event->{series_id} eq '-1' ) ); $class .= " error x$event->{error}" if defined $event->{error}; - for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', 'draft' ) { - $class .= ' ' . $filter if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); + for my $filter ( 'rerun', 'archived', 'playout', 'published', 'live', 'disable_event_sync', + 'draft' ) + { + $class .= ' ' . $filter + if ( ( defined $event->{$filter} ) && ( $event->{$filter} eq '1' ) ); } - $class .= ' preproduced' unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); - $class .= ' no_playout' unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); - $class .= ' no_rerun' unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); + $class .= ' preproduced' + unless ( ( defined $event->{'live'} ) && ( $event->{'live'} eq '1' ) ); + $class .= ' no_playout' + unless ( ( defined $event->{'playout'} ) && ( $event->{'playout'} eq '1' ) ); + $class .= ' no_rerun' + unless ( ( defined $event->{'rerun'} ) && ( $event->{'rerun'} eq '1' ) ); $showIcons = 1; } @@ -1626,8 +1649,9 @@ sub printToolbar { # my $options=[]; for my $range ( - $params->{loc}->{label_month}, $params->{loc}->{label_4_weeks}, $params->{loc}->{label_2_weeks}, - $params->{loc}->{label_1_week}, $params->{loc}->{label_day} + $params->{loc}->{label_month}, $params->{loc}->{label_4_weeks}, + $params->{loc}->{label_2_weeks}, $params->{loc}->{label_1_week}, + $params->{loc}->{label_day} ) { my $value = $ranges->{$range} || ''; @@ -1657,14 +1681,17 @@ sub printToolbar { - + }; @@ -1717,11 +1745,16 @@ sub getCalendar { my $next = ''; if ( $range eq 'month' ) { $previous = - time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( months => 1 )->set_day(1)->date(); - $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( months => 1 )->set_day(1)->date(); + time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( months => 1 ) + ->set_day(1)->date(); + $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( months => 1 ) + ->set_day(1)->date(); } else { - $previous = time::get_datetime( $from_date, $config->{date}->{time_zone} )->subtract( days => $range )->date(); - $next = time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( days => $range )->date(); + $previous = time::get_datetime( $from_date, $config->{date}->{time_zone} ) + ->subtract( days => $range )->date(); + $next = + time::get_datetime( $from_date, $config->{date}->{time_zone} )->add( days => $range ) + ->date(); } my ( $year, $month, $day ) = split( /\-/, $from_date ); my $monthName = time::getMonthNamesShort($language)->[ $month - 1 ] || ''; @@ -1752,7 +1785,8 @@ sub getFromDate { if ( $params->{range} eq '28' ) { #get start of 4 week period - $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' )->ymd(); + $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' ) + ->ymd(); } if ( $params->{range} eq 'month' ) { @@ -1775,17 +1809,19 @@ sub getTillDate { $date = DateTime->now( time_zone => $config->{date}->{time_zone} )->date(); } if ( $params->{range} eq '28' ) { - $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' )->ymd(); + $date = time::get_datetime( $date, $config->{date}->{time_zone} )->truncate( to => 'week' ) + ->ymd(); } if ( $params->{range} eq 'month' ) { #get last day of month - return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1)->add( months => 1 ) - ->subtract( days => 1 )->date(); + return time::get_datetime( $date, $config->{date}->{time_zone} )->set_day(1) + ->add( months => 1 )->subtract( days => 1 )->date(); } #add range to date - return time::get_datetime( $date, $config->{date}->{time_zone} )->add( days => $params->{range} )->date(); + return time::get_datetime( $date, $config->{date}->{time_zone} ) + ->add( days => $params->{range} )->date(); } sub getSeriesEvents { @@ -1816,8 +1852,8 @@ sub getSeriesEvents { $request2->{params}->{checked}->{published} = 'all'; $request2->{params}->{checked}->{draft} = '1' if $params->{list} == 1; - #delete $request2->{params}->{checked}->{locations_to_exclude} - # if ( ( $params->{studio_id} == -1 ) && ( defined $request2->{params}->{checked}->{locations_to_exclude} ) ); +#delete $request2->{params}->{checked}->{locations_to_exclude} +# if ( ( $params->{studio_id} == -1 ) && ( defined $request2->{params}->{checked}->{locations_to_exclude} ) ); my $events = events::get( $config, $request2 ); @@ -1838,7 +1874,8 @@ sub getSeriesEvents { for my $event (@$events) { $event->{project_id} = $options->{project_id} unless defined $event->{project_id}; - $event->{studio_id} = $studio_id_by_location->{ $event->{location} } unless defined $event->{studio_id}; + $event->{studio_id} = $studio_id_by_location->{ $event->{location} } + unless defined $event->{studio_id}; } return $events; @@ -1862,8 +1899,9 @@ sub check_params { $checked->{part} = 0; $checked->{list} = 0; for my $param ( - 'id', 'project_id', 'studio_id', 'default_studio_id', 'user_id', 'series_id', - 'event_id', 'part', 'list', 'day_start' + 'id', 'project_id', 'studio_id', 'default_studio_id', + 'user_id', 'series_id', 'event_id', 'part', + 'list', 'day_start' ) { if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { @@ -1871,7 +1909,8 @@ sub check_params { } } - $checked->{day_start} = $config->{date}->{day_starting_hour} unless defined $checked->{day_start}; + $checked->{day_start} = $config->{date}->{day_starting_hour} + unless defined $checked->{day_start}; $checked->{day_start} %= 24; if ( defined $checked->{studio_id} ) { @@ -1916,7 +1955,11 @@ sub check_params { $checked->{$param} = time::check_date( $params->{$param} ); } - for my $param ( 'series_name', 'title', 'excerpt', 'content', 'program', 'category', 'image', 'user_content' ) { + for my $param ( + 'series_name', 'title', 'excerpt', 'content', + 'program', 'category', 'image', 'user_content' + ) + { if ( defined $params->{$param} ) { #$checked->{$param}=uri_unescape(); @@ -1928,7 +1971,9 @@ sub check_params { #actions and roles if ( defined $params->{action} ) { - if ( $params->{action} =~ /^(add_user|remove_user|delete|save|details|show|edit_event|save_event)$/ ) { + if ( $params->{action} =~ + /^(add_user|remove_user|delete|save|details|show|edit_event|save_event)$/ ) + { $checked->{action} = $params->{action}; } } @@ -1936,3 +1981,43 @@ sub check_params { return $checked; } +__DATA__ +sub formatLoudness { + my $label = shift; + my $value = shift; + return '' unless defined $value; + return '' if $value == 0; + return '' if $value eq ''; + + #print STDERR "'$value'\n"; + $value = sprintf( "%d", $value + 0.5 ); + my $class = 'ok'; + $class = 'warn' if $value > -18.5; + $class = 'error' if $value > -16.0; + $class = 'warn' if $value < -24.0; + $class = 'error' if $value < -27.0; + return qq{$label} . $value . qq{dB}; +} + +sub formatDuration { + my $duration = shift; + return '' unless defined $duration; + return '' if $duration eq ''; + my $result = int( ( $duration + 30.5 ) % 60 ) - 30; + my $class = "ok"; + $class = "warn" if abs($result) > 1; + $class = "error" if abs($result) > 2; + return sprintf( qq{%ds}, $class, $duration ); +} + +sub formatBitrate { + my $bitrate = shift; + return '' if $bitrate eq ''; + if ( $bitrate >= 200 ) { + return qq{$bitrate}; + } elsif ( $bitrate < 190 ) { + return qq{$bitrate}; + } else { + return qq{$bitrate}; + } +} diff --git a/website/agenda/planung/css/admin.css b/website/agenda/planung/css/admin.css index ea9ffff..e586684 100644 --- a/website/agenda/planung/css/admin.css +++ b/website/agenda/planung/css/admin.css @@ -49,6 +49,7 @@ body #content{ div{ transition: background-color 0.5s linear; + transition: z-index 2s linear; } #selectImage #content{ diff --git a/website/agenda/planung/css/audio_recordings.css b/website/agenda/planung/css/audio_recordings.css index a2ac4e3..9073b1c 100644 --- a/website/agenda/planung/css/audio_recordings.css +++ b/website/agenda/planung/css/audio_recordings.css @@ -26,3 +26,14 @@ th{ border:0; box-shadow:#888 2px 2px 1px 1px; } + + +#content div.ok, +#content div.warn, +#content div.error{ + padding-top:3px; + padding-bottom:3px; + margin:1px; + border-radius:4px; + text-align:center; +} diff --git a/website/agenda/planung/css/calendar.css b/website/agenda/planung/css/calendar.css index eef7b7a..31c9383 100644 --- a/website/agenda/planung/css/calendar.css +++ b/website/agenda/planung/css/calendar.css @@ -443,6 +443,11 @@ div#toolbar input.search{ display:none; } +#calendar div.event:hover { + min-height: 4rem!important; + z-index:99; +} + #calendar div.ui-draggable-dragging{ z-index:99; cursor:move; @@ -497,3 +502,13 @@ div.play .error{ padding-right:32px; } + +#content div.ok, +#content div.warn, +#content div.error{ + padding-top:3px; + padding-bottom:3px; + margin:1px; + border-radius:4px; + text-align:center; +} diff --git a/website/agenda/planung/js/audio_recordings.js b/website/agenda/planung/js/audio_recordings.js index f7b42d5..670c117 100644 --- a/website/agenda/planung/js/audio_recordings.js +++ b/website/agenda/planung/js/audio_recordings.js @@ -18,9 +18,9 @@ function changeFile(fileInput){ var file = fileInput.files[0]; var size = file.size / (1000*1000); $('#uploadSize').html(size + " MB"); - if (size > 300){ + if (size > 400){ $('#uploadButton').hide(); - showError("file is too large. maximum size is 300 MB! Please use MP3, 192 kHz, CBR, 44100 Hz, 16bit"); + showError("file is too large. maximum size is 400 MB! Please use MP3, 192 kHz, CBR, 44100 Hz, 16bit"); }else{ $('#uploadButton').show(); } diff --git a/website/agenda/planung/playout.cgi b/website/agenda/planung/playout.cgi index e7bab0a..88fa195 100755 --- a/website/agenda/planung/playout.cgi +++ b/website/agenda/planung/playout.cgi @@ -37,7 +37,6 @@ return if ( ( !defined $user ) || ( $user eq '' ) ); print "Content-type:text/html; charset=UTF-8;\n\n"; -#print STDERR $params->{project_id}."\n"; my $user_presets = uac::get_user_presets( $config, { diff --git a/website/agenda/planung/show-playout.cgi b/website/agenda/planung/show-playout.cgi index 550467e..16c8dbd 100755 --- a/website/agenda/planung/show-playout.cgi +++ b/website/agenda/planung/show-playout.cgi @@ -16,6 +16,8 @@ use studios; use series; use template; use playout; +use audio; + binmode STDOUT, ":utf8"; my $r = shift; @@ -52,7 +54,8 @@ $params = $request->{params}->{checked}; unless ( params::isJson() ) { 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, 'default.html' ), $headerParams ); + template::process( $config, 'print', template::check( $config, 'default.html' ), + $headerParams ); } return unless uac::check( $config, $params, $user_presets ) == 1; @@ -68,7 +71,8 @@ $params->{error} = $error || ''; showPlayout( $config, $request ); print STDERR "$0 ERROR: " . $params->{error} . "\n" if $params->{error} ne ''; -$params->{loc} = localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); +$params->{loc} = + localization::get( $config, { user => $params->{presets}->{user}, file => 'event,comment' } ); template::process( $config, 'print', $params->{template}, $params ); exit; @@ -89,7 +93,7 @@ sub showPlayout { my $today = time::time_to_date( time() ); my $startDate = time::add_days_to_date( $today, -14 ); - my $events = playout::get( + my $events = playout::get_scheduled( $config, { project_id => $params->{project_id}, @@ -110,10 +114,18 @@ sub showPlayout { $event->{stream_size} =~ s/(\d)(\d\d\d\.\d\d\d)$/$1\.$2/g; $event->{duration} =~ s/(\d\.\d)(\d+)$/$1/g; $event->{duration} =~ s/(\d)\.0/$1/g; - $event->{rms_left} = formatLoudness( $event->{rms_left} ); - $event->{rms_right} = formatLoudness( $event->{rms_right} ); - $event->{bitrate} = formatBitrate($event); - $event->{duration} = formatDuration($event); + $event->{rms_left} = audio::formatLoudness( $event->{rms_left} ); + $event->{rms_right} = audio::formatLoudness( $event->{rms_right} ); + $event->{bitrate} = audio::formatBitrate( $event->{bitrate} ); + $event->{bitrate_mode} = audio::formatBitrateMode( $event->{bitrate_mode} ); + $event->{sampling_rate} = audio::formatSamplingRate( $event->{sampling_rate} ); + $event->{duration} = audio::formatDuration( + $event->{duration}, + $event->{event_duration}, + sprintf( "%.1g h", $event->{duration} / 3600) + ); + $event->{channels} = audio::formatChannels( $event->{channels} ); + if ( $event->{start} lt $today ) { $event->{class} = "past"; } @@ -122,50 +134,6 @@ sub showPlayout { $params->{events} = $events; } -sub formatDuration { - my $event = $_[0]; - my $duration = $event->{duration}; - return '' unless defined $duration; - return '' if $duration eq ''; - my $result = ( ( $duration + 30 ) % 60 ) - 30; - my $class = "ok"; - $class = "warn" if abs($result) > 1; - $class = "error" if abs($result) > 2; - return sprintf( qq{
%.01f
}, $class, $duration ); -} - -sub formatBitrate { - my $event = $_[0]; - my $bitrate = $event->{bitrate} || ''; - my $mode = $event->{bitrate_mode} || ''; - if ( $bitrate ne '' ) { - if ( $bitrate >= 200 ) { - $bitrate = '
' . $bitrate . ' ' . $mode . '
'; - } elsif ( $bitrate < 190 ) { - $bitrate = '
' . $bitrate . ' ' . $mode . '
'; - } else { - $bitrate .= ' ' . $mode; - } - } - return $bitrate; -} - -sub formatLoudness { - my $value = shift; - return '' unless defined $value; - return '' if $value == 0; - return '' if $value eq ''; - - $value = sprintf( "%.1f", $value ); - my $class = 'ok'; - $class = 'warn' if $value > -18.5; - $class = 'error' if $value > -16.0; - $class = 'warn' if $value < -24.0; - $class = 'error' if $value < -27.0; - - return qq{
$value dB
}; -} - sub check_params { my $config = shift; my $params = shift; @@ -175,7 +143,8 @@ sub check_params { $checked->{template} = template::check( $config, $params->{template}, 'show_playout' ); #numeric values - for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) { + for my $param ( 'project_id', 'studio_id', 'default_studio_id', 'series_id', 'event_id', 'id' ) + { if ( ( defined $params->{$param} ) && ( $params->{$param} =~ /^\d+$/ ) ) { $checked->{$param} = $params->{$param}; } diff --git a/website/agenda/planung/templates/show_playout.html b/website/agenda/planung/templates/show_playout.html index 423a027..61d4ca2 100644 --- a/website/agenda/planung/templates/show_playout.html +++ b/website/agenda/planung/templates/show_playout.html @@ -33,7 +33,7 @@ -  ch. + diff --git a/website/agenda/planung/templates/upload_audio_recordings.html b/website/agenda/planung/templates/upload_audio_recordings.html index e290e2c..88b1598 100644 --- a/website/agenda/planung/templates/upload_audio_recordings.html +++ b/website/agenda/planung/templates/upload_audio_recordings.html @@ -77,9 +77,9 @@ - - - + + +