Беларусь |
Списки воспроизведения
Пример многосегментного воспроизведения в предыдущем разделе, это лишь учебное упражнение, так как приложения обычно не работают со списками воспроизведения, расположенными в памяти. Веротянее всего, приложение загрузит существующий список воспроизведения или создаст плейлист из файлов, которые выбрал пользователь.
WinRT поддерживает эти действия посредством простого API в пространстве имен Windows.Media.Playlists (http://msdn.microsoft.com/en-us/library/windows/apps/br206938.aspx), используя форматы WPL (Windows Media Player), ZPL (Zune) и M3U. Пример "Список воспроизведения" (http://code.msdn.microsoft.com/windowsapps/Playlist-sample-3d80daee) в Windows SDK (который почти победил в конкурсе на самое короткое название примера!) показывает, как выполнять различные задачи с данным API. В Сценарии 1 он позволяет вам выбрать несколько файлов с использованием средства выбора файлов, создает новый объект Windows. Media.Playlists.Playlist (http://msdn.microsoft.com/en-us/library/windows/apps/windows.media.playlists.playlist.aspx), добавляет выбранные файлы в его список files (вектор объектов StorageFile) и сохраняет список воспроизведения с помощью метода saveAsAsync (этот код из create.js упрощен и слегка переформатирован):
function pickAudio() { var picker = new Windows.Storage.Pickers.FileOpenPicker(); picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.musicLibrary; picker.fileTypeFilter.replaceAll(SdkSample.audioExtensions); picker.pickMultipleFilesAsync().done(function (files) { if (files.size > 0) { SdkSample.playlist = new Windows.Media.Playlists.Playlist(); files.forEach(function (file) { SdkSample.playlist.files.append(file); }); SdkSample.playlist.saveAsAsync(Windows.Storage.KnownFolders.musicLibrary, "Sample", Windows.Storage.NameCollisionOption.replaceExisting, Windows.Media.Playlists.PlaylistFormat.windowsMedia) .done(); } }
Обратите внимание на то, что saveAsAsync принимает объект типа StorageFolder и имя для файла (вместе с необязательным параметром формата). Это соответствует обычно используемому шаблону для списков воспроизведения, где у музыкального приложения есть отдельная папка, где оно хранит списки воспроизведения и предоставляет пользователю простые средства для их именования и/или выбора. При таком подходе списками воспроизведения обычно управляют не так как пользовательскими файлами, когда действия выполняются с помощью средства выбора файлов для выполнения команды Сохранить как (Save as) в произвольной папке. Вы можете использовать FileSavePicker, получить StorageFile, и использовать его свойство path для получения подходящего объекта StorageFolder, но вероятнее всего, вы будете сохранять списки воспроизведения в одном месте и представлять их в виде сущностей, которые появляются лишь внутри самого приложения.
Например, приложение Музыка (Music), поставляемое вместе с Windows 8, позволяет вам создавать новый список воспроизведения, когда вы просматриваете записи некоторого альбома. Следующие команды появляются на панели приложения (слева), и когда вы выбираете команду Новый список воспроизведения (New playlist), появляется всплывающий элемент (в середине), запрашивающий имя, после чего всплывающий элемент появляется на панели приложения (справа):
Созданный список воспроизведения затем появляется в приложении в виде другого альбома. Другими словами, хотя плейлисты можно сохранить как самостоятельные файлы, обычно нет нужды представлять их в подобном виде пользователю, и API отражает подобный шаблон их использования.
Для загрузки плейлиста используется метод Playlist.loadAsync, которому передается StorageFile для плейлиста. Это может быть объект StorageFile, полученный от средства выбора файлов, или из перечисления выделенной для списков воспроизведения папки приложения. Сценарий 2 примера "Список воспроизведения" (display.js) показывает последний подход, после чего осуществляется обход файлов и запрос их музыкальных свойств:
function displayPlaylist() { var picker = new Windows.Storage.Pickers.FileOpenPicker(); picker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.musicLibrary; picker.fileTypeFilter.replaceAll(SdkSample.playlistExtensions); var promiseCount = 0; picker.pickSingleFileAsync() .then(function (item) { if (item) { return Windows.Media.Playlists.Playlist.loadAsync(item); } return WinJS.Promise.wrapError("No file picked."); }) .then(function (playlist) { SdkSample.playlist = playlist; var promises = {}; // Запрос музыкальных свойств для каждого файла в списке. playlist.files.forEach(function (file) { promises[promiseCount++] = file.properties.getMusicPropertiesAsync(); }); // Вывод музыкальных свойств каждого файла. По причине асинхронной // природы вызова по получению музыкальных свойств, данные могут появиться // в ином порядке, нежели они заданы в исходном списке воспроизведения. // Для обеспечения верного порядка, мы используем Promise.join с ассоциативным массивом // переданным в качестве параметра, содержащим индекс каждого отдельного promise. return WinJS.Promise.join(promises); }) .done(function (results) { var output = "Playlist content:\n\n"; var musicProperties; for (var resultIndex = 0; resultIndex < promiseCount; resultIndex++) { musicProperties = results[resultIndex]; output += "Title: " + musicProperties.title + "\n"; output += "Album: " + musicProperties.album + "\n"; output += "Artist: " + musicProperties.artist + "\n\n"; } if (resultIndex === 0) { output += "(playlist is empty)"; } }, function (error) { // ... }); }
Мы вернемся к работе с этими специальными свойствами в следующем разделе, так как их обработка применима и к другим типам мультимедийных данных.
Другой метод управления плейлистами – это PlayList.saveAsync, который принимает единственный StorageFile. Такой подход используется, когда вы загружаете и модифицируете список воспроизведения и просто хотите сохранить эти изменения (что обычно выполняется автоматически, когда пользователь добавляет или удаляет элементы плейлиста). Это показано в Сценариях 3, 4 и 5 примера (add.js, js/remove.js и js/clear.js), где просто использованы методы вектора Playlist.files, наподобие append, removeAtEnd и clear, соответственно.
Проигрывание списка воспроизведения, конечно, зависит от типов включенных в него элементов, но обычно загружают плейлист и последовательно получают объекты StorageFile из его вектора files, передают их в URL.createObjectURL, и затем присваивают полученный URI атрибуту src элемента audio или video. Вы можете, кроме того, использовать плейлисты для управления списками изображений для слайд-шоу
Загрузка мультимедийных данных и управление ими
Пользователь может хранить медиафайлы везде, но изображения, музыка и видео обычно хранятся в соответствующих библиотеках пользователя. Проще говоря, это папки, которые медиа-приложениям следует использовать по умолчанию до тех пор, пока пользователь не укажет иную папку с помощью средства выбора папок. Как мы видели в "Состояния, параметры, файлы и документы" , приложения могут объявлять о программном доступе к библиотекам изображений, музыки и видео в манифестах, и получать объекты StorageFolder для них посредством Windows.Storage.KnownFolders:
var picsLib = Windows.Storage.KnownFolders.picturesLibrary; var musicLib = Windows.Storage.KnownFolders.musicLibrary; var vidsLib = Windows.Storage.KnownFolders.videosLibrary;
Приложения для работы с фотографиями обычно объявляют возможность Библиотека изображений (Pictures Library), и отображают ее содержимое в ListView. Приложения для работы с музыкой и видео так же используют соответствующие библиотеки, как вы можете видеть во встроенных приложениях Windows 8 Фотографии (Photos), Музыка (Music) и Видео (Video). Помните так же, что если вы забудете объявить соответствующие возможности, строки кода выше приведут к выдаче исключения "Доступ запрещен". Вы тут же поймете, если вы забудете эти важные особенности.
Я должен предупредить вас заранее, что работа с мультимедиа может быть очень сложной и запутанной. Поэтому вы, возможно, сочтете полезным просмотреть несколько материалов в документации, таких, как "Обработка файлов изображений" (http://msdn.microsoft.com/library/windows/apps/hh465103.aspx), "Перекодировка" (http://msdn.microsoft.com/ru-ru/library/windows/apps/hh452806.aspx), "Применение расширений мультимедиа" (http://msdn.microsoft.com/library/windows/apps/Hh700365.aspx).
Метаданные мультимедийных файлов
Когда у нас есть StorageFolder для некоторой медиабиблиотеки или некоторый набор таких объектов, мы можем использовать, как мы уже видели в "Состояния, параметры, файлы и документы" , их метод getItemAsync для получения их содержимого. Так же вы можете использовать файловые запросы для перечисления файлов, которые подпадают под некоторый критерий. В любом случае, в итоге вы получаете коллекцию объектов storageFile, с которой вы можете работать так, как вам нужно.
Теперь начинается кое-что интересное. Как я упоминал в "Состояния, параметры, файлы и документы" , вы можете получать дополнительные метаданные для этих файлов. Имеется несколько уровней данных, которые вы будете исследовать, начиная открывать тайные двери класса StorageFile, как показано на рис. 6.1. Следующий раздел, в свою очередь, посвящем этим областям.
Эскизы
Во-первых, вызов StorageFile.getThumbnailAsync предоставляет изображение эскиза, соответствующее конкретному "режиму" из перечисления Windows.Storage.FileProperties.ThumbnailMode (http://msdn.microsoft.com/library/windows/apps/windows.storage.fileproperties.thumbnailmode.aspx). Здесь есть такие варианты, как picturesView, videosView, musicView, documentsView, listView, и singleItem. То, что вы получите в обработчике завершения, это объект StorageItemThumbnail (http://msdn.microsoft.com/library/windows/apps/windows.storage.fileproperties.storageitemthumbnail.aspx), который предоставляет данные эскиза в виде потока. Вы можете удобно передать его нашему старому другу URL.createObjectURL для отображения в элементе img и так далее.
Примеры этого найти в примере "Эскизы файлов и папок" (http://code.msdn.microsoft.com/windowsapps/File-thumbnails-sample-17575959). Сценарий 1, например, (js/scenario1.js), предоставляет эскиз и отображает его в элементе img:
file.getThumbnailAsync(thumbnailMode, requestedSize, thumbnailOptions).done(function (thumbnail) { if (thumbnail) { outputResult(file, thumbnail, modeNames[modeSelected], requestedSize); } // ... }); function outputResult(item, thumbnailImage, thumbnailMode, requestedSize) { document.getElementById("picture-thumb-imageHolder").src = URL.createObjectURL(thumbnailImage, { oneTimeOnly: true }); // ... }
Общие свойства файлов
Общие свойства файлов – это те свойства, которые имеются у всех файлов – находятся во множестве различных мест. Наиболее общие свойства можно обнаружить непосредственно в объекте StorageFile, наподобие attributes, contentType, dateCreated, displayName, displayType, fileType, name, и path.
Свойства следующей группы можно получить из StorageFile.getBasicPropertiesAsync. Этот вызов предоставляет вам объект Windows.Storage.FileProperties.BasicProperties (http://msdn.microsoft.com/library/windows/apps/windows.storage.fileproperties.basicproperties.aspx), который содержит свойства dateModified, itemDate, и size. "Вот скукота!", скажете вы себе. Ну хорошо, у этого объекта еще есть дополнительный метод, который называется retrievePropertiesAsync, который предоставляет вам массив пар имя – значение для разных штуковин.
Весь фокус в том, чтобы понять, что вы можете взять массив имен свойств, которые вам нужны, где каждое имя – это строка, происходящая из очень длинного списка свойств Windows (http://msdn.microsoft.com/library/windows/desktop/dd561977.aspx), таких, как System.FileOwner и System.FileAttributes, и передать его retrievePropertiesAsync . Пример этого можно найти в Сценарии 5 примера "Перечисление папок" (http://code.msdn.microsoft.com/windowsapps/Folder-enumeration-sample-33ebd000), который мы видели в "Состояния, параметры, файлы и документы" :
var dateAccessedProperty = "System.DateAccessed"; var fileOwnerProperty = "System.FileOwner"; SdkSample.sampleFile.getBasicPropertiesAsync().then(function (basicProperties) { outputDiv.innerHTML += "Size: " + basicProperties.size + " bytes<br />"; outputDiv.innerHTML += "Date modified: " + basicProperties.dateModified + "<br />"; // Получить дополнительные свойства return SdkSample.sampleFile.properties.retrievePropertiesAsync([fileOwnerProperty, dateAccessedProperty]); }).done(function (extraProperties) { var propValue = extraProperties[dateAccessedProperty]; if (propValue !== null) { outputDiv.innerHTML += "Date accessed: " + propValue + "<br />"; } propValue = extraProperties[fileOwnerProperty]; if (propValue !== null) { outputDiv.innerHTML += "File owner: " + propValue; } });
Что здесь особенно удобно, так это то, что здесь вы можете получить почти любое свойство, которое вам нужно (список свойств содержит тысячи позиций), затем модифицировать массив и вызвать BasicProperties.savePropertiesAsync. Вуаля! Только что вы обновили эти свойства файлов. Вариация savePropertiesAsync так же позволяет вам передавать специальный массив из пар имя – значение, если вы лишь хотите изменить лишь некоторые из свойств.
Третий набор свойств можно найти, если пройти через тайную дверь StorageFile.properties. Здесь содержится объект StorageItemContentProperties (http://msdn.microsoft.com/library/windows/apps/windows.storage.fileproperties.storageitemcontentproperties.aspx), методы которого retrievePropertiesAsync и savePropertiesAsync похожи на те, что мы видели у BasicProperties. Гораздо интереснее то, что у него есть еще четыре метода: getDocumentPropertiesAsync, getImagePropertiesAsync, getMusicPropertiesAsync, и getVideoPropertiesAsync. С их помощью вы можете получить по-настоящему специальные сведения для конкретных типов файлов, как мы увидим дальше.