29 сентября 2010 г.

О субтитрах формата ttxt

Пример субтитров формата 3GPP timed text:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!-- GPAC 3GPP Text Stream -->
  3. <TextStream version="1.1">
  4. <TextStreamHeader width="320" height="60" layer="0" translation_x="0" translation_y="0">
  5. <TextSampleDescription horizontalJustification="center" verticalJustification="bottom" backColor="0 ff 0 80" verticalText="no" fillTextRegion="no" continuousKaraoke="no" scroll="None">
  6. <FontTable>
  7. <FontTableEntry fontName="Serif" fontID="1"/>
  8. <FontTableEntry fontName="Helvetica" fontID="2"/>
  9. <FontTableEntry fontName="Arial" fontID="3"/>
  10. </FontTable>
  11. <TextBox top="0" left="0" bottom="60" right="320"/>
  12. <Style styles="Normal" fontID="1" fontSize="18" color="ff ff 00 ff"/>
  13. </TextSampleDescription>
  14. </TextStreamHeader>
  15. <TextSample sampleTime="00:00:00.000" xml:space="preserve"></TextSample>
  16. <TextSample sampleTime="00:00:00.800" xml:space="preserve">Детки, в каждой любовной истории
  17. есть два особенных дня:<Style fromChar="10" toChar="46" styles="Italic " fontID="2" fontSize="18" color="ff ff 00 80"/><Style fromChar="16" toChar="40" fontID="1" fontSize="18" color="00 ff 00 80"/>
  18. </TextSample>
  19. <TextSample sampleTime="00:00:03.794" xml:space="preserve"></TextSample>
  20. <TextSample sampleTime="00:00:03.895" xml:space="preserve">День, когда встречаешь
  21. девушку своей мечты,<Style fromChar="0" toChar="43" styles="Italic " fontID="3" fontSize="18" color="ff ff ff ff"/>
  22. </TextSample>
  23. <TextSample sampleTime="00:00:06.246" xml:space="preserve"></TextSample>
  24. <TextSample sampleTime="00:00:06.247" xml:space="preserve">и день, когда женишься на ней.<Style fromChar="0" toChar="30" styles="Italic " fontID="1" fontSize="18" color="ff ff ff ff"/>
  25. </TextSample>
  26. <TextSample sampleTime="00:00:07.882" xml:space="preserve"></TextSample>
  27. </TextStream>

хорошее описание тэгов есть здесь. Для меня интересен тэг TextSample, так как он может содержать в себе тэг Style, что в свою очередь дает возможность изменят цвет субтитра и его стиль. Так-же MP4Box хорошо вставляет субтитры этого формата в контейнер MPEG 4, который потом прогрывается на iPhone. Правда iPhone так-же как и с SubRip Text субтитрами не понимает полужирный текст и изменение шрифтов.

28 сентября 2010 г.

О субтитрах формата srt

Формат SubRip Text пожалуй самый популярный из форматов субтитров. Файл этого формата имеет расширение .srt и состоит из последовательности блоков. Каждый блок имеет формат:

  1. <Номер блока>
  2. <Время начала показа субтитра> --> <Время конца показа субтитра>
  3. Текст субтитра (одна или несколько строк)
  4. <пустая строка>


Номер блока - целое число начинающееся с 1, время начала и конца показа субтитра имеет формат HH:MM:SS,milliseconds, пустая строка необходима для отделения блоков в файле и текст субтитра не может содержать пустых строк.

Пример файла:

  1. 1
  2. 00:00:20,000 --> 00:00:24,400
  3. Бла-<font color="#4096d1">бла</font>-бла
  4. <i>ыва</i>


  5. 2
  6. 00:00:24,600 --> 00:00:27,800
  7. йцукен


текст субтитра может содержать тэги, и многие плееры их подтерживают. Мне извесны такие тэги в тексте субтитра:
<b>…</b> - полужирный
<i>…</i> - наклонный
<u>…</u> - подчеркнутый шрифты
<font color="#RRGGBB">…</font> - задает цвет текста

Что интересно, при кодировании видео для iPhone и добавлении субтитров SubRip Text формата (использовался MP4Box) iPhone корректно отображал тэги в субтитрах (кроме <b>)

23 сентября 2010 г.

"Привязываем" UISearchBar к UITableView

У меня возникла задача использовать фильтр к большому списку однотипных элементов (проще говоря поиск). Раньше я решал такую задачу кидая на UINavigationBar элемент UITextField и обрабатывал его события, но выглядело это очень некрасиво. UISearchBar хоть и занимает дополнительное место на экране, но выглядит приятно и вписывается в интерфейс, хотя при редактировании в UISearchBar можно скрывать UINavigationBar для освобождения пространства на экране.

