/* This file is part of Subsonic. Subsonic is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Subsonic is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Subsonic. If not, see <http://www.gnu.org/licenses/>. Copyright 2009 (C) Sindre Mehus */ package net.sourceforge.subsonic.dao; import net.sourceforge.subsonic.Logger; import net.sourceforge.subsonic.domain.MediaFile; import net.sourceforge.subsonic.domain.MediaType; import org.springframework.jdbc.core.simple.ParameterizedRowMapper; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import java.util.Random; /** * Provides database services for media files. * * @author Sindre Mehus */ public class MediaFileDao extends AbstractDao { private static final Logger LOG = Logger.getLogger(MediaFileDao.class); private static final String COLUMNS = "id, path, media_type, format, is_directory, is_album, title, album, artist, disc_number, " + "track_number, year, genre, bit_rate, variable_bit_rate, duration_seconds, file_size, width, height, cover_art_path, " + "parent_path, play_count, last_played, comment, created, last_modified, children_last_updated, enabled"; private static final Random RANDOM = new Random(System.currentTimeMillis()); private final MediaFileMapper rowMapper = new MediaFileMapper(); /** * Returns the media file for the given path. * * @param path The path. * @return The media file or null. */ public MediaFile getMediaFile(String path) { return queryOne("select " + COLUMNS + " from media_file where path=?", rowMapper, path); } /** * Returns a subset of all media files. */ public List<MediaFile> getMediaFiles(int offset, int size) { return query("select " + COLUMNS + " from media_file order by id limit ? offset ?", rowMapper, size, offset); } /** * Returns the media file that are direct children of the given path. * * @param path The path. * @return The list of children. */ public List<MediaFile> getChildrenOf(String path) { return query("select " + COLUMNS + " from media_file where parent_path=?", rowMapper, path); } /** * Creates a new media file. * * @param file The media file to create. */ public void createOrUpdateMediaFile(MediaFile file) { update("delete from media_file where path=?", file.getPath()); String sql = "insert into media_file (" + COLUMNS + ") values (" + questionMarks(COLUMNS) + ")"; update(sql, null, file.getPath(), file.getMediaType() == null ? null : file.getMediaType().name(), file.getFormat(), file.isDirectory(), file.isAlbum(), file.getTitle(), file.getAlbumName(), file.getArtist(), file.getDiscNumber(), file.getTrackNumber(), file.getYear(), file.getGenre(), file.getBitRate(), file.isVariableBitRate(), file.getDurationSeconds(), file.getFileSize(), file.getWidth(), file.getHeight(), file.getCoverArtPath(), file.getParentPath(), file.getPlayCount(), file.getLastPlayed(), file.getComment(), file.getCreated(), file.getLastModified(), file.getChildrenLastUpdated(), file.isEnabled()); LOG.debug("Created/updated media_file for " + file.getPath()); } public void deleteMediaFile(String path) { update("delete from media_file where path=?", path); } public List<String> getGenres() { return queryForString("select distinct genre from media_file where genre is not null order by genre"); } public MediaFile getRandomAlbum() { int n = queryForInt("select count(*) from media_file where is_album"); return queryOne("select " + COLUMNS + " from media_file where is_album order by id limit 1 offset ?", rowMapper, RANDOM.nextInt(n)); } private static class MediaFileMapper implements ParameterizedRowMapper<MediaFile> { public MediaFile mapRow(ResultSet rs, int rowNum) throws SQLException { return new MediaFile( rs.getInt(1), rs.getString(2), rs.getString(3) == null ? null : MediaType.valueOf(rs.getString(3)), rs.getString(4), rs.getBoolean(5), rs.getBoolean(6), rs.getString(7), rs.getString(8), rs.getString(9), rs.getInt(10) == 0 ? null : rs.getInt(10), rs.getInt(11) == 0 ? null : rs.getInt(11), rs.getInt(12) == 0 ? null : rs.getInt(12), rs.getString(13), rs.getInt(14) == 0 ? null : rs.getInt(14), rs.getBoolean(15), rs.getInt(16) == 0 ? null : rs.getInt(16), rs.getLong(17) == 0 ? null : rs.getLong(17), rs.getInt(18) == 0 ? null : rs.getInt(18), rs.getInt(19) == 0 ? null : rs.getInt(19), rs.getString(20), rs.getString(21), rs.getInt(22), rs.getTimestamp(23), rs.getString(24), rs.getTimestamp(25), rs.getTimestamp(26), rs.getTimestamp(27), rs.getBoolean(28)); } } }