protected function action_stats()
 {
     $g = new xml_gen();
     $s = new morg_stats($this->dbh);
     $this->head('Statistics', './');
     // general stats
     echo $g->h4('General Statistics');
     $t = new Table(2, "id='stats'", null, 'left;right;left');
     $t->data('Total number of tracks:');
     $t->data(number_format($s->number_of_tracks()));
     // filesize stats
     $t->row_attr("class='add_space'");
     $t->data('Total size of tracks:');
     $t->data($this->display_bytes_human_readable($s->size_of_tracks()));
     $t->data('Average track size:');
     $t->data($this->display_bytes_human_readable($s->average_size_of_tracks()));
     // playing time stats
     $t->row_attr("class='add_space'");
     $t->data('Total track length:');
     $t->data($this->display_seconds_as_days($s->length_of_tracks()));
     $t->data('Total track length:');
     $t->data($this->display_seconds_human_readable($s->length_of_tracks()));
     $t->data('Average track length:');
     $t->data($this->display_seconds_human_readable($s->average_length_of_tracks()));
     $t->done();
     // file formats stats
     echo $g->h4('File Formats');
     $t = new Table(5, "id='stats2'", null, 'left;right;right;right;right');
     foreach ($s->format_names_array() as $format_name_id => $format_name) {
         $t->data($format_name);
         $t->data(number_format($s->number_of_tracks($format_name_id)) . ' files');
         $t->data($this->display_bytes_human_readable($s->size_of_tracks($format_name_id)));
         $t->data($this->display_seconds_human_readable($s->length_of_tracks($format_name_id)));
         $t->data(number_format($s->average_bit_rate($format_name_id) / 1000) . ' kbps');
     }
     $t->done();
     // reports
     echo $g->h4('Reports');
     $t = new Table(3, "id='stats3'");
     $t->data('File Formats/Encoders');
     $t->data();
     $t->data('[' . $g->a('./?action=stats_formats', 'view', "title='View report'") . ']');
     $t->data('Fields');
     $t->data();
     $t->data('[' . $g->a('./?action=stats_fields', 'view', "title='View report'") . ']');
     $t->data('Duplicate Files (md5_data)');
     $t->data();
     $t->data('[' . $g->a('./?action=stats_duplicates1&field=artist', 'view', "title='View report'") . ']');
     $t->data('Duplicate Files (metadata)');
     $t->data();
     $t->data('[' . $g->a('./?action=stats_duplicates2&field=artist', 'view', "title='View report'") . ']');
     $t->done();
     // problems
     echo $g->h4('Problems');
     $t = new Table(3, "id='stats4'");
     $t->data('Files not tagged');
     $t->data(number_format($s->count_tagless()) . ' items');
     $t->data('[' . $g->a('./?action=stats_tagless', 'view', "title='View report'") . ']');
     // missing key fields
     foreach ($this->key_fields() as $field) {
         $t->data('Files missing ' . $field . ' field');
         $t->data(number_format($s->count_missing_key_field($field)) . ' items');
         $t->data('[' . $g->a('./?action=stats_key_field&field=' . $field, 'view', "title='View report'") . ']');
     }
     $t->data('Files missing replaygain info');
     $t->data(number_format($s->count_missing_replaygain()) . ' items');
     $t->data('[' . $g->a('./?action=stats_replaygain', 'view', "title='View report'") . ']');
     $t->data('Directories without artwork');
     $t->data(number_format($s->count_artless_directories()) . ' items');
     $t->data('[' . $g->a('./?action=stats_artless_dirs', 'view', "title='View report'") . ']');
     $t->done();
     $this->foot();
 }
            $t->data('Tags', 'class=header');
            $t->data('Warnings', 'class=header');
            $t->data('Scan Time', 'class=header');
            //$t->data('Edit Tags', 'class=header');
            $counter = 19;
        }
        $link_name = $short_name;
        if (strlen($short_name) > GETID3_FILENAME_LENGTH) {
            if (preg_match('/^(.*)\\.([a-zA-Z0-9]{1,5})$/', $short_name, $r)) {
                $link_name = substr($r[1], 0, GETID3_FILENAME_LENGTH - 2 - strlen($r[2])) . '...' . $r[2];
            } else {
                $link_name = substr($short_name, 0, GETID3_FILENAME_LENGTH - 2);
            }
        }
        $i++;
        $t->row_attr("id='row{$i}'");
        $t->data(xml_gen::a($_SERVER['SCRIPT_NAME'] . '?filename=' . urlencode($full_name), $link_name, 'title="' . $short_name . '"'));
        $t->data('Scanning in progress... Please wait.', "colspan=8 id=wait{$i}");
        $t->data(null, "id=scan{$i}");
        //$t->data();
    }
}
// Finish table
$t->done();
// Finish page
CommonFooter();
// DHTML/PHP update scripts
echo "\n<script>\n\nfunction upd_entry(row_num, format, playtime, bitrate, audio, artist, title, tags, warnings, ms) {\n\n    row = document.getElementById('row' + row_num);\n\n    row.deleteCell(1);\n\n    cell = row.insertCell(1);   cell.innerHTML = format;\n    cell = row.insertCell(2);   cell.innerHTML = playtime;\n    cell = row.insertCell(3);   cell.innerHTML = bitrate;\n    cell = row.insertCell(4);   cell.innerHTML = audio;\n    cell = row.insertCell(5);   cell.innerHTML = artist;\n    cell = row.insertCell(6);   cell.innerHTML = title;\n    cell = row.insertCell(7);   cell.innerHTML = tags;\n    cell = row.insertCell(8);   cell.innerHTML = warnings;\n\n    document.getElementById('scan' + row_num).innerHTML = ms;\n}\n\nfunction upd_error(row_num, msg, ms) {\n\n    document.getElementById('wait' + row_num).innerHTML = '<span class=error>ERROR: ' + msg + '</span>';\n    document.getElementById('scan' + row_num).innerHTML = ms;\n\n}\n\n</script>\n";
function upd_entry($row_num, $format, $playtime, $bitrate, $audio, $artist, $title, $tags, $warnings, $ms)
{
    $time = number_format($ms * 1000) . " ms";