Как я реализовывал.
Есть класс наследник от UIViewController в котором находятся визуальные компоненты (UISearchBar и UITableView). Так-же этот класс содержит два массива: массив со всеми элементами которые могут присутствовать в списке, второй с элементами которые удовлетворяют условиям поиска. Изначально массивы равны. Второй массив необходимо отображать в UITableView и применять к нему фильтр при изменении текста в UISearchBar. Просто?

Начнем с функции поиска, в моем случае я у меня строковые массивы (itemsList - со всеми элементами, searched - с элементами которые удовлетворяют условию из UISearchBar). Единственным параметр функции - строка из UISearchBar:

  1. - (void) search:(NSString *) matchString
  2. {
  3.   NSString *upString = [matchString uppercaseString];
  4.   if (searched)
  5.     [searched release];
  6.   searched = [[NSMutableArray alloc] init];
  7.   for (NSString *line in itemsList)
  8.   {
  9.     if ([matchString length] == 0)
  10.     {
  11.       [searched addObject:line];
  12.       continue;
  13.     }
  14.     NSRange range = [[line uppercaseString] rangeOfString:upString];
  15.     if (range.location != NSNotFound)
  16.       [searched addObject:line];
  17.   }
  18.   [tv reloadData]; // UITableView
  19. }


я тут не боролся за оптимальность поиска. Можно было б не пересоздавать при каждом вызове массив searched, а так-же учитывать предыдущий поиск.

Функция search: должна вызываться при каждом изменении в UISearchBar, для которого нужно определить делегат с методом searchBar:textDidChange:

  1. - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
  2. {
  3.   [self search:searchText];
  4. }


так-же для иницилизации массива searched метод search: нужно вызвать при загрузке вью конттроллера, например в методе loadView

  1. - (void)loadView
  2. {
  3.   [self search:@""];
  4. }


и осталось отобразить массив searched в UITableView

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  2. {
  3.   UITableViewCell *rv = nil;
  4.   NSString *cellID = @"cell_ID";
  5.   rv = [tableView dequeueReusableCellWithIdentifier:cellID];
  6.   if (rv==nil)
  7.   {
  8.     rv = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellID] autorelease];
  9.   }
  10.   rv.textLabel.text = [searched objectAtIndex:indexPath.row];
  11.   return rv;
  12. }


В статье не описано, что нужно обрабатывать появление клавиатуры, а так-же можно скрывать UINavigationBar при фокусе на UISearchBar, что есть в примере.

22 сентября 2010 г.

Изменение размера системного раздела в Ubuntu Linux

Есть у меня на работе несколько виртуальных серверов под управлением Ubuntu Linux для локальных задач которые зависят от конкретных версий пакетов. Сегодня на одном из серверов закончилось дисковое пространство, проблема усугубилась тем, что в этой виртуальной машине диск имеет один единственный раздел, т.е. изменять размер прийдется системному разделу.

Как увеличить размер диска с помощью средств виртуализации я не буду, там все просто. После этой операции Ubuntu видит увеличенный обьем диска как неразмеченную область, нужно добавить эту область к уже существующему разделу. Для этого нужно загрузить виртуальную машину с установочного диска (у меня это Ubuntu 9.10 Desktop Edition).

Изменять размер раздела будем с помощью утилиты gparted (графическая надстройка над консольной parted), я пробовал parted, но с первого раза у меня не получилось изменить размер и поэтому я выбрал графическую версию, для меньшей вероятности потерять данные.


Выбираем нужный раздел диска и в сплывающем меню выбираем "Resize/Move".


двигаем ползунков размера диска покрывая неразмеченую область диска. Сохраняем изменения на диск.

Все. После перезагрузки машины размер вашего диска увеличился.

20 сентября 2010 г.

Запуск приложения в "ландшафтном" режиме

Иногда необходимо, что б iPhone приложение запускалось в горизонтальном (ландшафтном) режиме. Все довольно просто, и ограничивается правкой файла Info.plist приложения. Добавляем в него ключ UIInterfaceOrientation со значением UIInterfaceOrientationLandscapeLeft или UIInterfaceOrientationLandscapeRight.



не забывайте, что метод shouldAutorotateToInterfaceOrientation: вью-контоллеров приложения должны возвращать YES для выбранной ориентации, и элементы во вью должны правльно изменять размер при изменении ориентации устройства.

Пример приложения

14 сентября 2010 г.

Бекапы подключенных к iTunes устройств

При синхронизации с устройством (iPhone|iPod Touch|iPad) iTunes делает бекап файлов настройки устройства а так-же данные приложений на установленных на устройстве.

Лежат эти бекапы в папке:
~/Library/Application Support/MobileSync/Backup/

13 сентября 2010 г.

Даунмикс аудио 5.1 в стерео (ffmpeg)

Даунмикс мне необходим для конвертирования видео для iPhone/iPod Touch.
Использую ffmpeg:

  1. $ ffmpeg -y -i <input_audio> -map 0.1 -vn -acodec libfaac -ab 128k -ac 2 -ar 41000 -strict experimental <out.aac>



некоторые типы аудио у меня ffmpeg незахотел конвертировать командой выше (например "Stream #0.0: Audio: aac, 48000 Hz, 5.1, s16, 148 kb/s"). Из-за этого пришлось конвертировать через временный файл

  1. $ ffmpeg -y -i <input_audio> -map 0.1 -vn -acodec ac3 -ab 448k -ar 44100 -ac 6 ./tmp.ac3
  2. $ ffmpeg -y -i ./tmp.ac3 -vn -acodec libfaac -ab 128k -ar 44100 -ac 2 <out_audio>.aac


Если есть более лучший вариант, пишите.

10 сентября 2010 г.

Подключение проекта статической библиотеки к вашему проекту в xCode

Сейчас я не буду рассказывать о прелестях использования статических библиотек при программировании для iPhone, а просто опишу как подключить проект статической библиотеки к вашему проекту. Итак, у вас имеется проект статической библиотеки и проект (буду его называть проектом приложения) в который вы хотите ее подключить.

Открываем в xCode проект приложения. В Finder переходим в папку проекта статической бибилотеки и перетаскиваем файл проекта в xCode


Идем в меню Project->Edit Active Target "…". В появившемся окне жмем на "+" на вкладке "General" в группе "Direct Dependencies" и выбираем статическую библиотеку только-что добавленную в проект.


после добавления


а так выглядит "Group & Files" в окне проекта приложения


теперь нужно сказать xCode, что при сборке этого таргета необходимо прилинковывать нашу статическую библиотеку. Для этого перетаскиваем библиотеку и проекта библиотеки в секцию "Link Binary With Libraries" таргета приложения.


теперь можно добавить заготовочные файлы библиотеки в проект приложения и запускать приложение.

Если ваша статическая библиотека использует классы ObjectiveC, то в свойствах проекта добавте ключ -ObjC к "Other Linker Flags"



Пример.

8 сентября 2010 г.

Извлечение постера сериала/фильма из iTunes Store

Мне сегодня понадобился постер сериала из iTunes Store. Я знал, что есть у каждого постера постоянная http-ссылка, но инструкции как ее получить на просторах Всемирной паутины не нашел. Пришлось разбираться самому.

Итак имеем телешоу в iTunes Store, копируем ссылку на него прямо из iTunes:


Открываем ссылку в браузере


теперь нужно скопировать ссылку на постер размером 100х100:


имеем ссылку типа:

http://a1.phobos.apple.com/us/r30/Features/a2/76/0d/dj.wvuibynu.100x100-75.jpg

жирным выделен размер изображения. Существует несколько размеров изображений, нам необходим максимальный, для фильмов это 227х227, для телешоу - 600х600. Получаем:

http://a1.phobos.apple.com/us/r30/Features/a2/76/0d/dj.wvuibynu.600x600-75.jpg

PS: Найдены еще такие размеры постеров (некоторых может не быть):
110x110
140x140
167x167
170x170
176x176
182x182
200x200
225x225
227x227
600х600

3 сентября 2010 г.

Создание шаблонов приложений в xCode (часть 2)

В первой части я рассказывал о создании проекта в шаблоне xCode. В этой части разберем файл TemplateChooser.plist и отличие проекта шаблона от обычного проекта.

В файле TemplateChooser.plist расположено описание окна "New Project" выбраного шаблона, а так же набор правил выбора проекта из шаблона в зависимости от выбраных пользователем параметров шаблона.


Приведенный пример представлен хешом из 4-х элементов: "Checkboxes", "OptionsLabel", "PopupMenu" и "TemplateSelection". Первые три отвечают за внешний вид она "New Project" при выбраном шаблоне, TemplateSelection - за правила выбора проекта из шаблона.

Секции Checkboxes это массив чекбоксов, а PopupMenu отвечает за пункты во всплывающем списке при выборе шаблона. OptionsLabel отвечает только за заголовок. Каждый элемент этих массивов имеет уникальный идинтификатор (Key) и строку описания(Title) которая выводится как имя элемента.

TemplateSelection это хеш, который указывает какой проект из шаблона выбрать в зависимости от выбранных параметров в шаблоне. Ключ хеша - это строка составленная из идинтификаторов выбранных опций, значение - имя проекта из шаблона который должен использоваться.

Например в таком варианте:


будет использоваться ключ "iPhoneStorage"

Сам проект в шаблоне тоже немного отличается от стандартного проекта. В папке проекта содержаться два файла: TemplateIcon.icns и TemplateInfo.plist. Первый - иконка шаблона, второй - краткое описание шаблона.