From 57e2f323c716056c45fb64f8e8d1f5e034ad0f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 9 Jun 2005 20:28:21 +0000 Subject: [PATCH] Added SoundRecorder (inspired by SoundCapture from beos samples) Alpha state git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13035 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/Jamfile | 1 + src/apps/soundrecorder/DrawingTidbits.cpp | 78 + src/apps/soundrecorder/DrawingTidbits.h | 50 + src/apps/soundrecorder/FileUtils.cpp | 100 + src/apps/soundrecorder/FileUtils.h | 21 + src/apps/soundrecorder/Jamfile | 19 + src/apps/soundrecorder/RecorderApp.cpp | 37 + src/apps/soundrecorder/RecorderApp.h | 26 + src/apps/soundrecorder/RecorderWindow.cpp | 1233 ++++++++++++ src/apps/soundrecorder/RecorderWindow.h | 164 ++ src/apps/soundrecorder/ScopeView.cpp | 271 +++ src/apps/soundrecorder/ScopeView.h | 55 + src/apps/soundrecorder/SoundConsumer.cpp | 706 +++++++ src/apps/soundrecorder/SoundConsumer.h | 173 ++ src/apps/soundrecorder/SoundListView.cpp | 70 + src/apps/soundrecorder/SoundListView.h | 40 + src/apps/soundrecorder/SoundPrivate.h | 41 + src/apps/soundrecorder/SoundRecorder.rdef | 83 + src/apps/soundrecorder/SoundUtils.cpp | 103 + src/apps/soundrecorder/SoundUtils.h | 56 + src/apps/soundrecorder/TrackSlider.cpp | 465 +++++ src/apps/soundrecorder/TrackSlider.h | 54 + src/apps/soundrecorder/TransportButton.cpp | 734 +++++++ src/apps/soundrecorder/TransportButton.h | 212 ++ src/apps/soundrecorder/UpDownButton.cpp | 100 + src/apps/soundrecorder/UpDownButton.h | 31 + src/apps/soundrecorder/VUView.cpp | 194 ++ src/apps/soundrecorder/VUView.h | 40 + src/apps/soundrecorder/VolumeSlider.cpp | 176 ++ src/apps/soundrecorder/VolumeSlider.h | 44 + src/apps/soundrecorder/array_delete.h | 30 + src/apps/soundrecorder/icon_button.h | 2061 ++++++++++++++++++++ 32 files changed, 7468 insertions(+) create mode 100644 src/apps/soundrecorder/DrawingTidbits.cpp create mode 100644 src/apps/soundrecorder/DrawingTidbits.h create mode 100644 src/apps/soundrecorder/FileUtils.cpp create mode 100644 src/apps/soundrecorder/FileUtils.h create mode 100644 src/apps/soundrecorder/Jamfile create mode 100644 src/apps/soundrecorder/RecorderApp.cpp create mode 100644 src/apps/soundrecorder/RecorderApp.h create mode 100644 src/apps/soundrecorder/RecorderWindow.cpp create mode 100644 src/apps/soundrecorder/RecorderWindow.h create mode 100644 src/apps/soundrecorder/ScopeView.cpp create mode 100644 src/apps/soundrecorder/ScopeView.h create mode 100644 src/apps/soundrecorder/SoundConsumer.cpp create mode 100644 src/apps/soundrecorder/SoundConsumer.h create mode 100644 src/apps/soundrecorder/SoundListView.cpp create mode 100644 src/apps/soundrecorder/SoundListView.h create mode 100644 src/apps/soundrecorder/SoundPrivate.h create mode 100644 src/apps/soundrecorder/SoundRecorder.rdef create mode 100644 src/apps/soundrecorder/SoundUtils.cpp create mode 100644 src/apps/soundrecorder/SoundUtils.h create mode 100644 src/apps/soundrecorder/TrackSlider.cpp create mode 100644 src/apps/soundrecorder/TrackSlider.h create mode 100644 src/apps/soundrecorder/TransportButton.cpp create mode 100644 src/apps/soundrecorder/TransportButton.h create mode 100644 src/apps/soundrecorder/UpDownButton.cpp create mode 100644 src/apps/soundrecorder/UpDownButton.h create mode 100644 src/apps/soundrecorder/VUView.cpp create mode 100644 src/apps/soundrecorder/VUView.h create mode 100644 src/apps/soundrecorder/VolumeSlider.cpp create mode 100644 src/apps/soundrecorder/VolumeSlider.h create mode 100644 src/apps/soundrecorder/array_delete.h create mode 100644 src/apps/soundrecorder/icon_button.h diff --git a/src/apps/Jamfile b/src/apps/Jamfile index 6fe76ed7f2..93947c1ef4 100644 --- a/src/apps/Jamfile +++ b/src/apps/Jamfile @@ -14,6 +14,7 @@ SubInclude OBOS_TOP src apps people ; SubInclude OBOS_TOP src apps poorman ; SubInclude OBOS_TOP src apps pulse ; SubInclude OBOS_TOP src apps showimage ; +SubInclude OBOS_TOP src apps soundrecorder ; SubInclude OBOS_TOP src apps stylededit ; SubInclude OBOS_TOP src apps terminal ; SubInclude OBOS_TOP src apps tracker ; diff --git a/src/apps/soundrecorder/DrawingTidbits.cpp b/src/apps/soundrecorder/DrawingTidbits.cpp new file mode 100644 index 0000000000..cccfdb5785 --- /dev/null +++ b/src/apps/soundrecorder/DrawingTidbits.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include +#include +#include + +#include "DrawingTidbits.h" + +rgb_color +ShiftColor(rgb_color color, float percent) +{ + rgb_color result = { + ShiftComponent(color.red, percent), + ShiftComponent(color.green, percent), + ShiftComponent(color.blue, percent), + 0 + }; + + return result; +} + +static bool +CompareColors(const rgb_color a, const rgb_color b) +{ + return a.red == b.red + && a.green == b.green + && a.blue == b.blue + && a.alpha == b.alpha; +} + +bool +operator==(const rgb_color &a, const rgb_color &b) +{ + return CompareColors(a, b); +} + +bool +operator!=(const rgb_color &a, const rgb_color &b) +{ + return !CompareColors(a, b); +} + +void +ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to) +{ + ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet + + BScreen screen(B_MAIN_SCREEN_ID); + uint32 fromIndex = screen.IndexForColor(from); + uint32 toIndex = screen.IndexForColor(to); + + uchar *bits = (uchar *)bitmap->Bits(); + int32 bitsLength = bitmap->BitsLength(); + for (int32 index = 0; index < bitsLength; index++) + if (bits[index] == fromIndex) + bits[index] = toIndex; +} + +void +ReplaceTransparentColor(BBitmap *bitmap, rgb_color with) +{ + ASSERT(bitmap->ColorSpace() == B_COLOR_8_BIT); // other color spaces not implemented yet + + BScreen screen(B_MAIN_SCREEN_ID); + uint32 withIndex = screen.IndexForColor(with); + + uchar *bits = (uchar *)bitmap->Bits(); + int32 bitsLength = bitmap->BitsLength(); + for (int32 index = 0; index < bitsLength; index++) + if (bits[index] == B_TRANSPARENT_8_BIT) + bits[index] = withIndex; +} + diff --git a/src/apps/soundrecorder/DrawingTidbits.h b/src/apps/soundrecorder/DrawingTidbits.h new file mode 100644 index 0000000000..a0d2374bf6 --- /dev/null +++ b/src/apps/soundrecorder/DrawingTidbits.h @@ -0,0 +1,50 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef __DRAWING_TIBITS__ +#define __DRAWING_TIBITS__ + +#include + +rgb_color ShiftColor(rgb_color , float ); + +bool operator==(const rgb_color &, const rgb_color &); +bool operator!=(const rgb_color &, const rgb_color &); + +inline uchar +ShiftComponent(uchar component, float percent) +{ + // change the color by , make sure we aren't rounding + // off significant bits + if (percent >= 1) + return (uchar)(component * (2 - percent)); + else + return (uchar)(255 - percent * (255 - component)); +} + +inline rgb_color +Color(int32 r, int32 g, int32 b, int32 alpha = 255) +{ + rgb_color result; + result.red = r; + result.green = g; + result.blue = b; + result.alpha = alpha; + + return result; +} + +const rgb_color kWhite = { 255, 255, 255, 255}; +const rgb_color kBlack = { 0, 0, 0, 255}; + +const float kDarkness = 1.06; +const float kDimLevel = 0.6; + +void ReplaceColor(BBitmap *bitmap, rgb_color from, rgb_color to); +void ReplaceTransparentColor(BBitmap *bitmap, rgb_color with); + +#endif \ No newline at end of file diff --git a/src/apps/soundrecorder/FileUtils.cpp b/src/apps/soundrecorder/FileUtils.cpp new file mode 100644 index 0000000000..3912046dda --- /dev/null +++ b/src/apps/soundrecorder/FileUtils.cpp @@ -0,0 +1,100 @@ +/******************************************************************************* +/ +/ File: FileUtils.cpp +/ +/ Description: Utility functions for copying file data and attributes. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#include +#include +#include "array_delete.h" +#include "FileUtils.h" + +status_t CopyFileData(BFile& dst, BFile& src) +{ + struct stat src_stat; + status_t err = src.GetStat(&src_stat); + if (err != B_OK) { + printf("couldn't get stat: %#010lx\n", err); + return err; + } + + size_t bufSize = src_stat.st_blksize; + if (! bufSize) { + bufSize = 32768; + } + + char* buf = new char[bufSize]; + array_delete bufDelete(buf); + + printf("copy data, bufSize = %ld\n", bufSize); + // copy data + while (true) { + ssize_t bytes = src.Read(buf, bufSize); + if (bytes > 0) { + ssize_t result = dst.Write(buf, bytes); + if (result != bytes) { + printf("result = %#010lx, bytes = %#010lx\n", (uint32) result, + (uint32) bytes); + return B_ERROR; + } + } else { + if (bytes < 0) { + printf(" bytes = %#010lx\n", (uint32) bytes); + return bytes; + } else { + // EOF + break; + } + } + } + + // finish up miscellaneous stat stuff + dst.SetPermissions(src_stat.st_mode); + dst.SetOwner(src_stat.st_uid); + dst.SetGroup(src_stat.st_gid); + dst.SetModificationTime(src_stat.st_mtime); + dst.SetCreationTime(src_stat.st_crtime); + + return B_OK; +} + + +status_t CopyAttributes(BNode& dst, BNode& src) +{ + // copy attributes + src.RewindAttrs(); + char name[B_ATTR_NAME_LENGTH]; + while (src.GetNextAttrName(name) == B_OK) { + attr_info info; + if (src.GetAttrInfo(name, &info) == B_OK) { + size_t bufSize = info.size; + char* buf = new char[bufSize]; + array_delete bufDelete = buf; + + // copy one attribute + ssize_t bytes = src.ReadAttr(name, info.type, 0, buf, bufSize); + if (bytes > 0) { + dst.WriteAttr(name, info.type, 0, buf, bufSize); + } else { + return bytes; + } + } + } + + return B_OK; +} + + +status_t CopyFile(BFile& dst, BFile& src) +{ + status_t err = CopyFileData(dst, src); + if (err != B_OK) + return err; + + return CopyAttributes(dst, src); +} diff --git a/src/apps/soundrecorder/FileUtils.h b/src/apps/soundrecorder/FileUtils.h new file mode 100644 index 0000000000..30bbd8390d --- /dev/null +++ b/src/apps/soundrecorder/FileUtils.h @@ -0,0 +1,21 @@ +/******************************************************************************* +/ +/ File: FileUtils.h +/ +/ Description: Utility functions for copying file data and attributes. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#if ! defined( _FileUtils_h ) +#define _FileUtils_h + +#include + +status_t CopyFile(BFile& dest, BFile& src); +status_t CopyFileData(BFile& dst, BFile& src); +status_t CopyAttributes(BNode& dst, BNode& src); + +#endif /* _FileUtils_h */ diff --git a/src/apps/soundrecorder/Jamfile b/src/apps/soundrecorder/Jamfile new file mode 100644 index 0000000000..6b896a32e5 --- /dev/null +++ b/src/apps/soundrecorder/Jamfile @@ -0,0 +1,19 @@ +SubDir OBOS_TOP src apps soundrecorder ; + +App SoundRecorder : + DrawingTidbits.cpp + FileUtils.cpp + RecorderApp.cpp + RecorderWindow.cpp + ScopeView.cpp + SoundConsumer.cpp + SoundListView.cpp + SoundUtils.cpp + TrackSlider.cpp + TransportButton.cpp + UpDownButton.cpp + VUView.cpp + VolumeSlider.cpp + : libbe.so libmedia.so libtracker.so + : SoundRecorder.rdef +; diff --git a/src/apps/soundrecorder/RecorderApp.cpp b/src/apps/soundrecorder/RecorderApp.cpp new file mode 100644 index 0000000000..567fff2bed --- /dev/null +++ b/src/apps/soundrecorder/RecorderApp.cpp @@ -0,0 +1,37 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include "RecorderApp.h" +#include "RecorderWindow.h" + + +RecorderApp::RecorderApp(const char * signature) : + BApplication(signature), fRecorderWin(NULL) +{ +} + +RecorderApp::~RecorderApp() +{ +} + + +void +RecorderApp::ReadyToRun() +{ + BApplication::ReadyToRun(); + fRecorderWin = new RecorderWindow(); + fRecorderWin->Show(); +} + + +int +main() +{ + RecorderApp app("application/x-vnd.Haiku-SoundRecorder"); + app.Run(); + return 0; +} \ No newline at end of file diff --git a/src/apps/soundrecorder/RecorderApp.h b/src/apps/soundrecorder/RecorderApp.h new file mode 100644 index 0000000000..f0ddebba04 --- /dev/null +++ b/src/apps/soundrecorder/RecorderApp.h @@ -0,0 +1,26 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef RECORDERAPP_H +#define RECORDERAPP_H + +#include + +class RecorderWindow; + +class RecorderApp : public BApplication { +public: + RecorderApp(const char * signature); +virtual ~RecorderApp(); + +virtual void ReadyToRun(); + +private: + RecorderWindow* fRecorderWin; +}; + +#endif /* RECORDERAPP_H */ diff --git a/src/apps/soundrecorder/RecorderWindow.cpp b/src/apps/soundrecorder/RecorderWindow.cpp new file mode 100644 index 0000000000..dcbaf8e3a4 --- /dev/null +++ b/src/apps/soundrecorder/RecorderWindow.cpp @@ -0,0 +1,1233 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "RecorderWindow.h" +#include "SoundConsumer.h" +#include "SoundListView.h" +#include "array_delete.h" +#include "FileUtils.h" + +#if ! NDEBUG +#define FPRINTF(args) fprintf args +#else +#define FPRINTF(args) +#endif + +#define DEATH FPRINTF +#define CONNECT FPRINTF +#define WINDOW FPRINTF + +// default window positioning +static const float MIN_WIDTH = 400.0f; +static const float MIN_HEIGHT = 336.0f; +static const float XPOS = 100.0f; +static const float YPOS = 200.0f; + +#define FOURCC(a,b,c,d) ((((uint32)(d)) << 24) | (((uint32)(c)) << 16) | (((uint32)(b)) << 8) | ((uint32)(a))) + +struct riff_struct +{ + uint32 riff_id; // 'RIFF' + uint32 len; + uint32 wave_id; // 'WAVE' +}; + +struct chunk_struct +{ + uint32 fourcc; + uint32 len; +}; + +struct format_struct +{ + uint16 format_tag; + uint16 channels; + uint32 samples_per_sec; + uint32 avg_bytes_per_sec; + uint16 block_align; + uint16 bits_per_sample; +}; + + +struct wave_struct +{ + struct riff_struct riff; + struct chunk_struct format_chunk; + struct format_struct format; + struct chunk_struct data_chunk; +}; + + +RecorderWindow::RecorderWindow() : + BWindow(BRect(XPOS,YPOS,XPOS+MIN_WIDTH,YPOS+MIN_HEIGHT), "Sound Recorder", B_TITLED_WINDOW, + B_ASYNCHRONOUS_CONTROLS | B_NOT_V_RESIZABLE), + fPlayer(NULL), + fPlayFile(NULL), + fPlayTrack(NULL), + fSavePanel(B_SAVE_PANEL) +{ + fRoster = NULL; + fRecordButton = NULL; + fPlayButton = NULL; + fStopButton = NULL; + fSaveButton = NULL; + fLengthControl = NULL; + fInputField = NULL; + fRecordNode = 0; + fRecording = false; + fTempCount = -1; + fButtonState = btnPaused; + + CalcSizes(MIN_WIDTH, MIN_HEIGHT); + + InitWindow(); +} + +RecorderWindow::~RecorderWindow() +{ + DEATH((stderr, "RecorderWindow::~RecorderWindow()\n")); + // The sound consumer and producer are Nodes; it has to be Release()d and the Roster + // will reap it when it's done. + if (fRecordNode) { + fRecordNode->Release(); + } + if (fPlayer) { + delete fPlayer; + } + // Clean up items in list view. + if (fSoundList) { + fSoundList->DeselectAll(); + for (int ix=0; ixCountItems(); ix++) { + WINDOW((stderr, "clean up item %d\n", ix+1)); + SoundListItem * item = dynamic_cast(fSoundList->ItemAt(ix)); + if (item) { + if (item->IsTemp()) { + item->Entry().Remove(); // delete temp file + } + delete item; + } + } + fSoundList->MakeEmpty(); + } + // Clean up currently recording file, if any. + fRecEntry.Remove(); + fRecEntry.Unset(); +} + + +void +RecorderWindow::CalcSizes(float min_wid, float min_hei) +{ + // Set up size limits based on new screen size + BScreen screen; + BRect r = screen.Frame(); + float wid = r.Width()-12; + SetSizeLimits(min_wid, wid, min_hei, r.Height()-24); + + // Don't zoom to cover all of screen; user can resize last bit if necessary. + // This leaves other windows visible. + if (wid > 640) { + wid = 640 + (wid-640)/2; + } + SetZoomLimits(wid, r.Height()-24); +} + + +status_t +RecorderWindow::InitWindow() +{ + BPopUpMenu * popup = 0; + status_t error; + + try { + // Find temp directory for recorded sounds. + BPath path; + if (!(error = find_directory(B_COMMON_TEMP_DIRECTORY, &path))) { + error = fTempDir.SetTo(path.Path()); + } + if (error < 0) { + goto bad_mojo; + } + + // Make sure the media roster is there (which means the server is there). + fRoster = BMediaRoster::Roster(&error); + if (!fRoster) { + goto bad_mojo; + } + + error = fRoster->GetAudioInput(&fAudioInputNode); + if (error < B_OK) { // there's no input? + goto bad_mojo; + } + + error = fRoster->GetAudioMixer(&fAudioMixerNode); + if (error < B_OK) { // there's no mixer? + goto bad_mojo; + } + + // Create our internal Node which records sound, and register it. + fRecordNode = new SoundConsumer("Sound Recorder"); + error = fRoster->RegisterNode(fRecordNode); + if (error < B_OK) { + goto bad_mojo; + } + + // Create the window header with controls + BRect r(Bounds()); + r.bottom = r.top + 175; + BBox *background = new BBox(r, "_background", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, + B_WILL_DRAW|B_FRAME_EVENTS|B_NAVIGABLE_JUMP, B_PLAIN_BORDER); + AddChild(background); + + + + r = background->Bounds(); + r.left = 2; + r.right = r.left + 39; + r.bottom = r.top + 104; + fVUView = new VUView(r, B_FOLLOW_LEFT|B_FOLLOW_TOP); + background->AddChild(fVUView); + + r = background->Bounds(); + r.left = r.left + 40; + r.bottom = r.top + 104; + fScopeView = new ScopeView(r, B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); + background->AddChild(fScopeView); + + r = background->Bounds(); + r.left = 2; + r.right -= 26; + r.top = 115; + r.bottom = r.top + 30; + fTrackSlider = new TrackSlider(r, "trackSlider", new BMessage(POSITION_CHANGED), B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); + background->AddChild(fTrackSlider); + + BRect buttonRect; + + // Button for rewinding + buttonRect = BRect(BPoint(0,0), kSkipButtonSize); + buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-7, 25)); + fRewindButton = new TransportButton(buttonRect, "Rewind", + kSkipBackBitmapBits, kPressedSkipBackBitmapBits, kDisabledSkipBackBitmapBits, + new BMessage(REWIND)); + background->AddChild(fRewindButton); + + // Button for stopping recording or playback + buttonRect = BRect(BPoint(0,0), kStopButtonSize); + buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-48, 25)); + fStopButton = new TransportButton(buttonRect, "Stop", + kStopButtonBitmapBits, kPressedStopButtonBitmapBits, kDisabledStopButtonBitmapBits, + new BMessage(STOP)); + background->AddChild(fStopButton); + + // Button for starting playback of selected sound + BRect playRect(BPoint(0,0), kPlayButtonSize); + playRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-82, 25)); + fPlayButton = new PlayPauseButton(playRect, "Play", + new BMessage(PLAY), new BMessage(PLAY_PERIOD), ' ', 0); + background->AddChild(fPlayButton); + + // Button for forwarding + buttonRect = BRect(BPoint(0,0), kSkipButtonSize); + buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-133, 25)); + fForwardButton = new TransportButton(buttonRect, "Forward", + kSkipForwardBitmapBits, kPressedSkipForwardBitmapBits, kDisabledSkipForwardBitmapBits, + new BMessage(FORWARD)); + background->AddChild(fForwardButton); + + // Button to start recording (or waiting for sound) + buttonRect = BRect(BPoint(0,0), kRecordButtonSize); + buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-174, 25)); + fRecordButton = new RecordButton(buttonRect, "Record", + new BMessage(RECORD), new BMessage(RECORD_PERIOD)); + background->AddChild(fRecordButton); + + // Button for saving selected sound + buttonRect = BRect(BPoint(0,0), kDiskButtonSize); + buttonRect.OffsetTo(background->Bounds().LeftBottom() - BPoint(-250, 21)); + fSaveButton = new TransportButton(buttonRect, "Save", + kDiskButtonBitmapsBits, kPressedDiskButtonBitmapsBits, kDisabledDiskButtonBitmapsBits, new BMessage(SAVE)); + fSaveButton->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); + background->AddChild(fSaveButton); + + buttonRect = BRect(BPoint(0,0), kSpeakerIconBitmapSize); + buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(121, 17)); + SpeakerView *speakerView = new SpeakerView(buttonRect, B_FOLLOW_LEFT | B_FOLLOW_TOP); + speakerView->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); + background->AddChild(speakerView); + + buttonRect = BRect(BPoint(0,0), BPoint(84, 19)); + buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(107, 20)); + fVolumeSlider = new VolumeSlider(buttonRect, "volumeSlider", B_FOLLOW_LEFT | B_FOLLOW_TOP); + fVolumeSlider->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); + background->AddChild(fVolumeSlider); + + // Button to mask/see sounds list + buttonRect = BRect(BPoint(0,0), kUpDownButtonSize); + buttonRect.OffsetTo(background->Bounds().RightBottom() - BPoint(21, 25)); + fUpDownButton = new UpDownButton(buttonRect, new BMessage(VIEW_LIST)); + fUpDownButton->SetResizingMode(B_FOLLOW_RIGHT | B_FOLLOW_TOP); + background->AddChild(fUpDownButton); + + r = Bounds(); + r.top = background->Bounds().bottom + 1; + fBottomBox = new BBox(r, "bottomBox", B_FOLLOW_ALL); + fBottomBox->SetBorder(B_NO_BORDER); + AddChild(fBottomBox); + + // The actual list of recorded sounds (initially empty) sits + // below the header with the controls. + r = fBottomBox->Bounds(); + r.left += 190; + r.InsetBy(10, 10); + r.left -= 10; + r.top += 4; + r.right -= B_V_SCROLL_BAR_WIDTH; + r.bottom -= 25; + fSoundList = new SoundListView(r, "Sound List", B_FOLLOW_ALL); + fSoundList->SetSelectionMessage(new BMessage(SOUND_SELECTED)); + fSoundList->SetViewColor(216, 216, 216); + BScrollView *scroller = new BScrollView("scroller", fSoundList, B_FOLLOW_ALL, + 0, false, true, B_FANCY_BORDER); + fBottomBox->AddChild(scroller); + + r = fBottomBox->Bounds(); + r.right = r.left + 190; + r.bottom -= 25; + r.InsetBy(10, 8); + r.top -= 1; + fFileInfoBox = new BBox(r, "fileinfo", B_FOLLOW_LEFT | B_FOLLOW_BOTTOM); + fFileInfoBox->SetLabel("File Info"); + + r = fFileInfoBox->Bounds(); + r.left = 8; + r.top = 13; + r.bottom = r.top + 15; + r.right -= 10; + fFilename = new BStringView(r, "filename", "File Name:"); + fFileInfoBox->AddChild(fFilename); + r.top += 13; + r.bottom = r.top + 15; + fFormat = new BStringView(r, "format", "Format:"); + fFileInfoBox->AddChild(fFormat); + r.top += 13; + r.bottom = r.top + 15; + fCompression = new BStringView(r, "compression", "Compression:"); + fFileInfoBox->AddChild(fCompression); + r.top += 13; + r.bottom = r.top + 15; + fChannels = new BStringView(r, "channels", "Channels:"); + fFileInfoBox->AddChild(fChannels); + r.top += 13; + r.bottom = r.top + 15; + fSampleSize = new BStringView(r, "samplesize", "Sample Size:"); + fFileInfoBox->AddChild(fSampleSize); + r.top += 13; + r.bottom = r.top + 15; + fSampleRate = new BStringView(r, "samplerate", "Sample Rate:"); + fFileInfoBox->AddChild(fSampleRate); + r.top += 13; + r.bottom = r.top + 15; + fDuration = new BStringView(r, "duration", "Duration:"); + fFileInfoBox->AddChild(fDuration); + + // Input selection lists all available physical inputs that produce + // buffers with B_MEDIA_RAW_AUDIO format data. + popup = new BPopUpMenu("Input"); + int max_input_count = 64; + dormant_node_info dni[max_input_count]; + + int32 real_count = max_input_count; + media_format output_format; + output_format.type = B_MEDIA_RAW_AUDIO; + output_format.u.raw_audio = media_raw_audio_format::wildcard; + error = fRoster->GetDormantNodes(dni, &real_count, 0, &output_format, + 0, B_BUFFER_PRODUCER | B_PHYSICAL_INPUT); + if (real_count > max_input_count) { + WINDOW((stderr, "dropped %ld inputs\n", real_count - max_input_count)); + real_count = max_input_count; + } + char selected_name[B_MEDIA_NAME_LENGTH] = "Default Input"; + BMessage * msg; + BMenuItem * item; + for (int ix=0; ixAddData("node", B_RAW_TYPE, &dni[ix], sizeof(dni[ix])); + item = new BMenuItem(dni[ix].name, msg); + popup->AddItem(item); + media_node_id ni[12]; + int32 ni_count = 12; + error = fRoster->GetInstancesFor(dni[ix].addon, dni[ix].flavor_id, ni, &ni_count); + if (error == B_OK) + for (int iy=0; iyBounds()); + r = frame; + r.left = 42; + r.right = (r.left + r.right) / 2; + r.InsetBy(10,10); + r.top = r.bottom - 18; + fInputField = new BMenuField(r, "Input", "Input:", popup); + fInputField->SetDivider(50); + fBottomBox->AddChild(fInputField); + + // Text field for entering length to record (in seconds) + r.OffsetBy(r.Width()+20, 1); + r.right -= 70; + msg = new BMessage(LENGTH_CHANGED); + fLengthControl = new BTextControl(r, "Length", "Length:", "8", msg); + fLengthControl->SetDivider(60); + fLengthControl->SetAlignment(B_ALIGN_CENTER, B_ALIGN_RIGHT); + fBottomBox->AddChild(fLengthControl); + + r.left += r.Width()+5; + r.right = r.left + 65; + r.bottom -= 1; + BStringView* lenUnits = new BStringView(r, "Seconds", "seconds"); + fBottomBox->AddChild(lenUnits); + + fBottomBox->AddChild(fFileInfoBox); + + fBottomBox->Hide(); + CalcSizes(Frame().Width(), MIN_HEIGHT-161); + ResizeTo(Frame().Width(), MIN_HEIGHT-161); + + + popup->Superitem()->SetLabel(selected_name); + + // Make sure the save panel is happy. + fSavePanel.SetTarget(this); + } + catch (...) { + goto bad_mojo; + } + UpdateButtons(); + return B_OK; + + // Error handling. +bad_mojo: + if (error >= 0) { + error = B_ERROR; + } + if (fRecordNode) { + fRecordNode->Release(); + } + + delete fPlayer; + if (!fInputField) { + delete popup; + } + return error; +} + + +bool +RecorderWindow::QuitRequested() // this means Close pressed +{ + StopRecording(); + StopPlaying(); + be_app->PostMessage(B_QUIT_REQUESTED); + return true; +} + + +void +RecorderWindow::MessageReceived(BMessage * message) +{ + // Your average generic message dispatching switch() statement. + switch (message->what) { + case INPUT_SELECTED: + Input(message); + break; + case LENGTH_CHANGED: + Length(message); + break; + case SOUND_SELECTED: + Selected(message); + break; + case STOP_PLAYING: + StopPlaying(); + break; + case STOP_RECORDING: + StopRecording(); + break; + case PLAY_PERIOD: + if (fPlayer) { + if (fPlayer->HasData()) + fPlayButton->SetPlaying(); + else + fPlayButton->SetPaused(); + } + break; + case RECORD_PERIOD: + fRecordButton->SetRecording(); + break; + case RECORD: + Record(message); + break; + case STOP: + Stop(message); + break; + case PLAY: + Play(message); + break; + case SAVE: + Save(message); + break; + case B_SAVE_REQUESTED: + DoSave(message); + break; + case VIEW_LIST: + if (fUpDownButton->Value() == B_CONTROL_ON) { + fBottomBox->Show(); + CalcSizes(Frame().Width(), MIN_HEIGHT); + ResizeTo(Frame().Width(), MIN_HEIGHT); + } else { + fBottomBox->Hide(); + CalcSizes(Frame().Width(), MIN_HEIGHT-161); + ResizeTo(Frame().Width(), MIN_HEIGHT-161); + + } + break; + case UPDATE_TRACKSLIDER: + { + bigtime_t timestamp = fPlayTrack->CurrentTime(); + fTrackSlider->SetMainTime(timestamp, false); + fScopeView->SetMainTime(timestamp); + } + break; + case POSITION_CHANGED: + { + bigtime_t right, left, main; + if (message->FindInt64("main", &main) == B_OK) { + if (fPlayTrack) { + fPlayTrack->SeekToTime(fTrackSlider->MainTime()); + fPlayFrame = fPlayTrack->CurrentFrame(); + } + fScopeView->SetMainTime(main); + } + if (message->FindInt64("right", &right) == B_OK) { + if (fPlayTrack) + fPlayLimit = MIN(fPlayTrack->CountFrames(), (off_t)(right * fPlayFormat.u.raw_audio.frame_rate/1000000LL)); + fScopeView->SetRightTime(right); + } + if (message->FindInt64("left", &left) == B_OK) { + fScopeView->SetLeftTime(left); + } + } + break; + case B_SIMPLE_DATA: + case B_REFS_RECEIVED: + { + RefsReceived(message); + break; + } + default: + BWindow::MessageReceived(message); + break; + } +} + + +void +RecorderWindow::Record(BMessage * message) +{ + // User pressed Record button + fRecording = true; + int seconds = atoi(fLengthControl->Text()); + if (seconds < 1) { + ErrorAlert("record a sound that's shorter than a second", B_ERROR); + return; + } + + if (fButtonState != btnPaused) { + StopRecording(); + return; // user is too fast on the mouse + } + SetButtonState(btnRecording); + fRecordButton->SetRecording(); + + char name[256]; + // Create a file with a temporary name + status_t err = NewTempName(name); + if (err < B_OK) { + ErrorAlert("find an unused name to use for the new recording", err); + return; + } + // Find the file so we can refer to it later + err = fTempDir.FindEntry(name, &fRecEntry); + if (err < B_OK) { + ErrorAlert("find the temporary file created to hold the new recording", err); + return; + } + err = fRecFile.SetTo(&fTempDir, name, O_RDWR); + if (err < B_OK) { + ErrorAlert("open the temporary file created to hold the new recording", err); + fRecEntry.Unset(); + return; + } + // Reserve space on disk (creates fewer fragments) + err = fRecFile.SetSize(seconds*4*48000LL); + if (err < B_OK) { + ErrorAlert("record a sound that long", err); + fRecEntry.Remove(); + fRecEntry.Unset(); + return; + } + fRecLimit = seconds*4*48000LL; + fRecSize = 0; + + fRecFile.Seek(sizeof(struct wave_struct), SEEK_SET); + + // Hook up input + err = MakeRecordConnection(fAudioInputNode); + if (err < B_OK) { + ErrorAlert("connect to the selected sound input", err); + fRecEntry.Remove(); + fRecEntry.Unset(); + return; + } + + // And get it going... + bigtime_t then = fRecordNode->TimeSource()->Now()+50000LL; + fRoster->StartNode(fRecordNode->Node(), then); + if (fAudioInputNode.kind & B_TIME_SOURCE) { + fRoster->StartNode(fAudioInputNode, fRecordNode->TimeSource()->RealTimeFor(then, 0)); + } + else { + fRoster->StartNode(fAudioInputNode, then); + } +} + +void +RecorderWindow::Play(BMessage * message) +{ + if (fPlayer) { + // User pressed Play button and playing + if (fPlayer->HasData()) + fPlayButton->SetPaused(); + else + fPlayButton->SetPlaying(); + fPlayer->SetHasData(!fPlayer->HasData()); + return; + } + + SetButtonState(btnPlaying); + fPlayButton->SetPlaying(); + + if (!fPlayTrack) { + ErrorAlert("get the file to play", B_ERROR); + return; + } + + fPlayLimit = MIN(fPlayTrack->CountFrames(), (off_t)(fTrackSlider->RightTime()*fPlayFormat.u.raw_audio.frame_rate/1000000LL)); + fPlayTrack->SeekToTime(fTrackSlider->MainTime()); + fPlayFrame = fPlayTrack->CurrentFrame(); + + // Create our internal Node which plays sound, and register it. + fPlayer = new BSoundPlayer(fAudioMixerNode, &fPlayFormat.u.raw_audio, "Sound Player"); + status_t err = fPlayer->InitCheck(); + if (err < B_OK) { + return; + } + + fVolumeSlider->SetSoundPlayer(fPlayer); + fPlayer->SetCallbacks(PlayFile, NotifyPlayFile, this); + + // And get it going... + fPlayer->Start(); + fPlayer->SetHasData(true); +} + +void +RecorderWindow::Stop(BMessage * message) +{ + // User pressed Stop button. + // Stop recorder. + StopRecording(); + // Stop player. + StopPlaying(); +} + +void +RecorderWindow::Save(BMessage * message) +{ + // User pressed Save button. + // Find the item to save. + int32 index = fSoundList->CurrentSelection(); + SoundListItem* pItem = dynamic_cast(fSoundList->ItemAt(index)); + if ((! pItem) || (pItem->Entry().InitCheck() != B_OK)) { + return; + } + + // Update the save panel and show it. + char filename[B_FILE_NAME_LENGTH]; + pItem->Entry().GetName(filename); + BMessage saveMsg(B_SAVE_REQUESTED); + entry_ref ref; + pItem->Entry().GetRef(&ref); + + saveMsg.AddPointer("sound list item", pItem); + fSavePanel.SetSaveText(filename); + fSavePanel.SetMessage(&saveMsg); + fSavePanel.Show(); +} + +void +RecorderWindow::DoSave(BMessage * message) +{ + // User picked a place to put the file. + // Find the location of the old (e.g. + // temporary file), and the name of the + // new file to save. + entry_ref old_ref, new_dir_ref; + const char* new_name; + SoundListItem* pItem; + + if ((message->FindPointer("sound list item", (void**) &pItem) == B_OK) + && (message->FindRef("directory", &new_dir_ref) == B_OK) + && (message->FindString("name", &new_name) == B_OK)) + { + BEntry& oldEntry = pItem->Entry(); + BFile oldFile(&oldEntry, B_READ_WRITE); + if (oldFile.InitCheck() != B_OK) + return; + + BDirectory newDir(&new_dir_ref); + if (newDir.InitCheck() != B_OK) + return; + + BFile newFile; + newDir.CreateFile(new_name, &newFile); + + if (newFile.InitCheck() != B_OK) + return; + + status_t err = CopyFile(newFile, oldFile); + + if (err == B_OK) { + // clean up the sound list and item + if (pItem->IsTemp()) + oldEntry.Remove(); // blows away temp file! + oldEntry.SetTo(&newDir, new_name); + pItem->SetTemp(false); // don't blow the new entry away when we exit! + fSoundList->Invalidate(); + } + } else { + WINDOW((stderr, "Couldn't save file.\n")); + } +} + + +void +RecorderWindow::Length(BMessage * message) +{ + // User changed the Length field -- validate + const char * ptr = fLengthControl->Text(); + const char * start = ptr; + const char * anchor = ptr; + const char * end = fLengthControl->Text() + fLengthControl->TextView()->TextLength(); + while (ptr < end) { + // Remember the last start-of-character for UTF-8 compatibility + // needed in call to Select() below (which takes bytes). + if (*ptr & 0x80) { + if (*ptr & 0xc0 == 0xc0) { + anchor = ptr; + } + } + else { + anchor = ptr; + } + if (!isdigit(*ptr)) { + fLengthControl->TextView()->MakeFocus(true); + fLengthControl->TextView()->Select(anchor-start, fLengthControl->TextView()->TextLength()); + beep(); + break; + } + ptr++; + } +} + + +void +RecorderWindow::Input(BMessage * message) +{ + // User selected input from pop-up + const dormant_node_info * dni = 0; + ssize_t size = 0; + if (message->FindData("node", B_RAW_TYPE, (const void **)&dni, &size)) { + return; // bad input selection message + } + + media_node_id node_id; + status_t error = fRoster->GetInstancesFor(dni->addon, dni->flavor_id, &node_id); + if (error != B_OK) { + fRoster->InstantiateDormantNode(*dni, &fAudioInputNode); + } else { + fRoster->GetNodeFor(node_id, &fAudioInputNode); + } +} + +void +RecorderWindow::Selected(BMessage * message) +{ + // User selected a sound in list view + UpdatePlayFile(); + UpdateButtons(); +} + +status_t +RecorderWindow::MakeRecordConnection(const media_node & input) +{ + CONNECT((stderr, "RecorderWindow::MakeRecordConnection()\n")); + + // Find an available output for the given input node. + int32 count = 0; + status_t err = fRoster->GetFreeOutputsFor(input, &fAudioOutput, 1, &count, B_MEDIA_RAW_AUDIO); + if (err < B_OK) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free outputs from audio input node\n")); + return err; + } + if (count < 1) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free outputs from audio input node\n")); + return B_BUSY; + } + + // Find an available input for our own Node. Note that we go through the + // MediaRoster; calling Media Kit methods directly on Nodes in our app is + // not OK (because synchronization happens in the service thread, not in + // the calling thread). + // TODO: explain this + err = fRoster->GetFreeInputsFor(fRecordNode->Node(), &fRecInput, 1, &count, B_MEDIA_RAW_AUDIO); + if (err < B_OK) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't get free inputs for sound recorder\n")); + return err; + } + if (count < 1) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): no free inputs for sound recorder\n")); + return B_BUSY; + } + + // Find out what the time source of the input is. + // For most nodes, we just use the preferred time source (the DAC) for synchronization. + // However, nodes that record from an input need to synchronize to the audio input node + // instead for best results. + // MakeTimeSourceFor gives us a "clone" of the time source node that we can manipulate + // to our heart's content. When we're done with it, though, we need to call Release() + // on the time source node, so that it keeps an accurate reference count and can delete + // itself when it's no longer needed. + // TODO: what about filters connected to audio input? + media_node use_time_source; + BTimeSource * tsobj = fRoster->MakeTimeSourceFor(input); + if (! tsobj) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't clone time source from audio input node\n")); + return B_MEDIA_BAD_NODE; + } + + // Apply the time source in effect to our own Node. + err = fRoster->SetTimeSourceFor(fRecordNode->Node().node, tsobj->Node().node); + if (err < B_OK) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's time source\n")); + tsobj->Release(); + return err; + } + + // Get a format, any format. + media_format fmt; + fmt.u.raw_audio = fAudioOutput.format.u.raw_audio; + fmt.type = B_MEDIA_RAW_AUDIO; + + // Tell the consumer where we want data to go. + err = fRecordNode->SetHooks(RecordFile, NotifyRecordFile, this); + if (err < B_OK) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): couldn't set the sound recorder's hook functions\n")); + tsobj->Release(); + return err; + } + + // Using the same structs for input and output is OK in BMediaRoster::Connect(). + err = fRoster->Connect(fAudioOutput.source, fRecInput.destination, &fmt, &fAudioOutput, &fRecInput); + if (err < B_OK) { + CONNECT((stderr, "RecorderWindow::MakeRecordConnection(): failed to connect sound recorder to audio input node.\n")); + tsobj->Release(); + fRecordNode->SetHooks(0, 0, 0); + return err; + } + + // Start the time source if it's not running. + if ((tsobj->Node() != input) && !tsobj->IsRunning()) { + fRoster->StartNode(tsobj->Node(), BTimeSource::RealTime()); + } + tsobj->Release(); // we're done with this time source instance! + return B_OK; +} + + +status_t +RecorderWindow::BreakRecordConnection() +{ + status_t err; + + // If we are the last connection, the Node will stop automatically since it + // has nowhere to send data to. + err = fRoster->StopNode(fRecInput.node, 0); + err = fRoster->Disconnect(fAudioOutput.node.node, fAudioOutput.source, fRecInput.node.node, fRecInput.destination); + fAudioOutput.source = media_source::null; + fRecInput.destination = media_destination::null; + return err; +} + +status_t +RecorderWindow::StopRecording() +{ + if (!fRecording) + return B_OK; + fRecording = false; + BreakRecordConnection(); + fRecordNode->SetHooks(NULL,NULL,NULL); + if (fRecSize > 0) { + + wave_struct header; + header.riff.riff_id = FOURCC('R','I','F','F'); + header.riff.len = fRecSize + 36; + header.riff.wave_id = FOURCC('W','A','V','E'); + header.format_chunk.fourcc = FOURCC('f','m','t',' '); + header.format_chunk.len = sizeof(header.format); + header.format.format_tag = 1; + header.format.channels = 2; + header.format.samples_per_sec = 48000; + header.format.avg_bytes_per_sec = 48000 * 4; + header.format.block_align = 4; + header.format.bits_per_sample = 16; + header.data_chunk.fourcc = FOURCC('d','a','t','a'); + header.data_chunk.len = fRecSize; + fRecFile.Seek(0, SEEK_SET); + fRecFile.Write(&header, sizeof(header)); + + fRecFile.SetSize(fRecSize + sizeof(header)); // We reserve space; make sure we cut off any excess at the end. + AddSoundItem(fRecEntry, true); + } + else { + fRecEntry.Remove(); + } + // We're done for this time. + fRecEntry.Unset(); + // Close the file. + fRecFile.Unset(); + // No more recording going on. + fRecLimit = 0; + fRecSize = 0; + SetButtonState(btnPaused); + fRecordButton->SetStopped(); + + return B_OK; +} + + +status_t +RecorderWindow::StopPlaying() +{ + if (fPlayer) { + fPlayer->Stop(); + fPlayer->SetCallbacks(0, 0, 0); + fVolumeSlider->SetSoundPlayer(NULL); + delete fPlayer; + fPlayer = NULL; + } + SetButtonState(btnPaused); + fPlayButton->SetStopped(); + fTrackSlider->ResetMainTime(); + fScopeView->SetMainTime(*fTrackSlider->MainTime()); + return B_OK; +} + + +void +RecorderWindow::SetButtonState(BtnState state) +{ + fButtonState = state; + UpdateButtons(); +} + + +void +RecorderWindow::UpdateButtons() +{ + bool hasSelection = (fSoundList->CurrentSelection() >= 0); + fRecordButton->SetEnabled(fButtonState != btnPlaying); + fPlayButton->SetEnabled((fButtonState != btnRecording) && hasSelection); + fRewindButton->SetEnabled((fButtonState != btnRecording) && hasSelection); + fForwardButton->SetEnabled((fButtonState != btnRecording) && hasSelection); + fStopButton->SetEnabled(fButtonState != btnPaused); + fSaveButton->SetEnabled(hasSelection && (fButtonState != btnRecording)); + fLengthControl->SetEnabled(fButtonState != btnRecording); + fInputField->SetEnabled(fButtonState != btnRecording); +} + + +void +RecorderWindow::UpdatePlayFile() +{ + // Get selection. + int32 selIdx = fSoundList->CurrentSelection(); + SoundListItem* pItem = dynamic_cast(fSoundList->ItemAt(selIdx)); + if (! pItem) { + return; + } + + status_t err; + BEntry& entry = pItem->Entry(); + entry_ref ref; + entry.GetRef(&ref); + fPlayFile = new BMediaFile(&ref); //, B_MEDIA_FILE_UNBUFFERED); + if ((err = fPlayFile->InitCheck()) < B_OK) { + ErrorAlert("get the file to play", err); + delete fPlayFile; + return; + } + + ASSERT(fPlayTrack == NULL); + + for (int ix=0; ixCountTracks(); ix++) { + BMediaTrack * track = fPlayFile->TrackAt(ix); + fPlayFormat.type = B_MEDIA_RAW_AUDIO; + if ((track->DecodedFormat(&fPlayFormat) == B_OK) && (fPlayFormat.type == B_MEDIA_RAW_AUDIO)) { + fPlayTrack = track; + break; + } + if (track) + fPlayFile->ReleaseTrack(track); + } + + if (!fPlayTrack) { + ErrorAlert("get the file to play", err); + delete fPlayFile; + return; + } + + BString filename = "File Name: "; + filename << ref.name; + fFilename->SetText(filename.String()); + + BString format = "Format: "; + media_file_format file_format; + if (fPlayFile->GetFileFormatInfo(&file_format) == B_OK) + format << file_format.short_name; + BString compression = "Compression: "; + media_codec_info codec_info; + if (fPlayTrack->GetCodecInfo(&codec_info) == B_OK) { + if (strcmp(codec_info.short_name, "raw")==0) + compression << "None"; + else + compression << codec_info.short_name; + } + BString channels = "Channels: "; + channels << fPlayFormat.u.raw_audio.channel_count; + BString samplesize = "Sample Size: "; + samplesize << 8 * (fPlayFormat.u.raw_audio.format & 0xf) << " bits"; + BString samplerate = "Sample Rate: "; + samplerate << (int)fPlayFormat.u.raw_audio.frame_rate; + BString durationString = "Duration: "; + bigtime_t duration = fPlayTrack->Duration(); + durationString << (float)(duration / 1000000.0) << " seconds"; + + fFormat->SetText(format.String()); + fCompression->SetText(compression.String()); + fChannels->SetText(channels.String()); + fSampleSize->SetText(samplesize.String()); + fSampleRate->SetText(samplerate.String()); + fDuration->SetText(durationString.String()); + + fTrackSlider->SetTotalTime(duration, true); + fScopeView->SetMainTime(fTrackSlider->LeftTime()); + fScopeView->SetTotalTime(duration); + fScopeView->SetRightTime(fTrackSlider->RightTime()); + fScopeView->SetLeftTime(fTrackSlider->LeftTime()); + fScopeView->RenderTrack(fPlayTrack, fPlayFormat); +} + + +void +RecorderWindow::ErrorAlert(const char * action, status_t err) +{ + char msg[300]; + sprintf(msg, "Cannot %s: %s.\n[%lx]", action, strerror(err), (int32) err); + (new BAlert("", msg, "Stop"))->Go(); +} + + +status_t +RecorderWindow::NewTempName(char * name) +{ + int init_count = fTempCount; +again: + if (fTempCount-init_count > 25) { + return B_ERROR; + } + else { + fTempCount++; + if (fTempCount==0) + sprintf(name, "Audio Clip"); + else + sprintf(name, "Audio Clip %d", fTempCount); + BPath path; + status_t err; + BEntry tempEnt; + if ((err = fTempDir.GetEntry(&tempEnt)) < B_OK) { + return err; + } + if ((err = tempEnt.GetPath(&path)) < B_OK) { + return err; + } + path.Append(name); + int fd; + // Use O_EXCL so we know we created the file (sync with other instances) + if ((fd = open(path.Path(), O_RDWR | O_CREAT | O_EXCL, 0666)) < 0) { + goto again; + } + close(fd); + } + return B_OK; +} + + +void +RecorderWindow::AddSoundItem(const BEntry& entry, bool temp) +{ + // Create list item to display. + SoundListItem * listItem = new SoundListItem(entry, temp); + fSoundList->AddItem(listItem); + fSoundList->Invalidate(); + fSoundList->Select(fSoundList->IndexOf(listItem)); +} + +void +RecorderWindow::RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t size, const media_raw_audio_format & format) +{ + // Callback called from the SoundConsumer when receiving buffers. + assert((format.format & 0x02) && format.channel_count); + RecorderWindow * window = (RecorderWindow *)cookie; + + if (window->fRecording) { + // Write the data to file (we don't buffer or guard file access + // or anything) + if (window->fRecSize < window->fRecLimit) { + window->fRecFile.WriteAt(window->fRecSize, data, size); + window->fVUView->ComputeNextLevel(data, size); + window->fRecSize += size; + } else { + // We're done! + window->PostMessage(STOP_RECORDING); + } + } +} + + +void +RecorderWindow::NotifyRecordFile(void * cookie, int32 code, ...) +{ + if ((code == B_WILL_STOP) || (code == B_NODE_DIES)) { + RecorderWindow * window = (RecorderWindow *)cookie; + // Tell the window we've stopped, if it doesn't + // already know. + window->PostMessage(STOP_RECORDING); + } +} + + +void +RecorderWindow::PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format) +{ + // Callback called from the SoundProducer when producing buffers. + RecorderWindow * window = (RecorderWindow *)cookie; + int32 frame_size = (window->fPlayFormat.u.raw_audio.format & 0xf) * + window->fPlayFormat.u.raw_audio.channel_count; + + if (window->fPlayFrame < window->fPlayLimit) { + int64 frames = 0; + window->fPlayTrack->ReadFrames(data, &frames); + window->fVUView->ComputeNextLevel(data, size/frame_size); + window->fPlayFrame += size/frame_size; + window->PostMessage(UPDATE_TRACKSLIDER); + } else { + // we're done! + window->PostMessage(STOP_PLAYING); + } +} + +void +RecorderWindow::NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...) +{ + if ((code == BSoundPlayer::B_STOPPED) || (code == BSoundPlayer::B_SOUND_DONE)) { + RecorderWindow * window = (RecorderWindow *)cookie; + // tell the window we've stopped, if it doesn't + // already know. + window->PostMessage(STOP_PLAYING); + } +} + + +void +RecorderWindow::RefsReceived(BMessage *msg) +{ + entry_ref ref; + int32 i = 0; + + while (msg->FindRef("refs", i++, &ref) == B_OK) { + + BEntry entry(&ref, true); + BPath path(&entry); + BNode node(&entry); + + if (node.IsFile()) { + AddSoundItem(entry, false); + } else if(node.IsDirectory()) { + + } + } +} \ No newline at end of file diff --git a/src/apps/soundrecorder/RecorderWindow.h b/src/apps/soundrecorder/RecorderWindow.h new file mode 100644 index 0000000000..8e06528b47 --- /dev/null +++ b/src/apps/soundrecorder/RecorderWindow.h @@ -0,0 +1,164 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef RECORDERWINDOW_H +#define RECORDERWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ScopeView.h" +#include "TransportButton.h" +#include "TrackSlider.h" +#include "UpDownButton.h" +#include "VolumeSlider.h" +#include "VUView.h" + +class BMediaRoster; +class BBox; +class BButton; +class BCheckBox; +class BTextControl; +class BMenuField; +class SoundConsumer; +class SoundListView; +class BScrollView; +class BSlider; +class BStringView; + +class RecorderWindow : public BWindow { +public: + RecorderWindow(); +virtual ~RecorderWindow(); + + +virtual bool QuitRequested(); +virtual void MessageReceived(BMessage * message); + + enum { + RECORD = 'cw00', // command messages + PLAY, + STOP, + REWIND, + FORWARD, + SAVE, + VIEW_LIST, + INPUT_SELECTED = 'cW00', // control messages + LENGTH_CHANGED, + SOUND_SELECTED, + STOP_PLAYING, + STOP_RECORDING, + RECORD_PERIOD, + PLAY_PERIOD, + UPDATE_TRACKSLIDER, + POSITION_CHANGED + }; + + void AddSoundItem(const BEntry& entry, bool temp = false); + +private: + BMediaRoster * fRoster; + VUView *fVUView; + ScopeView *fScopeView; + RecordButton * fRecordButton; + PlayPauseButton * fPlayButton; + TransportButton * fStopButton; + TransportButton * fRewindButton; + TransportButton * fForwardButton; + TransportButton * fSaveButton; + VolumeSlider *fVolumeSlider; + TrackSlider *fTrackSlider; + UpDownButton * fUpDownButton; + BTextControl * fLengthControl; + BMenuField * fInputField; + SoundConsumer * fRecordNode; + BSoundPlayer * fPlayer; + bool fRecording; + SoundListView * fSoundList; + BDirectory fTempDir; + int fTempCount; + + BBox * fBottomBox; + BBox * fFileInfoBox; + BStringView *fFilename; + BStringView *fFormat; + BStringView *fCompression; + BStringView *fChannels; + BStringView *fSampleSize; + BStringView *fSampleRate; + BStringView *fDuration; + + enum BtnState { + btnPaused, + btnRecording, + btnPlaying + }; + BtnState fButtonState; + BEntry fRecEntry; + + BFile fRecFile; + off_t fRecLimit; + off_t fRecSize; + + media_node fAudioInputNode; + media_output fAudioOutput; + media_input fRecInput; + + BMediaFile *fPlayFile; + media_format fPlayFormat; + BMediaTrack *fPlayTrack; + int64 fPlayLimit; + int64 fPlayFrame; + + media_node fAudioMixerNode; + + BFilePanel fSavePanel; + + status_t InitWindow(); + + void Record(BMessage * message); + void Play(BMessage * message); + void Stop(BMessage * message); + void Save(BMessage * message); + void DoSave(BMessage * message); + void Input(BMessage * message); + void Length(BMessage * message); + void Selected(BMessage * message); + + status_t MakeRecordConnection(const media_node & input); + status_t BreakRecordConnection(); + status_t StopRecording(); + + status_t MakePlayConnection(const media_multi_audio_format & format); + status_t BreakPlayConnection(); + status_t StopPlaying(); + + status_t NewTempName(char * buffer); + void CalcSizes(float min_width, float min_height); + void SetButtonState(BtnState state); + void UpdateButtons(); + void UpdatePlayFile(); + void ErrorAlert(const char * action, status_t err); + +static void RecordFile(void * cookie, bigtime_t timestamp, void * data, size_t size, const media_raw_audio_format & format); +static void NotifyRecordFile(void * cookie, int32 code, ...); + +static void PlayFile(void * cookie, void * data, size_t size, const media_raw_audio_format & format); +static void NotifyPlayFile(void * cookie, BSoundPlayer::sound_player_notification code, ...); + + void RefsReceived(BMessage *msg); +}; + +#endif /* RECORDERWINDOW_H */ + diff --git a/src/apps/soundrecorder/ScopeView.cpp b/src/apps/soundrecorder/ScopeView.cpp new file mode 100644 index 0000000000..a68fdac038 --- /dev/null +++ b/src/apps/soundrecorder/ScopeView.cpp @@ -0,0 +1,271 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include +#include +#include +#include +#include "DrawingTidbits.h" +#include "ScopeView.h" + + +ScopeView::ScopeView(BRect rect, uint32 resizeFlags) + : BView(rect, "vumeter", resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS), + fThreadId(-1), + fBitmap(NULL), + fIsRendering(false), + fMediaTrack(NULL), + fQuitting(false), + fMainTime(0), + fRightTime(1000000), + fLeftTime(0), + fTotalTime(1000000) +{ + fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true); + memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); + + rect.OffsetToSelf(B_ORIGIN); + rect.right -= 2; + fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); + fBitmap->AddChild(fBitmapView); + + fRenderSem = create_sem(0, "scope rendering"); + fHeight = Bounds().Height(); +} + + +ScopeView::~ScopeView() +{ + delete_sem(fRenderSem); +} + + +void +ScopeView::AttachedToWindow() +{ + SetViewColor(B_TRANSPARENT_COLOR); + Run(); +} + + +void +ScopeView::DetachedFromWindow() +{ + Quit(); +} + + +void +ScopeView::Draw(BRect updateRect) +{ + BRect bounds = Bounds(); + if (!fIsRendering) + DrawBitmapAsync(fBitmap, BPoint(2,0)); + + float x = 2; + if (fTotalTime !=0) + x = 2 + (fMainTime - fLeftTime) * (bounds.right - 2) / (fRightTime - fLeftTime); + SetHighColor(60,255,40); + StrokeLine(BPoint(x, bounds.top), BPoint(x, bounds.bottom)); + + Sync(); +} + + +void +ScopeView::Run() +{ + fThreadId = spawn_thread(&RenderLaunch, "Scope view", B_NORMAL_PRIORITY, this); + if (fThreadId < 0) + return; + resume_thread(fThreadId); +} + +void +ScopeView::Quit() +{ + delete_sem(fRenderSem); + fQuitting = true; + snooze(10000); + kill_thread(fThreadId); +} + + + +int32 +ScopeView::RenderLaunch(void *data) +{ + ScopeView *scope = (ScopeView*) data; + scope->RenderLoop(); + return B_OK; +} + + +void +ScopeView::RenderLoop() +{ + + while (!fQuitting) { + + if (acquire_sem(fRenderSem)!=B_OK) + continue; + + fIsRendering = true; + + int32 frame_size = (fPlayFormat.u.raw_audio.format & 0xf) * fPlayFormat.u.raw_audio.channel_count; + int64 totalFrames = fMediaTrack->CountFrames(); + int16 samples[fPlayFormat.u.raw_audio.buffer_size / (fPlayFormat.u.raw_audio.format & 0xf)]; + int64 frames = 0; + int64 sum = 0; + int64 framesIndex = 0; + int32 sumCount = 0; + fMediaTrack->SeekToFrame(&frames); + + printf("begin computing\n"); + + int32 previewIndex = 0; + + while (fMediaTrack->ReadFrames(samples, &frames) == B_OK) { + //printf("reading block\n"); + framesIndex = 0; + + while (framesIndex < frames) { + + for (; framesIndex < frames && sumCount < totalFrames/20000; framesIndex++, sumCount++) { + sum += samples[2*framesIndex]; + sum += samples[2*framesIndex+1]; + } + + if (previewIndex >= 20000) { + break; + } + + if (sumCount >= totalFrames/20000) { + //printf("computing block %ld, sumCount %ld\n", previewIndex, sumCount); + fPreview[previewIndex++] = (int32)(sum / 2 /(totalFrames/20000) / 32767.0 * fHeight / 2 + fHeight / 2); + sumCount = 0; + sum = 0; + } + } + + + } + + printf("finished computing\n"); + + /* rendering */ + RenderBitmap(); + + /* ask drawing */ + + fIsRendering = false; + + if (Window()->LockWithTimeout(5000) == B_OK) { + Invalidate(); + Window()->Unlock(); + } + } +} + + +void +ScopeView::SetMainTime(bigtime_t timestamp) +{ + fMainTime = timestamp; + Invalidate(); +} + + +void +ScopeView::SetTotalTime(bigtime_t timestamp) +{ + fTotalTime = timestamp; + Invalidate(); +} + +void +ScopeView::SetLeftTime(bigtime_t timestamp) +{ + fLeftTime = timestamp; + RenderBitmap(); + Invalidate(); +} + +void +ScopeView::SetRightTime(bigtime_t timestamp) +{ + fRightTime = timestamp; + RenderBitmap(); + Invalidate(); +} + + +void +ScopeView::RenderTrack(BMediaTrack *track, media_format format) +{ + fMediaTrack = track; + fPlayFormat = format; + release_sem(fRenderSem); +} + + +void +ScopeView::FrameResized(float width, float height) +{ + InitBitmap(); + RenderBitmap(); + Invalidate(); +} + + +void +ScopeView::InitBitmap() +{ + if (fBitmapView) { + fBitmap->RemoveChild(fBitmapView); + delete fBitmapView; + } + if (fBitmap) + delete fBitmap; + + BRect rect = Bounds(); + + fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true); + memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); + + rect.OffsetToSelf(B_ORIGIN); + rect.right -= 2; + fBitmapView = new BView(rect.OffsetToSelf(B_ORIGIN), "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); + fBitmap->AddChild(fBitmapView); +} + + +void +ScopeView::RenderBitmap() +{ + if (!fMediaTrack) + return; + + /* rendering */ + fBitmap->Lock(); + memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); + float width = fBitmapView->Bounds().Width(); + + fBitmapView->SetDrawingMode(B_OP_ADD); + fBitmapView->SetHighColor(15,60,15); + int32 leftIndex = (fTotalTime != 0) ? fLeftTime * 20000 / fTotalTime : 0; + int32 rightIndex = (fTotalTime != 0) ? fRightTime * 20000 / fTotalTime : 20000; + + for (int32 i = leftIndex; iStrokeLine(point, point); + } + + fBitmap->Unlock(); +} + diff --git a/src/apps/soundrecorder/ScopeView.h b/src/apps/soundrecorder/ScopeView.h new file mode 100644 index 0000000000..29e39d487c --- /dev/null +++ b/src/apps/soundrecorder/ScopeView.h @@ -0,0 +1,55 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef SCOPEVIEW_H +#define SCOPEVIEW_H + +#include +#include +#include + + +class ScopeView : public BView +{ +public: + ScopeView(BRect rect, uint32 resizeFlags); + ~ScopeView(); + void AttachedToWindow(); + void DetachedFromWindow(); + void Draw(BRect updateRect); + void SetMainTime(bigtime_t timestamp); + void SetLeftTime(bigtime_t timestamp); + void SetRightTime(bigtime_t timestamp); + void SetTotalTime(bigtime_t timestamp); + void RenderTrack(BMediaTrack *track, media_format format); + virtual void FrameResized(float width, float height); +private: + void Run(); + void Quit(); + static int32 RenderLaunch(void *data); + void RenderLoop(); + void RenderBitmap(); + void InitBitmap(); + + thread_id fThreadId; + BBitmap *fBitmap; + BView *fBitmapView; + sem_id fRenderSem; + bool fIsRendering; + BMediaTrack *fMediaTrack; + media_format fPlayFormat; + + bool fQuitting; + bigtime_t fMainTime; + bigtime_t fRightTime; + bigtime_t fLeftTime; + bigtime_t fTotalTime; + int32 fPreview[20000]; + float fHeight; +}; + +#endif /* SCOPEVIEW_H */ diff --git a/src/apps/soundrecorder/SoundConsumer.cpp b/src/apps/soundrecorder/SoundConsumer.cpp new file mode 100644 index 0000000000..d7e259854b --- /dev/null +++ b/src/apps/soundrecorder/SoundConsumer.cpp @@ -0,0 +1,706 @@ +/******************************************************************************* +/ +/ File: SoundConsumer.cpp +/ +/ Description: Record sound from some sound-producing Node. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "SoundPrivate.h" +#include "SoundConsumer.h" +#include "array_delete.h" + + +// If we don't mind the format changing to another format while +// running, we can define this to 1. Look for the symbol down in the source. +#define ACCEPT_ANY_FORMAT_CHANGE 0 + + +// Compiling with NDEBUG means "release" -- it also turns off assert() and +// other such debugging aids. By contrast, DEBUG turns on extra debugging +// in some programs. +#if !NDEBUG +#define FPRINTF fprintf +#else +#define FPRINTF (void) +#endif + +// Comment out the FPRINTF part of these lines to reduce verbiage. +// Enabling MESSAGE will kill performance on slower machines, because it +// prints for each message received (including each buffer). +#define NODE //FPRINTF +#define MESSAGE //FPRINTF + + +SoundConsumer::SoundConsumer( + const char * name, + SoundProcessFunc recordFunc, + SoundNotifyFunc notifyFunc, + void * cookie) : + BMediaNode(name ? name : "SoundConsumer"), + BBufferConsumer(B_MEDIA_RAW_AUDIO) +{ + NODE(stderr, "SoundConsumer::SoundConsumer(%p, %p, %p, %p)\n", + name, recordFunc, notifyFunc, cookie); + + if (!name) name = "SoundConsumer"; + + // Set up the hook functions. + m_recordHook = recordFunc; + m_notifyHook = notifyFunc; + m_cookie = cookie; + + // Create the port that we publish as our Control Port. + char pname[32]; + sprintf(pname, "%.20s Control", name); + m_port = create_port(10, pname); + + // Initialize our single media_input. Make sure it knows + // the Control Port associated with the destination, and + // the index of the destination (since we only have one, + // that's trivial). + m_input.destination.port = m_port; + m_input.destination.id = 1; + sprintf(m_input.name, "%.20s Input", name); + + // Set up the timing variables that we'll be using. + m_trTimeout = 0LL; + m_tpSeekAt = 0; + m_tmSeekTo = 0; + m_delta = 0; + m_seeking = false; + + // Create, and run, the thread that we use to service + // the Control Port. + sprintf(pname, "%.20s Service", name); + m_thread = spawn_thread(ThreadEntry, pname, 110, this); + resume_thread(m_thread); +} + + +SoundConsumer::~SoundConsumer() +{ + NODE(stderr, "SoundConsumer::~SoundConsumer()\n"); + // Signal to our thread that it's time to go home. + write_port(m_port, MSG_QUIT_NOW, 0, 0); + status_t s; + while (wait_for_thread(m_thread, &s) == B_INTERRUPTED) + NODE(stderr, "wait_for_thread() B_INTERRUPTED\n"); + delete_port(m_port); +} + + +status_t +SoundConsumer::SetHooks( + SoundProcessFunc recordFunc, + SoundNotifyFunc notifyFunc, + void * cookie) +{ + // SetHooks needs to be synchronized with the service thread, else we may + // call the wrong hook function with the wrong cookie, which would be bad. + // Rather than do locking, which is expensive, we streamline the process + // by sending our service thread a request to change the hooks, and waiting + // for the acknowledge. + status_t err = B_OK; + set_hooks_q cmd; + cmd.process = recordFunc; + cmd.notify = notifyFunc; + cmd.cookie = cookie; + // If we're not in the service thread, we need to round-trip a message. + if (find_thread(0) != m_thread) { + cmd.reply = create_port(1, "SetHooks reply"); + // Send the private message to our service thread. + err = write_port(ControlPort(), MSG_CHANGE_HOOKS, &cmd, sizeof(cmd)); + if (err >= 0) { + int32 code; + // Wait for acknowledge from the service thread. + err = read_port_etc(cmd.reply, &code, 0, 0, B_TIMEOUT, 6000000LL); + if (err > 0) err = 0; + NODE(stderr, "SoundConsumer::SetHooks read reply: %#010lx\n", err); + } + // Clean up. + delete_port(cmd.reply); + } + else { + // Within the service thread, it's OK to just go ahead and do the change. + DoHookChange(&cmd); + } + return err; +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// BMediaNode-derived methods +// +//////////////////////////////////////////////////////////////////////////////// + + +port_id SoundConsumer::ControlPort() const +{ + return m_port; +} + + +BMediaAddOn* SoundConsumer::AddOn( + int32 * internal_id) const +{ + // This object is instantiated inside an application. + // Therefore, it has no add-on. + if (internal_id) *internal_id = 0; + return 0; +} + + +void SoundConsumer::Start( + bigtime_t performance_time) +{ + // Since we are a consumer and just blindly accept buffers that are + // thrown at us, we don't need to do anything special in Start()/Stop(). + // If we were (also) a producer, we'd have to be more elaborate. + // The only thing we do is immediately perform any queued Seek based on + // the start time, which is the right thing to do (seeing as we were + // Seek()-ed when we weren't started). + if (m_seeking) { + m_delta = performance_time - m_tmSeekTo; + m_seeking = false; + } + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_WILL_START, performance_time); + } + else { + Notify(B_WILL_START, performance_time); + } +} + + +void SoundConsumer::Stop( + bigtime_t performance_time, + bool immediate) +{ + // Since we are a consumer and just blindly accept buffers that are + // thrown at us, we don't need to do anything special in Start()/Stop(). + // If we were (also) a producer, we'd have to be more elaborate. + // Note that this is not strictly in conformance with The Rules, + // but since this is not an add-on Node for use with any application; + // it's a Node over which we have complete control, we can live with + // treating buffers received before the start time or after the stop + // time as any other buffer. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_WILL_STOP, performance_time, immediate); + } + else { + Notify(B_WILL_STOP, performance_time, immediate); + } +} + + +void SoundConsumer::Seek( + bigtime_t media_time, + bigtime_t performance_time) +{ + // Seek() on a consumer just serves to offset the time stamp + // of received buffers passed to our Record hook function. + // In the hook function, you may wish to save those time stamps + // to disk or otherwise store them. You may also want to + // synchronize this node's media time with an upstream + // producer's media time to make this offset meaningful. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_WILL_SEEK, performance_time, media_time); + } + else { + Notify(B_WILL_SEEK, performance_time, media_time); + } + m_tpSeekAt = performance_time; + m_tmSeekTo = media_time; + m_seeking = true; +} + + +void SoundConsumer::SetRunMode( + run_mode mode) +{ + if (mode == BMediaNode::B_OFFLINE) { + // BMediaNode::B_OFFLINE means we don't need to run in + // real time. So, we shouldn't run as a real time + // thread. + int32 new_prio = suggest_thread_priority(B_OFFLINE_PROCESSING); + set_thread_priority(m_thread, new_prio); + } + else { + // We're running in real time, so we'd better have + // a big enough thread priority to handle it! + // Here's where those magic scheduler values + // come from: + // + // * In the worst case, we process one buffer per + // reschedule (we get rescheduled when we go to + // look for a message on our Control Port), so + // in order to keep up with the incoming buffers, + // the duration of one buffer becomes our + // scheduling period. If we don't know anything + // about the buffers, we pick a reasonable + // default. + // * We're a simple consumer, so we don't have to + // be too picky about the jitter. Half a period + // of jitter means that we'd have to get two + // consecutive worst-case reschedules before + // we'd fall behind. + // * The amount of time we spend processing is + // our ProcessingLatency(). + bigtime_t period = 10000; + if (buffer_duration(m_input.format.u.raw_audio) > 0) { + period = buffer_duration(m_input.format.u.raw_audio); + } + // assuming we're running for 500 us or less per buffer + int32 new_prio = suggest_thread_priority(B_AUDIO_RECORDING, + period, period/2, ProcessingLatency()); + set_thread_priority(m_thread, new_prio); + } +} + + +void SoundConsumer::TimeWarp( + bigtime_t at_real_time, + bigtime_t to_performance_time) +{ + // Since buffers will come pre-time-stamped, we only need to look + // at them, so we can ignore the time warp as a consumer. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_WILL_TIMEWARP, at_real_time, to_performance_time); + } + else { + Notify(B_WILL_TIMEWARP, at_real_time, to_performance_time); + } +} + + +void SoundConsumer::Preroll() +{ + // There is nothing for us to do in Preroll() +} + + +void SoundConsumer::SetTimeSource( + BTimeSource * /* time_source */) +{ + // We don't need to do anything special to take note of the + // fact that the time source changed, because we get our timing + // information from the buffers we receive. +} + + +status_t SoundConsumer::HandleMessage( + int32 message, + const void * data, + size_t size) +{ + // Check with each of our superclasses to see if they + // understand the message. If none of them do, call + // BMediaNode::HandleBadMessage(). + if ((BBufferConsumer::HandleMessage(message, data, size) < 0) + && (BMediaNode::HandleMessage(message, data, size) < 0)) + { + HandleBadMessage(message, data, size); + return B_ERROR; + } + return B_OK; +} + + + + + +//////////////////////////////////////////////////////////////////////////////// +// +// BBufferConsumer-derived methods +// +//////////////////////////////////////////////////////////////////////////////// + + + +status_t SoundConsumer::AcceptFormat( + const media_destination & dest, + media_format * format) +{ + // We only accept formats aimed at our single input. + if (dest != m_input.destination) { + return B_MEDIA_BAD_DESTINATION; + } + // If no format is specified, we say we want raw audio. + if (format->type <= 0) { + format->type = B_MEDIA_RAW_AUDIO; + format->u.raw_audio = media_raw_audio_format::wildcard; + } + // If a non-raw-audio format is specified, we tell the world what + // we want, and that the specified format was unacceptable to us. + else if (format->type != B_MEDIA_RAW_AUDIO) { + format->type = B_MEDIA_RAW_AUDIO; + format->u.raw_audio = media_raw_audio_format::wildcard; + return B_MEDIA_BAD_FORMAT; + } +#if !ACCEPT_ANY_FORMAT_CHANGE + // If we're already connected, and this format doesn't go with the + // format in effect, we dont' accept this new format. + if (!format_is_compatible(*format, m_input.format)) { + *format = m_input.format; + return B_MEDIA_BAD_FORMAT; + } +#endif + // I guess we're OK by now, because we have no particular needs as + // far as frame rate, sample format, etc go. + return B_OK; +} + + +status_t SoundConsumer::GetNextInput( + int32 * cookie, + media_input * out_input) +{ + NODE(stderr, "SoundConsumer: GetNextInput()\n"); + // The "next" is kind of misleading, since it's also used for + // getting the first (and only) input. + if (!*cookie) { + if (m_input.source == media_source::null) { + // If there's no current connection, make sure we return a + // reasonable format telling the world we accept any raw audio. + m_input.format.type = B_MEDIA_RAW_AUDIO; + m_input.format.u.raw_audio = media_raw_audio_format::wildcard; + m_input.node = Node(); + m_input.destination.port = ControlPort(); + m_input.destination.id = 1; + } + *out_input = m_input; + *cookie = 1; + return B_OK; + } + // There's only one input. + return B_BAD_INDEX; +} + + +void SoundConsumer::DisposeInputCookie( + int32 /* cookie */) +{ + // We didn't allocate any memory or set any state in GetNextInput() + // so this function is a no-op. +} + + +void SoundConsumer::BufferReceived( + BBuffer * buffer) +{ + NODE(stderr, "SoundConsumer::BufferReceived()\n"); + // Whee, a buffer! Update the seek info, if necessary. + if (m_seeking && buffer->Header()->start_time >= m_tpSeekAt) { + m_delta = m_tpSeekAt - m_tmSeekTo; + m_seeking = false; + } + // If there is a record hook, let the interested party have at it! + if (m_recordHook) { + (*m_recordHook)(m_cookie, buffer->Header()->start_time-m_delta, buffer->Data(), buffer->Header()->size_used, m_input.format.u.raw_audio); + } + else { + Record(buffer->Header()->start_time-m_delta, buffer->Data(), buffer->Header()->size_used, m_input.format.u.raw_audio); + } + // Buffers should ALWAYS be recycled, else whomever is producing them + // will starve. + buffer->Recycle(); +} + + +void SoundConsumer::ProducerDataStatus( + const media_destination & for_whom, + int32 status, + bigtime_t at_media_time) +{ + if (for_whom == m_input.destination) { + // Tell whomever is interested that the upstream producer will or won't + // send more data in the immediate future. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_PRODUCER_DATA_STATUS, status, at_media_time); + } + else { + Notify(B_PRODUCER_DATA_STATUS, status, at_media_time); + } + } +} + + +status_t SoundConsumer::GetLatencyFor( + const media_destination & for_whom, + bigtime_t * out_latency, + media_node_id * out_timesource) +{ + // We only accept requests for the one-and-only input of our Node. + if (for_whom != m_input.destination) { + return B_MEDIA_BAD_DESTINATION; + } + // Tell the world about our latency information (overridable by user). + *out_latency = TotalLatency(); + *out_timesource = TimeSource()->Node().node; + return B_OK; +} + + +status_t SoundConsumer::Connected( + const media_source & producer, + const media_destination & where, + const media_format & with_format, + media_input * out_input) +{ + NODE(stderr, "SoundConsumer::Connected()\n"); + // Only accept connection requests when we're not already connected. + if (m_input.source != media_source::null) { + return B_MEDIA_BAD_DESTINATION; + } + // Only accept connection requests on the one-and-only available input. + if (where != m_input.destination) { + return B_MEDIA_BAD_DESTINATION; + } + // Other than that, we accept pretty much anything. The format has been + // pre-cleared through AcceptFormat(), and we accept any format anyway. + m_input.source = producer; + m_input.format = with_format; + // Tell whomever is interested that there's now a connection. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_CONNECTED, m_input.name); + } + else { + Notify(B_CONNECTED, m_input.name); + } + // This is the most important line -- return our connection information + // to the world so it can use it! + *out_input = m_input; + return B_OK; +} + + +void SoundConsumer::Disconnected( + const media_source & producer, + const media_destination & where) +{ + // We can't disconnect something which isn't us. + if (where != m_input.destination) { + return; + } + // We can't disconnect from someone who isn't connected to us. + if (producer != m_input.source) { + return; + } + // Tell the interested party that it's time to leave. + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_DISCONNECTED); + } + else { + Notify(B_DISCONNECTED); + } + // Mark ourselves as not-connected. + m_input.source = media_source::null; +} + + +status_t SoundConsumer::FormatChanged( + const media_source & producer, + const media_destination & consumer, + int32 from_change_count, + const media_format & format) +{ + NODE(stderr, "SoundConsumer::Connected()\n"); + // The up-stream guy feels like changing the format. If we can accept + // arbitrary format changes, we just say "OK". If, however, we're recording + // to a file, that's not such a good idea; we only accept format changes + // that are compatible with the format we're already using. You set this + // behaviour at compile time by defining ACCEPT_ANY_FORMAT_CHANGE to 1 or 0. + status_t err = B_OK; +#if ACCEPT_ANY_FORMAT_CHANGE + media_format fmt(format); + err = AcceptFormat(m_input.destination, &fmt); +#else + if (m_input.source != media_source::null) { + err = format_is_compatible(format, m_input.format) ? B_OK : B_MEDIA_BAD_FORMAT; + } +#endif + if (err >= B_OK) { + m_input.format = format; + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_FORMAT_CHANGED, &m_input.format.u.raw_audio); + } + else { + Notify(B_FORMAT_CHANGED, &m_input.format.u.raw_audio); + } + } + return err; +} + + +void +SoundConsumer::DoHookChange( + void * msg) +{ + // Tell the old guy we're changing the hooks ... + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_HOOKS_CHANGED); + } + else { + Notify(B_HOOKS_CHANGED); + } + // ... and then do it. + set_hooks_q * ptr = (set_hooks_q *)msg; + m_recordHook = ptr->process; + m_notifyHook = ptr->notify; + m_cookie = ptr->cookie; +} + + +status_t +SoundConsumer::ThreadEntry( + void * obj) +{ + ((SoundConsumer *)obj)->ServiceThread(); + return 0; +} + + +void +SoundConsumer::ServiceThread() +{ + // The Big Bad ServiceThread receives messages aimed at this + // Node and dispatches them (typically to HandleMessage()). + // If we were a Producer, we might have to do finicky timing and + // queued Start()/Stop() processing in here. But we ain't. + + // A media kit message will never be bigger than B_MEDIA_MESSAGE_SIZE. + // Avoid wasing stack space by dynamically allocating at start. + char * msg = new char[B_MEDIA_MESSAGE_SIZE]; + // Make sure we clean up this data when we exit the function. + array_delete msg_delete(msg); + int bad = 0; + while (true) { + // Call read_port_etc() with a timeout derived from a virtual function, + // to allow clients to do special processing if necessary. + bigtime_t timeout = Timeout(); + int32 code = 0; + status_t err = read_port_etc(m_port, &code, msg, B_MEDIA_MESSAGE_SIZE, + B_TIMEOUT, timeout); + MESSAGE(stderr, "SoundConsumer::ServiceThread() port %ld message %#010lx\n", m_port, code); + // If we received a message, err will be the size of the message (including 0). + if (err >= 0) { + // Real messages reset the timeout time. + m_trTimeout = 0; + bad = 0; + // Check for our private stop message. + if (code == MSG_QUIT_NOW) { + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_NODE_DIES, 0); + } + else { + Notify(B_NODE_DIES, 0); + } + break; + } + // Else check for our private change-hooks message. + else if (code == MSG_CHANGE_HOOKS) { + DoHookChange(msg); + // Write acknowledge to waiting thread. + write_port(((set_hooks_q *)msg)->reply, 0, 0, 0); + } + // Else it has to be a regular media kit message; go ahead and + // dispatch it. + else { + HandleMessage(code, msg, err); + } + } + // Timing out means that there was no buffer. Tell the interested party. + else if (err == B_TIMED_OUT) { + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_OP_TIMED_OUT, timeout); + } + else { + Notify(B_OP_TIMED_OUT, timeout); + } + } + // Other errors are bad. + else { + FPRINTF(stderr, "SoundConsumer: error %#010lx\n", err); + bad++; + // If we receive three bad reads with no good messages inbetween, + // things are probably not going to improve (like the port disappeared + // or something) so we call it a day. + if (bad > 3) { + if (m_notifyHook) { + (*m_notifyHook)(m_cookie, B_NODE_DIES, bad, err, code, msg); + } + else { + Notify(B_NODE_DIES, bad, err, code, msg); + } + break; + } + } + } +} + + +bigtime_t +SoundConsumer::Timeout() +{ + // Timeout() is called for each call to read_port_etc() in the service + // thread to figure out a reasonable time-out value. The default behaviour + // we've picked is to exponentially back off from one second and upwards. + // While it's true that 44 back-offs will run us out of precision in a + // bigtime_t, the time to actually reach 44 consecutive back-offs is longer + // than the expected market longevity of just about any piece of real estate. + // Is that the sound of an impending year-fifteen-million software problem? :-) + m_trTimeout = (m_trTimeout < 1000000) ? 1000000 : m_trTimeout*2; + return m_trTimeout; +} + + +bigtime_t +SoundConsumer::ProcessingLatency() +{ + // We're saying it takes us 500 us to process each buffer. If all we do is + // copy the data, it probably takes much less than that, but it doesn't + // hurt to be slightly conservative. + return 500LL; +} + + +bigtime_t +SoundConsumer::TotalLatency() +{ + // Had we been a producer that passes buffers on, we'd have to + // include downstream latency in this value. But we are not. + return ProcessingLatency(); +} + +void +SoundConsumer::Record( + bigtime_t /* time */, + const void * /* data */, + size_t /* size */, + const media_raw_audio_format & /* format */) +{ + // If there is no record hook installed, we instead call this function + // for received buffers. +} + + +void +SoundConsumer::Notify( + int32 /* cause */, + ...) +{ + // If there is no notification hook installed, we instead call this function + // for giving notification of various events. +} diff --git a/src/apps/soundrecorder/SoundConsumer.h b/src/apps/soundrecorder/SoundConsumer.h new file mode 100644 index 0000000000..d8fc3ca1f1 --- /dev/null +++ b/src/apps/soundrecorder/SoundConsumer.h @@ -0,0 +1,173 @@ +/******************************************************************************* +/ +/ File: SoundConsumer.h +/ +/ Description: Record sound from some sound-producing Node. +/ +/ Copyright 1998, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#if !defined( _SoundConsumer_h ) +#define _SoundConsumer_h + +#include +#include "SoundUtils.h" + +// To use this Consumer: +// 1. Create Record and Notify hooks, or subclass SoundConsumer +// if you'd rather use the inheritance hierarchy. +// * The Record function should do whatever you want to do +// when you receive a buffer. +// * The Notify function should handle whatever events +// you wish to handle (defined in SoundUtil.h). +// 2: Create an instance of SoundConsumer, giving it the +// appropriate hook functions. Or, create an instance of an +// appropriate subclass if you've made one. +// 3: Register your new Consumer with the MediaRoster. +// 4: Connect your Consumer to some Producer. +// 5: Start or Stop the Consumer if your hook functions +// implement behavior for these kinds of events. +// Seek the Consumer to set the offset of the timestamps that +// your Record function will see. +// 6: When you're done, disconnect the Consumer, then delete it. + +class SoundConsumer : + public BBufferConsumer +{ +public: + SoundConsumer( + const char * name, + SoundProcessFunc recordFunc = NULL, + SoundNotifyFunc notifyFunc = NULL, + void * cookie = NULL); + ~SoundConsumer(); + + // This function is OK to call from any thread. + status_t SetHooks( + SoundProcessFunc recordFunc = NULL, + SoundNotifyFunc notifyFunc = NULL, + void * cookie = NULL); + + // The MediaNode interface +public: +virtual port_id ControlPort() const; +virtual BMediaAddOn* AddOn( + int32 * internal_id) const; /* Who instantiated you -- or NULL for app class */ + + +protected: + +virtual void Start( + bigtime_t performance_time); +virtual void Stop( + bigtime_t performance_time, + bool immediate); +virtual void Seek( + bigtime_t media_time, + bigtime_t performance_time); +virtual void SetRunMode( + run_mode mode); +virtual void TimeWarp( + bigtime_t at_real_time, + bigtime_t to_performance_time); +virtual void Preroll(); +virtual void SetTimeSource( + BTimeSource * time_source); +virtual status_t HandleMessage( + int32 message, + const void * data, + size_t size); + + // The BufferConsumer interface +virtual status_t AcceptFormat( + const media_destination & dest, + media_format * format); +virtual status_t GetNextInput( /* cookie starts at 0 */ + int32 * cookie, + media_input * out_input); +virtual void DisposeInputCookie( + int32 cookie); +virtual void BufferReceived( + BBuffer * buffer); +virtual void ProducerDataStatus( + const media_destination & for_whom, + int32 status, + bigtime_t at_media_time); +virtual status_t GetLatencyFor( + const media_destination & for_whom, + bigtime_t * out_latency, + media_node_id * out_timesource); +virtual status_t Connected( + const media_source & producer, + const media_destination & where, + const media_format & with_format, + media_input * out_input); +virtual void Disconnected( + const media_source & producer, + const media_destination & where); +virtual status_t FormatChanged( + const media_source & producer, + const media_destination & consumer, + int32 from_change_count, + const media_format & format); + +protected: + // Functions called when no hooks are installed. + // OK to override instead of installing hooks. +virtual void Record( + bigtime_t time, + const void * data, + size_t size, + const media_raw_audio_format & format); +virtual void Notify( + int32 cause, + ...); + +private: + SoundProcessFunc m_recordHook; + SoundNotifyFunc m_notifyHook; + void * m_cookie; + media_input m_input; + thread_id m_thread; + port_id m_port; + + // The times we need to deal with + // My notation for times: tr = real time, + // tp = performance time, tm = media time. + bigtime_t m_trTimeout; // how long to wait on the input port + bigtime_t m_tpSeekAt; // when we Seek + bigtime_t m_tmSeekTo; // target time for Seek + + // The transformation from media to peformance time. + // d = p - m, so m + d = p. + // Media time is generally governed by the Seek + // function. In our node, we simply use media time as + // the time that we report to the record hook function. + // If we were a producer node, we might use media time + // to track where we were in playing a certain piece + // of media. But we aren't. + bigtime_t m_delta; + + // State variables + bool m_seeking; // a Seek is pending + + // Functions to calculate timing values. OK to override. + // ProcessingLatency is the time it takes to process a buffer; + // TotalLatency is returned to producer; Timeout is passed + // to call to read_port_etc() in service thread loop. +virtual bigtime_t Timeout(); +virtual bigtime_t ProcessingLatency(); +virtual bigtime_t TotalLatency(); + // The actual thread doing the work +static status_t ThreadEntry( + void * obj); + void ServiceThread(); + void DoHookChange( + void * msg); +}; + + +#endif /* _SoundConsumer_h */ + diff --git a/src/apps/soundrecorder/SoundListView.cpp b/src/apps/soundrecorder/SoundListView.cpp new file mode 100644 index 0000000000..5f306dce34 --- /dev/null +++ b/src/apps/soundrecorder/SoundListView.cpp @@ -0,0 +1,70 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ +#include + +#include "SoundListView.h" + + +SoundListView::SoundListView( + const BRect & area, + const char * name, + uint32 resize) : + BListView(area, name, B_SINGLE_SELECTION_LIST, resize) +{ +} + +SoundListView::~SoundListView() +{ +} + +void +SoundListView::Draw(BRect updateRect) +{ + if (IsEmpty()) { + SetHighColor(235,235,235); + FillRect(Bounds()); + + SetHighColor(0,0,0); + BFont font(be_bold_font); + font.SetSize(12.0); + SetFont(&font); + font_height height; + font.GetHeight(&height); + float width = font.StringWidth("Drop Files Here"); + + BPoint pt; + pt.x = (Bounds().Width() - width) / 2; + pt.y = (Bounds().Height() + height.ascent + height.descent)/ 2; + DrawString("Drop Files Here", pt); + } + BListView::Draw(updateRect); +} + + +void +SoundListView::AttachedToWindow() +{ + BListView::AttachedToWindow(); + SetViewColor(255,255,255); +} + + +SoundListItem::SoundListItem( + const BEntry & entry, + bool isTemp) + : BStringItem(""), + fEntry(entry), + fIsTemp(isTemp) +{ + char name[256]; + fEntry.GetName(name); + SetText(name); +} + +SoundListItem::~SoundListItem() +{ +} diff --git a/src/apps/soundrecorder/SoundListView.h b/src/apps/soundrecorder/SoundListView.h new file mode 100644 index 0000000000..9ce078e90a --- /dev/null +++ b/src/apps/soundrecorder/SoundListView.h @@ -0,0 +1,40 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef SOUNDLISTVIEW_H +#define SOUNDLISTVIEW_H + +#include + +class SoundListView : public BListView { +public: + SoundListView(const BRect & area, const char * name, uint32 resize); + virtual ~SoundListView(); + + virtual void Draw(BRect updateRect); + virtual void AttachedToWindow(); +}; + + +#include + +class SoundListItem : public BStringItem { +public: + SoundListItem(const BEntry & entry, bool isTemp); +virtual ~SoundListItem(); + + BEntry & Entry() { return fEntry; } + bool IsTemp() { return fIsTemp; } + void SetTemp(bool isTemp) { fIsTemp = isTemp; } +private: + BEntry fEntry; + bool fIsTemp; +}; + + +#endif /* SOUNDLISTVIEW_H */ + diff --git a/src/apps/soundrecorder/SoundPrivate.h b/src/apps/soundrecorder/SoundPrivate.h new file mode 100644 index 0000000000..a50a8b67e9 --- /dev/null +++ b/src/apps/soundrecorder/SoundPrivate.h @@ -0,0 +1,41 @@ +/******************************************************************************* +/ +/ File: SoundPrivate.h +/ +/ Description: Implementation headers for SoundConsumer and SoundProducer. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#if ! defined( _SoundPrivate_h ) +#define _SoundPrivate_h + +// The following are implementation details that we don't +// want to expose to the world at large. + +#include "SoundUtils.h" + +// This structure is the body of a request that we use to +// implement SetHooks(). +struct set_hooks_q { + port_id reply; + void * cookie; + SoundProcessFunc process; + SoundNotifyFunc notify; +}; + +// All incoming buffers and Media Kit requests arrive at a +// media node in the form of messages (which are generally +// dispatched for you by your superclasses' HandleMessage +// implementations). Each message has a 'type' which is +// analagous to a BMessage's 'what' field. We'll define our +// own private message types for our SoundConsumer and +// SoundProducer to use. The BeOS reserves a range, +// 0x60000000 to 0x7fffffff, for us to use. +enum { + MSG_QUIT_NOW = 0x60000000L, + MSG_CHANGE_HOOKS +}; + +#endif /* _SoundPrivate_h */ diff --git a/src/apps/soundrecorder/SoundRecorder.rdef b/src/apps/soundrecorder/SoundRecorder.rdef new file mode 100644 index 0000000000..e5fa0cd7c5 --- /dev/null +++ b/src/apps/soundrecorder/SoundRecorder.rdef @@ -0,0 +1,83 @@ + +resource app_signature "application/x-vnd.haiku.SoundRecorder"; + +resource app_flags B_SINGLE_LAUNCH; + +resource app_version +{ + major = 1, + middle = 0, + minor = 0, + variety = B_APPV_BETA, + internal = 0, + short_info = "SoundRecorder", + long_info = "Haiku Sound Recorder" +}; + +resource file_types message +{ + "types" = "audio/basic", + "types" = "audio/x-wav", + "types" = "audio/x-riff", + "types" = "audio/x-aifc", + "types" = "audio/x-aiff", + "types" = "audio/wav", + "types" = "audio/aiff", + "types" = "audio/riff" +}; + +resource large_icon array +{ + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FED8D80202FFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF00FED88484D8D80202FFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFF00FED884D8D88484D8D80202FFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF00FED8D8D88484D8D8AAAAD8D80202FFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFF00FED8D88484D8D8AAAAD8D8AA84D8D80202FFFFFF" + $"FFFFFFFFFFFFFFFFFFFF00FED8D884D8D8AAAAD8D8AAAAD8D88484D8D802FFFF" + $"FFFFFFFFFFFFFFFFFF00FE07D8D8D88484D8D8AAAAD8D8AA84D8D884D829FFFF" + $"FFFFFFFFFFFFFFFF00FE070A0707D8D8D8AAAAD8D8AAAAD8D88484D8D804FFFF" + $"FFFFFFFFFFFFFF00FE070A0A0A0A0707D8D8D8AAAAD8D88484D8D8D88329FFFF" + $"FFFFFFFFFFFF00FE070A0A0A0A0A0A0A0707D8D8D88484D8D8D8D8838302FFFF" + $"FFFFFFFFFF00FE070A0A0A0F150A0A0A0A0A0707D8D8D884D8D883838302FFFF" + $"FFFFFFFF00FE070A0A0A0A0F0F0A0A0A0A0A0A0A0707D8D8D8838383830210FF" + $"FFFFFF00FED8D807070A0A0A0A0A0A0F150A0A0A0A07D8D88383838383021010" + $"FFFF00FED8FEFED8D807070A0A0A0A0F0F0A0A0A07D8D8838383838300101010" + $"FF00FED80910D8FEFED8D807070A0A0A0A0A0A07D8D8838383838300101010FF" + $"FF00FE091010099CD8FEFED8D807070A0A0A07D8D8838383838300101010FFFF" + $"00FE091010099C9C3010D8FEFED8D8070707D8D8838383838300101010FFFFFF" + $"00D80C0C099C9C3010100910D8FEFED8D8D8D8838383838300101010FFFFFFFF" + $"FF0083832C2C3010100910100910D8FED8D8838383838300101010FFFFFFFFFF" + $"FFFF333383830C0C09101009101009D8D8838383838300101010FFFFFFFFFFFF" + $"FFFFFFFF330083830C0C09101009D8D8D88383838300101010FFFFFFFFFFFFFF" + $"FFFFFFFFFFFF003383830C0C0909D8D8D883838300101010FFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFF0000838309D8D8D883838300101010FFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFF00008383D8D8838300101010FFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFF280083838300101010FFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFF000000101010FFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; + +resource mini_icon array +{ + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + $"FFFFFFFFFFFFFF000000FFFFFFFFFFFF" + $"FFFFFFFFFFFF00FED8840000FFFFFFFF" + $"FFFFFFFFFF00FED8AAD8AA840000FFFF" + $"FFFFFFFF00FE0707D88484D8AAD800FF" + $"FFFFFF00FE070F090707D8AAD8D800FF" + $"FFFF00FE0709150F0F09070FD88300FF" + $"FF00FED807070909150F09D883830010" + $"00FE09FEFED807070909D88383001010" + $"000910099CFEFED807D88383001010FF" + $"0010099C9C0C09FED88383001010FFFF" + $"FF00092C0C090CD88383001010FFFFFF" + $"FFFF0000090CD88383001010FFFFFFFF" + $"FFFFFFFF00008383001010FFFFFFFFFF" + $"FFFFFFFFFFFF00001010FFFFFFFFFFFF" + $"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +}; diff --git a/src/apps/soundrecorder/SoundUtils.cpp b/src/apps/soundrecorder/SoundUtils.cpp new file mode 100644 index 0000000000..051e5a2563 --- /dev/null +++ b/src/apps/soundrecorder/SoundUtils.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* +/ +/ File: SoundUtils.cpp +/ +/ Description: Utility functions for handling audio data. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#include +#include "SoundUtils.h" + +// These two conversions seem to pop up all the time in media code. +// I guess it's the curse of microsecond resolution... ;-) +double +us_to_s(bigtime_t usecs) +{ + return (usecs / 1000000.0); +} + +bigtime_t +s_to_us(double secs) +{ + return (bigtime_t) (secs * 1000000.0); +} + +int +bytes_per_frame( + const media_raw_audio_format & format) +{ + // The media_raw_audio_format format constants encode the + // bytes-per-sample value in the low nybble. Having a fixed + // number of bytes-per-sample, and no inter-sample relationships, + // is what makes a format "raw". + int bytesPerSample = format.format & 0xf; + return bytesPerSample * format.channel_count; +} + +int +frames_per_buffer( + const media_raw_audio_format & format) +{ + // This will give us the number of full-sized frames that will fit + // in a buffer. (Remember, integer division automatically rounds + // down.) + int frames = 0; + if (bytes_per_frame(format) > 0) { + frames = format.buffer_size / bytes_per_frame(format); + } + return frames; +} + +bigtime_t +buffer_duration( + const media_raw_audio_format & format) +{ + // Figuring out duration is easy. We take extra precaution to + // not divide by zero or return irrelevant results. + bigtime_t duration = 0; + if (format.buffer_size > 0 && format.frame_rate > 0 && bytes_per_frame(format) > 0) { + // In these kinds of calculations, it's always useful to double-check + // the unit conversions. (Anyone remember high school physics?) + // bytes/(bytes/frame) / frames/sec + // = frames * sec/frames + // = secs which is what we want. + duration = s_to_us((format.buffer_size / bytes_per_frame(format)) / format.frame_rate); + } + return duration; +} + +bigtime_t +frames_duration( + const media_raw_audio_format & format, int64 num_frames) +{ + // Tells us how long in us it will take to produce num_frames, + // with the given format. + bigtime_t duration = 0; + if (format.frame_rate > 0) { + duration = s_to_us(num_frames/format.frame_rate); + } + return duration; +} + +int +buffers_for_duration( + const media_raw_audio_format & format, bigtime_t duration) +{ + // Double-checking those unit conversions again: + // secs * ( (frames/sec) / (frames/buffer) ) = secs * (buffers/sec) = buffers + int buffers = 0; + if (frames_per_buffer(format) > 0) { + buffers = (int) ceil(us_to_s(duration)*(format.frame_rate/frames_per_buffer(format))); + } + return buffers; +} + +int64 +frames_for_duration( + const media_raw_audio_format & format, bigtime_t duration) +{ + return (int64) ceil(format.frame_rate*us_to_s(duration)); +} diff --git a/src/apps/soundrecorder/SoundUtils.h b/src/apps/soundrecorder/SoundUtils.h new file mode 100644 index 0000000000..c9e5ec86a9 --- /dev/null +++ b/src/apps/soundrecorder/SoundUtils.h @@ -0,0 +1,56 @@ +/******************************************************************************* +/ +/ File: SoundUtils.h +/ +/ Description: Utility functions for handling audio data. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + +#if ! defined( _SoundUtils_h ) +#define _SoundUtils_h + +#include + +// Simple helper functions that come in handy when doing +// buffer calculations. +double us_to_s(bigtime_t usecs); +bigtime_t s_to_us(double secs); + +int bytes_per_frame(const media_raw_audio_format & format); +int frames_per_buffer(const media_raw_audio_format & format); +bigtime_t buffer_duration(const media_raw_audio_format & format); +bigtime_t frames_duration(const media_raw_audio_format & format, + int64 num_frames); +int64 frames_for_duration(const media_raw_audio_format & format, + bigtime_t duration); +int buffers_for_duration(const media_raw_audio_format & format, + bigtime_t duration); + +// This is a common hook function interface for +// SoundConsumer and SoundProducer to use. +typedef void (*SoundProcessFunc)(void * cookie, + bigtime_t timestamp, void * data, size_t datasize, + const media_raw_audio_format & format); +typedef void (*SoundNotifyFunc)(void * cookie, + int32 code, ...); + +// These are special codes that we use in the Notify +// function hook. +enum { + B_WILL_START = 1, // performance_time + B_WILL_STOP, // performance_time immediate + B_WILL_SEEK, // performance_time media_time + B_WILL_TIMEWARP, // real_time performance_time + B_CONNECTED, // name (char*) + B_DISCONNECTED, // + B_FORMAT_CHANGED, // media_raw_audio_format* + B_NODE_DIES, // node will die! + B_HOOKS_CHANGED, // + B_OP_TIMED_OUT, // timeout that expired -- Consumer only + B_PRODUCER_DATA_STATUS, // status performance_time -- Consumer only + B_LATE_NOTICE // how_much performance_time -- Producer only +}; + +#endif /* _SoundUtils_h */ diff --git a/src/apps/soundrecorder/TrackSlider.cpp b/src/apps/soundrecorder/TrackSlider.cpp new file mode 100644 index 0000000000..131b1623f5 --- /dev/null +++ b/src/apps/soundrecorder/TrackSlider.cpp @@ -0,0 +1,465 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include + +#include "TrackSlider.h" +#include "icon_button.h" + +TrackSlider::TrackSlider(BRect rect, const char *title, BMessage *msg, uint32 resizeFlags) + : BControl(rect, "slider", NULL, msg, resizeFlags, B_WILL_DRAW | B_FRAME_EVENTS), + leftBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8), + rightBitmap(BRect(BPoint(0,0), kLeftRightTrackSliderSize), B_CMAP8), + leftThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8), + rightThumbBitmap(BRect(0, 0, kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1), B_CMAP8), + fLeftTime(0), fRightTime(1000000), fMainTime(0), fTotalTime(1000000), + fLeftTracking(false), fRightTracking(false), fMainTracking(false) +{ + fFont.SetSize(8.0); + fFont.SetFlags(B_DISABLE_ANTIALIASING); + + int32 numFamilies = count_font_families(); + for (int32 i = 0; i < numFamilies; i++ ) { + font_family family; + uint32 flags; + if ((get_font_family(i, &family, &flags) == B_OK) + && (strcmp(family, "Baskerville") == 0)) { + fFont.SetFamilyAndFace(family, B_REGULAR_FACE); + break; + } + } + leftBitmap.SetBits(kLeftTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8); + rightBitmap.SetBits(kRightTrackSliderBits, kLeftRightTrackSliderWidth * kLeftRightTrackSliderHeight, 0, B_CMAP8); + leftThumbBitmap.SetBits(kLeftThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8); + rightThumbBitmap.SetBits(kRightThumbBits, kLeftRightThumbWidth * kLeftRightThumbHeight, 0, B_CMAP8); + + fRight = Bounds().right - kLeftRightTrackSliderWidth; + if (fTotalTime == 0) { + fLeftX = 14; + fRightX = fRight; + fPositionX = 15; + } else { + fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); + fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); + fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); + } +} + + +TrackSlider::~TrackSlider() +{ + +} + + +void +TrackSlider::AttachedToWindow() +{ + BControl::AttachedToWindow(); + SetViewColor(B_TRANSPARENT_COLOR); +} + + +#define SLIDER_BASE 10 + +void +TrackSlider::Draw(BRect updateRect) +{ + SetHighColor(189,186,189); + StrokeLine(BPoint(11,SLIDER_BASE+1), BPoint(fRight,SLIDER_BASE+1)); + SetHighColor(0,0,0); + StrokeLine(BPoint(11,SLIDER_BASE+2), BPoint(fRight,SLIDER_BASE+2)); + SetHighColor(255,255,255); + StrokeLine(BPoint(11,SLIDER_BASE+17), BPoint(fRight,SLIDER_BASE+17)); + SetHighColor(231,227,231); + StrokeLine(BPoint(11,SLIDER_BASE+18), BPoint(fRight,SLIDER_BASE+18)); + + SetDrawingMode(B_OP_OVER); + + SetHighColor(216,216,216); + FillRect(BRect(0,1,fPositionX < 18 ? 18 : fPositionX-26,SLIDER_BASE)); + FillRect(BRect(fPositionX < 18 ? 65 : fPositionX > fRight - 3 ? fRight : fPositionX+26,0,Bounds().right,SLIDER_BASE)); + FillRect(BRect(0,0,Bounds().right,0)); + FillRect(BRect(0,SLIDER_BASE+18,Bounds().right,SLIDER_BASE+21)); + FillRect(BRect(0,0,10,SLIDER_BASE+21)); + FillRect(BRect(Bounds().right - 10,0,Bounds().right,SLIDER_BASE+21)); + + SetLowColor(HighColor()); + + BPoint leftPoint(5,SLIDER_BASE+1); + DrawBitmapAsync(&leftBitmap, BRect(BPoint(0,0), kLeftRightTrackSliderSize - BPoint(5,0)), + BRect(leftPoint, leftPoint+kLeftRightTrackSliderSize-BPoint(5,0))); + BPoint rightPoint(fRight + 1,SLIDER_BASE+1); + DrawBitmapAsync(&rightBitmap, BRect(BPoint(5,0), kLeftRightTrackSliderSize), + BRect(rightPoint, rightPoint+kLeftRightTrackSliderSize-BPoint(5,0))); + + SetHighColor(153,153,153); + FillRect(BRect(11,SLIDER_BASE+3,fLeftX-9,SLIDER_BASE+16)); + FillRect(BRect(fRightX+9,SLIDER_BASE+3,fRight,SLIDER_BASE+16)); + if (fLeftX>19) { + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+3),BPoint(fLeftX-6,SLIDER_BASE+3)); + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+4),BPoint(fLeftX-7,SLIDER_BASE+4)); + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+5),BPoint(fLeftX-8,SLIDER_BASE+5)); + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+16),BPoint(fLeftX-6,SLIDER_BASE+16)); + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+15),BPoint(fLeftX-7,SLIDER_BASE+15)); + StrokeLine(BPoint(fLeftX-9,SLIDER_BASE+14),BPoint(fLeftX-8,SLIDER_BASE+14)); + } + if (fRightX < fRight - 5) { + StrokeLine(BPoint(fRightX+5,SLIDER_BASE+3),BPoint(fRightX+8,SLIDER_BASE+3)); + StrokeLine(BPoint(fRightX+7,SLIDER_BASE+4),BPoint(fRightX+8,SLIDER_BASE+4)); + StrokeLine(BPoint(fRightX+8,SLIDER_BASE+5),BPoint(fRightX+8,SLIDER_BASE+6)); + StrokeLine(BPoint(fRightX+8,SLIDER_BASE+13),BPoint(fRightX+8,SLIDER_BASE+14)); + StrokeLine(BPoint(fRightX+5,SLIDER_BASE+16),BPoint(fRightX+8,SLIDER_BASE+16)); + StrokeLine(BPoint(fRightX+7,SLIDER_BASE+15),BPoint(fRightX+8,SLIDER_BASE+15)); + } + SetHighColor(144,186,136); + FillRect(BRect(fLeftX+1,SLIDER_BASE+3,fRightX,SLIDER_BASE+4)); + FillRect(BRect(fLeftX+1,SLIDER_BASE+5,fLeftX+2,SLIDER_BASE+16)); + SetHighColor(171,221,161); + FillRect(BRect(fLeftX+3,SLIDER_BASE+5,fRightX,SLIDER_BASE+16)); + + int i = 17; + int j = 18; + SetHighColor(128,128,128); + for (; i fRight - 23) + counterX = fRight - 23; + BeginLineArray(30); + if (!isTracking) { + AddLine(BPoint(counterX-24,SLIDER_BASE+1), BPoint(counterX+24,SLIDER_BASE+1), gray); + AddLine(BPoint(counterX+25,SLIDER_BASE+1), BPoint(counterX+25,SLIDER_BASE-8), gray); + AddLine(BPoint(counterX-25,SLIDER_BASE+1), BPoint(counterX-25,SLIDER_BASE-9), white); + AddLine(BPoint(counterX-24,SLIDER_BASE-9), BPoint(counterX+25,SLIDER_BASE-9), white); + SetHighColor(216,216,216); + } else { + AddLine(BPoint(counterX-24,SLIDER_BASE+1), BPoint(counterX+24,SLIDER_BASE+1), blue); + AddLine(BPoint(counterX+25,SLIDER_BASE+1), BPoint(counterX+25,SLIDER_BASE-9), blue2); + AddLine(BPoint(counterX-25,SLIDER_BASE+1), BPoint(counterX-25,SLIDER_BASE-9), blue2); + AddLine(BPoint(counterX-24,SLIDER_BASE-9), BPoint(counterX+24,SLIDER_BASE-9), blue2); + SetHighColor(48,48,241); + } + EndLineArray(); + FillRect(BRect(counterX-24,SLIDER_BASE-8,counterX+24,SLIDER_BASE)); + + SetDrawingMode(B_OP_COPY); + if (isTracking) + SetHighColor(255,255,255); + else + SetHighColor(0,0,0); + SetLowColor(ViewColor()); + + SetFont(&fFont); + char string[12]; + TimeToString(timestamp, string); + DrawString(string, BPoint(counterX-22, SLIDER_BASE-1)); + +} + + +void +TrackSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + if (!IsTracking()) + return; + + uint32 mouseButtons; + BPoint where; + GetMouse(&where, &mouseButtons, true); + + // button not pressed, exit + if (! (mouseButtons & B_PRIMARY_MOUSE_BUTTON)) { + Invoke(); + SetTracking(false); + } + + UpdatePosition(point); +} + + +void +TrackSlider::MouseDown(BPoint point) +{ + if (!Bounds().InsetBySelf(2,2).Contains(point)) + return; + + UpdatePosition(point); + SetTracking(true); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); +} + + +void +TrackSlider::MouseUp(BPoint point) +{ + if (!IsTracking()) + return; + if (Bounds().InsetBySelf(2,2).Contains(point)) { + UpdatePosition(point); + } + + fLeftTracking = fRightTracking = fMainTracking = false; + + Invoke(); + SetTracking(false); + Draw(Bounds()); + Flush(); +} + + +void +TrackSlider::UpdatePosition(BPoint point) +{ + BRect leftRect(fLeftX-9, SLIDER_BASE+3, fLeftX, SLIDER_BASE+16); + BRect rightRect(fRightX, SLIDER_BASE+3, fRightX+9, SLIDER_BASE+16); + + if (!(fRightTracking || fMainTracking) && (fLeftTracking || ((point.x < fPositionX-4) && leftRect.Contains(point)))) { + if (!IsTracking()) + fLastX = point.x - fLeftX; + fLeftX = MIN(MAX(point.x - fLastX, 15), fRight); + fLeftTime = (bigtime_t)(MAX(MIN((fLeftX - 15) / (fRight - 14),1), 0) * fTotalTime); + fLeftTracking = true; + + BMessage msg = *Message(); + msg.AddInt64("left", fLeftTime); + + if (fPositionX < fLeftX) { + fPositionX = fLeftX + 1; + fMainTime = fLeftTime; + msg.AddInt64("main", fMainTime); + if (fRightX < fPositionX) { + fRightX = fPositionX; + fRightTime = fMainTime; + msg.AddInt64("right", fRightTime); + } + } + + Invoke(&msg); + + //printf("fLeftPos : %Ld\n", fLeftTime); + } else if (!fMainTracking && (fRightTracking || ((point.x > fPositionX+4) && rightRect.Contains(point)))) { + if (!IsTracking()) + fLastX = point.x - fRightX; + fRightX = MIN(MAX(point.x - fLastX, 15), fRight); + fRightTime = (bigtime_t)(MAX(MIN((fRightX - 15) / (fRight - 14),1), 0) * fTotalTime); + fRightTracking = true; + + BMessage msg = *Message(); + msg.AddInt64("right", fRightTime); + + if (fPositionX > fRightX) { + fPositionX = fRightX; + fMainTime = fRightTime; + msg.AddInt64("main", fMainTime); + if (fLeftX > fPositionX) { + fLeftX = fPositionX - 1; + fLeftTime = fMainTime; + msg.AddInt64("left", fLeftTime); + } + } + + Invoke(&msg); + + //printf("fRightPos : %Ld\n", fRightTime); + } else { + fPositionX = MIN(MAX(point.x, 15), fRight); + fMainTime = (bigtime_t)(MAX(MIN((fPositionX - 15) / (fRight - 14),1), 0) * fTotalTime); + fMainTracking = true; + + BMessage msg = *Message(); + msg.AddInt64("main", fMainTime); + + if (fRightX < fPositionX) { + fRightX = fPositionX; + fRightTime = fMainTime; + msg.AddInt64("right", fRightTime); + } else if (fLeftX > fPositionX) { + fLeftX = fPositionX - 1; + fLeftTime = fMainTime; + msg.AddInt64("left", fLeftTime); + } + + Invoke(&msg); + //printf("fPosition : %Ld\n", fMainTime); + } + Draw(Bounds()); + Flush(); +} + + +void +TrackSlider::TimeToString(bigtime_t timestamp, char *string) +{ + uint32 hours = timestamp / 3600000000LL; + timestamp -= hours * 3600000000LL; + uint32 minutes = timestamp / 60000000LL; + timestamp -= minutes * 60000000LL; + uint32 seconds = timestamp / 1000000LL; + timestamp -= seconds * 1000000LL; + uint32 centiseconds = timestamp / 10000LL; + sprintf(string, "%02ld:%02ld:%02ld:%02ld", hours, minutes, seconds, centiseconds); + +} + + +void +TrackSlider::SetMainTime(bigtime_t timestamp, bool reset) +{ + fMainTime = timestamp; + fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); + if (reset) { + fRightTime = fTotalTime; + fLeftTime = 0; + fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); + fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); + } + Invalidate(); +} + +void +TrackSlider::SetTotalTime(bigtime_t timestamp, bool reset) +{ + fTotalTime = timestamp; + if (reset) { + fMainTime = 0; + fRightTime = fTotalTime; + fLeftTime = 0; + } + fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); + fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); + fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); + Invalidate(); +} + + +void +TrackSlider::ResetMainTime() +{ + fMainTime = fLeftTime; + fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); + Invalidate(); +} + + +void +TrackSlider::FrameResized(float width, float height) +{ + fRight = Bounds().right - kLeftRightTrackSliderWidth; + fPositionX = 15 + (fRight - 14) * ((double)fMainTime / fTotalTime); + fLeftX = 14 + (fRight - 15) * ((double)fLeftTime / fTotalTime); + fRightX = 15 + (fRight - 16) * ((double)fRightTime / fTotalTime); + Invalidate(); +} diff --git a/src/apps/soundrecorder/TrackSlider.h b/src/apps/soundrecorder/TrackSlider.h new file mode 100644 index 0000000000..be43902582 --- /dev/null +++ b/src/apps/soundrecorder/TrackSlider.h @@ -0,0 +1,54 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ +#ifndef TRACKSLIDER_H +#define TRACKSLIDER_H + +#include +#include +#include + +class TrackSlider : public BControl +{ +public: + TrackSlider(BRect rect, const char* title, BMessage *msg, uint32 resizeFlags); + ~TrackSlider(); + void AttachedToWindow(); + virtual void Draw(BRect); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void MouseUp(BPoint point); + virtual void MouseDown(BPoint point); + void SetMainTime(bigtime_t timestamp, bool reset); + void SetTotalTime(bigtime_t timestamp, bool reset); + bigtime_t * MainTime() { return &fMainTime; }; + bigtime_t RightTime() { return fRightTime; }; + bigtime_t LeftTime() { return fLeftTime; }; + void ResetMainTime(); + virtual void FrameResized(float width, float height); +private: + void DrawCounter(bigtime_t timestamp, float position, bool isTracking); + void TimeToString(bigtime_t timestamp, char *string); + void UpdatePosition(BPoint point); + BBitmap leftBitmap, rightBitmap, leftThumbBitmap, rightThumbBitmap; + float fRight; + + bigtime_t fLeftTime; + bigtime_t fRightTime; + bigtime_t fMainTime; + bigtime_t fTotalTime; + + float fPositionX; + float fLeftX; + float fRightX; + float fLastX; + bool fLeftTracking; + bool fRightTracking; + bool fMainTracking; + + BFont fFont; +}; + +#endif /* TRACKSLIDER_H */ diff --git a/src/apps/soundrecorder/TransportButton.cpp b/src/apps/soundrecorder/TransportButton.cpp new file mode 100644 index 0000000000..348ad2bb99 --- /dev/null +++ b/src/apps/soundrecorder/TransportButton.cpp @@ -0,0 +1,734 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include +#include +#include +#include + +#include + +#include "TransportButton.h" +#include "DrawingTidbits.h" + +class BitmapStash { +// Bitmap stash is a simple class to hold all the lazily-allocated +// bitmaps that the TransportButton needs when rendering itself. +// signature is a combination of the different enabled, pressed, playing, etc. +// flavors of a bitmap. If the stash does not have a particular bitmap, +// it turns around to ask the button to create one and stores it for next time. +public: + BitmapStash(TransportButton *); + ~BitmapStash(); + BBitmap *GetBitmap(uint32 signature); + +private: + TransportButton *owner; + map stash; +}; + + +BitmapStash::BitmapStash(TransportButton *owner) + : owner(owner) +{ +} + + +BBitmap * +BitmapStash::GetBitmap(uint32 signature) +{ + if (stash.find(signature) == stash.end()) { + BBitmap *newBits = owner->MakeBitmap(signature); + ASSERT(newBits); + stash[signature] = newBits; + } + + return stash[signature]; +} + + +BitmapStash::~BitmapStash() +{ + // delete all the bitmaps + for (map::iterator i = stash.begin(); i != stash.end(); i++) + delete (*i).second; +} + + +class PeriodicMessageSender { + // used to send a specified message repeatedly when holding down a button +public: + static PeriodicMessageSender *Launch(BMessenger target, + const BMessage *message, bigtime_t period); + void Quit(); + +private: + PeriodicMessageSender(BMessenger target, const BMessage *message, + bigtime_t period); + ~PeriodicMessageSender() {} + // use quit + + static status_t TrackBinder(void *); + void Run(); + + BMessenger target; + BMessage message; + + bigtime_t period; + + bool requestToQuit; +}; + + +PeriodicMessageSender::PeriodicMessageSender(BMessenger target, + const BMessage *message, bigtime_t period) + : target(target), + message(*message), + period(period), + requestToQuit(false) +{ +} + + +PeriodicMessageSender * +PeriodicMessageSender::Launch(BMessenger target, const BMessage *message, + bigtime_t period) +{ + PeriodicMessageSender *result = new PeriodicMessageSender(target, message, period); + thread_id thread = spawn_thread(&PeriodicMessageSender::TrackBinder, + "ButtonRepeatingThread", B_NORMAL_PRIORITY, result); + + if (thread <= 0 || resume_thread(thread) != B_OK) { + // didn't start, don't leak self + delete result; + result = 0; + } + + return result; +} + + +void +PeriodicMessageSender::Quit() +{ + requestToQuit = true; +} + + +status_t +PeriodicMessageSender::TrackBinder(void *castToThis) +{ + ((PeriodicMessageSender *)castToThis)->Run(); + return 0; +} + + +void +PeriodicMessageSender::Run() +{ + for (;;) { + snooze(period); + if (requestToQuit) + break; + target.SendMessage(&message); + } + delete this; +} + + +class SkipButtonKeypressFilter : public BMessageFilter { +public: + SkipButtonKeypressFilter(uint32 shortcutKey, uint32 shortcutModifier, + TransportButton *target); + +protected: + filter_result Filter(BMessage *message, BHandler **handler); + +private: + uint32 shortcutKey; + uint32 shortcutModifier; + TransportButton *target; +}; + + +SkipButtonKeypressFilter::SkipButtonKeypressFilter(uint32 shortcutKey, + uint32 shortcutModifier, TransportButton *target) + : BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE), + shortcutKey(shortcutKey), + shortcutModifier(shortcutModifier), + target(target) +{ +} + + +filter_result +SkipButtonKeypressFilter::Filter(BMessage *message, BHandler **handler) +{ + if (target->IsEnabled() + && (message->what == B_KEY_DOWN || message->what == B_KEY_UP)) { + uint32 modifiers; + uint32 rawKeyChar = 0; + uint8 byte = 0; + int32 key = 0; + + if (message->FindInt32("modifiers", (int32 *)&modifiers) != B_OK + || message->FindInt32("raw_char", (int32 *)&rawKeyChar) != B_OK + || message->FindInt8("byte", (int8 *)&byte) != B_OK + || message->FindInt32("key", &key) != B_OK) + return B_DISPATCH_MESSAGE; + + modifiers &= B_SHIFT_KEY | B_COMMAND_KEY | B_CONTROL_KEY + | B_OPTION_KEY | B_MENU_KEY; + // strip caps lock, etc. + + if (modifiers == shortcutModifier && rawKeyChar == shortcutKey) { + if (message->what == B_KEY_DOWN) + target->ShortcutKeyDown(); + else + target->ShortcutKeyUp(); + + return B_SKIP_MESSAGE; + } + } + + // let others deal with this + return B_DISPATCH_MESSAGE; +} + + +TransportButton::TransportButton(BRect frame, const char *name, + const unsigned char *normalBits, + const unsigned char *pressedBits, + const unsigned char *disabledBits, + BMessage *invokeMessage, BMessage *startPressingMessage, + BMessage *pressingMessage, BMessage *donePressingMessage, bigtime_t period, + uint32 key, uint32 modifiers, uint32 resizeFlags) + : BControl(frame, name, "", invokeMessage, resizeFlags, B_WILL_DRAW | B_NAVIGABLE), + bitmaps(new BitmapStash(this)), + normalBits(normalBits), + pressedBits(pressedBits), + disabledBits(disabledBits), + startPressingMessage(startPressingMessage), + pressingMessage(pressingMessage), + donePressingMessage(donePressingMessage), + pressingPeriod(period), + mouseDown(false), + keyDown(false), + messageSender(0), + keyPressFilter(0) +{ + if (key) + keyPressFilter = new SkipButtonKeypressFilter(key, modifiers, this); +} + + +void +TransportButton::AttachedToWindow() +{ + _inherited::AttachedToWindow(); + if (keyPressFilter) + Window()->AddCommonFilter(keyPressFilter); + + // transparent to reduce flicker + SetViewColor(B_TRANSPARENT_COLOR); +} + + +void +TransportButton::DetachedFromWindow() +{ + if (keyPressFilter) { + Window()->RemoveCommonFilter(keyPressFilter); + delete keyPressFilter; + } + _inherited::DetachedFromWindow(); +} + + +TransportButton::~TransportButton() +{ + delete startPressingMessage; + delete pressingMessage; + delete donePressingMessage; + delete bitmaps; +} + + +void +TransportButton::WindowActivated(bool state) +{ + if (!state) + ShortcutKeyUp(); + + _inherited::WindowActivated(state); +} + + +void +TransportButton::SetEnabled(bool on) +{ + _inherited::SetEnabled(on); + if (!on) + ShortcutKeyUp(); +} + + +const unsigned char * +TransportButton::BitsForMask(uint32 mask) const +{ + switch (mask) { + case 0: + return normalBits; + case kDisabledMask: + return disabledBits; + case kPressedMask: + return pressedBits; + default: + break; + } + TRESPASS(); + return 0; +} + + +BBitmap * +TransportButton::MakeBitmap(uint32 mask) +{ + BBitmap *result = new BBitmap(Bounds(), B_COLOR_8_BIT); + result->SetBits(BitsForMask(mask), (Bounds().Width() + 1) * (Bounds().Height() + 1), + 0, B_COLOR_8_BIT); + + ReplaceTransparentColor(result, Parent()->ViewColor()); + + return result; +} + + +uint32 +TransportButton::ModeMask() const +{ + return (IsEnabled() ? 0 : kDisabledMask) + | (Value() ? kPressedMask : 0); +} + + +void +TransportButton::Draw(BRect) +{ + DrawBitmapAsync(bitmaps->GetBitmap(ModeMask())); +} + + +void +TransportButton::StartPressing() +{ + SetValue(1); + if (startPressingMessage) + Invoke(startPressingMessage); + + if (pressingMessage) { + ASSERT(pressingMessage); + messageSender = PeriodicMessageSender::Launch(Messenger(), + pressingMessage, pressingPeriod); + } +} + + +void +TransportButton::MouseCancelPressing() +{ + if (!mouseDown || keyDown) + return; + + mouseDown = false; + + if (pressingMessage) { + ASSERT(messageSender); + PeriodicMessageSender *sender = messageSender; + messageSender = 0; + sender->Quit(); + } + + if (donePressingMessage) + Invoke(donePressingMessage); + SetValue(0); +} + + +void +TransportButton::DonePressing() +{ + if (pressingMessage) { + ASSERT(messageSender); + PeriodicMessageSender *sender = messageSender; + messageSender = 0; + sender->Quit(); + } + + Invoke(); + SetValue(0); +} + + +void +TransportButton::MouseStartPressing() +{ + if (mouseDown) + return; + + mouseDown = true; + if (!keyDown) + StartPressing(); +} + + +void +TransportButton::MouseDonePressing() +{ + if (!mouseDown) + return; + + mouseDown = false; + if (!keyDown) + DonePressing(); +} + + +void +TransportButton::ShortcutKeyDown() +{ + if (!IsEnabled()) + return; + + if (keyDown) + return; + + keyDown = true; + if (!mouseDown) + StartPressing(); +} + + +void +TransportButton::ShortcutKeyUp() +{ + if (!keyDown) + return; + + keyDown = false; + if (!mouseDown) + DonePressing(); +} + + +void +TransportButton::MouseDown(BPoint) +{ + if (!IsEnabled()) + return; + + ASSERT(Window()->Flags() & B_ASYNCHRONOUS_CONTROLS); + SetTracking(true); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + MouseStartPressing(); +} + +void +TransportButton::MouseMoved(BPoint point, uint32 code, const BMessage *) +{ + if (IsTracking() && Bounds().Contains(point) != Value()) { + if (!Value()) + MouseStartPressing(); + else + MouseCancelPressing(); + } +} + +void +TransportButton::MouseUp(BPoint point) +{ + if (IsTracking()) { + if (Bounds().Contains(point)) + MouseDonePressing(); + else + MouseCancelPressing(); + SetTracking(false); + } +} + +void +TransportButton::SetStartPressingMessage(BMessage *message) +{ + delete startPressingMessage; + startPressingMessage = message; +} + +void +TransportButton::SetPressingMessage(BMessage *message) +{ + delete pressingMessage; + pressingMessage = message; +} + +void +TransportButton::SetDonePressingMessage(BMessage *message) +{ + delete donePressingMessage; + donePressingMessage = message; +} + +void +TransportButton::SetPressingPeriod(bigtime_t newTime) +{ + pressingPeriod = newTime; +} + + +PlayPauseButton::PlayPauseButton(BRect frame, const char *name, + BMessage *invokeMessage, BMessage *blinkMessage, + uint32 key, uint32 modifiers, uint32 resizeFlags) + : TransportButton(frame, name, kPlayButtonBitmapBits, kPressedPlayButtonBitmapBits, + kDisabledPlayButtonBitmapBits, invokeMessage, NULL, + NULL, NULL, 0, key, modifiers, resizeFlags), + fState(PlayPauseButton::kStopped), + fLastModeMask(0), + fRunner(NULL), + fBlinkMessage(blinkMessage) +{ +} + +void +PlayPauseButton::SetStopped() +{ + if (fState == kStopped || fState == kAboutToPlay) + return; + + fState = kStopped; + delete fRunner; + fRunner = NULL; + Invalidate(); +} + +void +PlayPauseButton::SetPlaying() +{ + if (fState == kAboutToPause) + return; + + // in playing state blink the LED on and off + if (fState == kPlayingLedOn) + fState = kPlayingLedOff; + else + fState = kPlayingLedOn; + + Invalidate(); +} + +const bigtime_t kPlayingBlinkPeriod = 600000; + +void +PlayPauseButton::SetPaused() +{ + if (fState == kAboutToPlay) + return; + + // in paused state blink the LED on and off + if (fState == kPausedLedOn) + fState = kPausedLedOff; + else + fState = kPausedLedOn; + + Invalidate(); +} + +uint32 +PlayPauseButton::ModeMask() const +{ + if (!IsEnabled()) + return kDisabledMask; + + uint32 result = 0; + + if (Value()) + result = kPressedMask; + + if (fState == kPlayingLedOn || fState == kAboutToPlay) + result |= kPlayingMask; + else if (fState == kAboutToPause || fState == kPausedLedOn) + result |= kPausedMask; + + return result; +} + +const unsigned char * +PlayPauseButton::BitsForMask(uint32 mask) const +{ + switch (mask) { + case kPlayingMask: + return kPlayingPlayButtonBitmapBits; + case kPlayingMask | kPressedMask: + return kPressedPlayingPlayButtonBitmapBits; + case kPausedMask: + return kPausedPlayButtonBitmapBits; + case kPausedMask | kPressedMask: + return kPressedPausedPlayButtonBitmapBits; + default: + return _inherited::BitsForMask(mask); + } + TRESPASS(); + return 0; +} + + +void +PlayPauseButton::StartPressing() +{ + if (fState == kPlayingLedOn || fState == kPlayingLedOff) + fState = kAboutToPause; + else + fState = kAboutToPlay; + + _inherited::StartPressing(); +} + +void +PlayPauseButton::MouseCancelPressing() +{ + if (fState == kAboutToPause) + fState = kPlayingLedOn; + else + fState = kStopped; + + _inherited::MouseCancelPressing(); +} + +void +PlayPauseButton::DonePressing() +{ + if (fState == kAboutToPause) { + fState = kPausedLedOn; + } else if (fState == kAboutToPlay) { + fState = kPlayingLedOn; + if (!fRunner && fBlinkMessage) + fRunner = new BMessageRunner(Messenger(), fBlinkMessage, kPlayingBlinkPeriod); + } + + _inherited::DonePressing(); +} + + +RecordButton::RecordButton(BRect frame, const char *name, + BMessage *invokeMessage, BMessage *blinkMessage, + uint32 key, uint32 modifiers, uint32 resizeFlags) + : TransportButton(frame, name, kRecordButtonBitmapBits, kPressedRecordButtonBitmapBits, + kDisabledRecordButtonBitmapBits, invokeMessage, NULL, NULL, + NULL, 0, key, modifiers, resizeFlags), + fState(RecordButton::kStopped), + fLastModeMask(0), + fRunner(NULL), + fBlinkMessage(blinkMessage) +{ +} + +void +RecordButton::SetStopped() +{ + if (fState == kStopped || fState == kAboutToRecord) + return; + + fState = kStopped; + delete fRunner; + fRunner = NULL; + Invalidate(); +} + +const bigtime_t kRecordingBlinkPeriod = 600000; + +void +RecordButton::SetRecording() +{ + if (fState == kAboutToStop) + return; + + if (fState == kRecordingLedOff) + fState = kRecordingLedOn; + else + fState = kRecordingLedOff; + + Invalidate(); +} + +uint32 +RecordButton::ModeMask() const +{ + if (!IsEnabled()) + return kDisabledMask; + + uint32 result = 0; + + if (Value()) + result = kPressedMask; + + if (fState == kAboutToStop || fState == kRecordingLedOn) + result |= kRecordingMask; + + return result; +} + +const unsigned char * +RecordButton::BitsForMask(uint32 mask) const +{ + switch (mask) { + case kRecordingMask: + return kRecordingRecordButtonBitmapBits; + case kRecordingMask | kPressedMask: + return kPressedRecordingRecordButtonBitmapBits; + default: + return _inherited::BitsForMask(mask); + } + TRESPASS(); + return 0; +} + + +void +RecordButton::StartPressing() +{ + if (fState == kRecordingLedOn || fState == kRecordingLedOff) + fState = kAboutToStop; + else + fState = kAboutToRecord; + + _inherited::StartPressing(); +} + +void +RecordButton::MouseCancelPressing() +{ + if (fState == kAboutToStop) + fState = kRecordingLedOn; + else + fState = kStopped; + + _inherited::MouseCancelPressing(); +} + +void +RecordButton::DonePressing() +{ + if (fState == kAboutToStop) { + fState = kStopped; + delete fRunner; + fRunner = NULL; + } else if (fState == kAboutToRecord) { + fState = kRecordingLedOn; + if (!fRunner && fBlinkMessage) + fRunner = new BMessageRunner(Messenger(), fBlinkMessage, kRecordingBlinkPeriod); + } + + _inherited::DonePressing(); +} diff --git a/src/apps/soundrecorder/TransportButton.h b/src/apps/soundrecorder/TransportButton.h new file mode 100644 index 0000000000..993f5879cc --- /dev/null +++ b/src/apps/soundrecorder/TransportButton.h @@ -0,0 +1,212 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef __MEDIA_BUTTON__ +#define __MEDIA_BUTTON__ + +#include +#include +#include "icon_button.h" + +class BMessage; +class BBitmap; +class PeriodicMessageSender; +class BitmapStash; + +// TransportButton must be installed into a window with B_ASYNCHRONOUS_CONTROLS on +// currently no button focus drawing + +class TransportButton : public BControl { +public: + + TransportButton(BRect frame, const char *name, + const unsigned char *normalBits, + const unsigned char *pressedBits, + const unsigned char *disabledBits, + BMessage *invokeMessage, // done pressing over button + BMessage *startPressingMessage = 0, // just clicked button + BMessage *pressingMessage = 0, // periodical still pressing + BMessage *donePressing = 0, // tracked out of button/didn't invoke + bigtime_t period = 0, // pressing message period + uint32 key = 0, // optional shortcut key + uint32 modifiers = 0, // optional shortcut key modifier + uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP); + + virtual ~TransportButton(); + + void SetStartPressingMessage(BMessage *); + void SetPressingMessage(BMessage *); + void SetDonePressingMessage(BMessage *); + void SetPressingPeriod(bigtime_t); + + virtual void SetEnabled(bool); + +protected: + + enum { + kDisabledMask = 0x1, + kPressedMask = 0x2 + }; + + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void Draw(BRect); + virtual void MouseDown(BPoint); + virtual void MouseMoved(BPoint, uint32 code, const BMessage *); + virtual void MouseUp(BPoint); + virtual void WindowActivated(bool); + + virtual BBitmap *MakeBitmap(uint32); + // lazy bitmap builder + + virtual uint32 ModeMask() const; + // mode mask corresponding to the current button state + // - determines which bitmap will be used + virtual const unsigned char *BitsForMask(uint32) const; + // pick the right bits based on a mode mask + + // overriding class can add swapping between two pairs of bitmaps, etc. + virtual void StartPressing(); + virtual void MouseCancelPressing(); + virtual void DonePressing(); + +private: + void ShortcutKeyDown(); + void ShortcutKeyUp(); + + void MouseStartPressing(); + void MouseDonePressing(); + + BitmapStash *bitmaps; + // using BitmapStash * here instead of a direct member so that the class can be private in + // the .cpp file + + // bitmap bits used to build bitmaps for the different states + const unsigned char *normalBits; + const unsigned char *pressedBits; + const unsigned char *disabledBits; + + BMessage *startPressingMessage; + BMessage *pressingMessage; + BMessage *donePressingMessage; + bigtime_t pressingPeriod; + + bool mouseDown; + bool keyDown; + PeriodicMessageSender *messageSender; + BMessageFilter *keyPressFilter; + + typedef BControl _inherited; + + friend class SkipButtonKeypressFilter; + friend class BitmapStash; +}; + +class PlayPauseButton : public TransportButton { +// Knows about playing and paused states, blinks +// the pause LED during paused state +public: + PlayPauseButton(BRect frame, const char *name, + BMessage *invokeMessage, // done pressing over button + BMessage *blinkMessage = 0, // blinking + uint32 key = 0, // optional shortcut key + uint32 modifiers = 0, // optional shortcut key modifier + uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP); + + // These need get called periodically to update the button state + // OK to call them over and over - once the state is correct, the call + // is very low overhead + void SetStopped(); + void SetPlaying(); + void SetPaused(); + +protected: + + virtual uint32 ModeMask() const; + virtual const unsigned char *BitsForMask(uint32) const; + + virtual void StartPressing(); + virtual void MouseCancelPressing(); + virtual void DonePressing(); + +private: + enum PlayState { + kStopped, + kAboutToPlay, + kPlayingLedOn, + kPlayingLedOff, + kAboutToPause, + kPausedLedOn, + kPausedLedOff + }; + + enum { + kPlayingMask = 0x4, + kPausedMask = 0x8 + }; + + PlayState fState; + uint32 fLastModeMask; + BMessageRunner *fRunner; + BMessage *fBlinkMessage; + + typedef TransportButton _inherited; +}; + + +class RecordButton : public TransportButton { +// Knows about recording states, blinks +// the recording LED during recording state +public: + RecordButton(BRect frame, const char *name, + BMessage *invokeMessage, // done pressing over button + BMessage *blinkMessage = 0, // blinking + uint32 key = 0, // optional shortcut key + uint32 modifiers = 0, // optional shortcut key modifier + uint32 resizeFlags = B_FOLLOW_LEFT | B_FOLLOW_TOP); + + // These need get called periodically to update the button state + // OK to call them over and over - once the state is correct, the call + // is very low overhead + void SetStopped(); + void SetRecording(); + +protected: + + virtual uint32 ModeMask() const; + virtual const unsigned char *BitsForMask(uint32) const; + + virtual void StartPressing(); + virtual void MouseCancelPressing(); + virtual void DonePressing(); + +private: + enum RecordState { + kAboutToStop, + kStopped, + kAboutToRecord, + kRecordingLedOn, + kRecordingLedOff + }; + + enum { + kRecordingMask = 0x4 + }; + + enum { + RECORD_PRESSING = 'crpr' + }; + + RecordState fState; + uint32 fLastModeMask; + BMessageRunner *fRunner; + BMessage *fBlinkMessage; + + typedef TransportButton _inherited; +}; + +#endif diff --git a/src/apps/soundrecorder/UpDownButton.cpp b/src/apps/soundrecorder/UpDownButton.cpp new file mode 100644 index 0000000000..2819a0f09d --- /dev/null +++ b/src/apps/soundrecorder/UpDownButton.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ +#include "UpDownButton.h" +#include "icon_button.h" + +UpDownButton::UpDownButton(BRect rect, BMessage *msg, uint32 resizeFlags) + : BControl(rect, "button", NULL, msg, resizeFlags, B_WILL_DRAW), + fLastValue(B_CONTROL_ON) +{ + BRect rect = BRect(0, 0, kUpDownButtonWidth - 1, kUpDownButtonHeight - 1); + fBitmapUp = new BBitmap(rect, B_CMAP8); + fBitmapUp->SetBits(kButtonUpBits, kUpDownButtonWidth * kUpDownButtonHeight, 0, B_CMAP8); + fBitmapDown = new BBitmap(rect, B_CMAP8); + fBitmapDown->SetBits(kButtonDownBits, kUpDownButtonWidth * kUpDownButtonHeight, 0, B_CMAP8); + fBitmapMiddle = new BBitmap(rect, B_CMAP8); + fBitmapMiddle->SetBits(kButtonMiddleBits, kUpDownButtonWidth * kUpDownButtonHeight, 0, B_CMAP8); +} + + +UpDownButton::~UpDownButton() +{ + delete fBitmapUp; + delete fBitmapDown; + delete fBitmapMiddle; +} + + +void +UpDownButton::Draw(BRect updateRect) +{ + SetDrawingMode(B_OP_OVER); + + if(IsTracking()) { + if((Bounds().top + Bounds().Height()/2) > (fTrackingY + 3)) + DrawBitmap(fBitmapUp); + else if((Bounds().top + Bounds().Height()/2) < (fTrackingY - 3)) + DrawBitmap(fBitmapDown); + else + DrawBitmap(fBitmapMiddle); + } else { + if(Value()==B_CONTROL_OFF) + DrawBitmap(fBitmapUp); + else + DrawBitmap(fBitmapDown); + } + + SetDrawingMode(B_OP_COPY); +} + + +void +UpDownButton::MouseDown(BPoint point) +{ + if(!IsEnabled()) + return; + + fLastValue = Value(); + fTrackingY = (Bounds().top + Bounds().Height()/2); + + SetTracking(true); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + + SetValue(Value() == B_CONTROL_ON ? B_CONTROL_OFF : B_CONTROL_ON); +} + + +void +UpDownButton::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + if (!IsTracking()) + return; + + fTrackingY = point.y; + Draw(Bounds()); + Flush(); +} + + +void +UpDownButton::MouseUp(BPoint point) +{ + if (!IsTracking()) + return; + + if((Bounds().top + Bounds().Height()/2) > (fTrackingY + 3)) + SetValue(B_CONTROL_ON); + else if((Bounds().top + Bounds().Height()/2) < (fTrackingY - 3)) + SetValue(B_CONTROL_OFF); + + if(Value()!=fLastValue) + Invoke(); + SetTracking(false); + Draw(Bounds()); + Flush(); + fLastValue = Value(); +} diff --git a/src/apps/soundrecorder/UpDownButton.h b/src/apps/soundrecorder/UpDownButton.h new file mode 100644 index 0000000000..00c534d0f3 --- /dev/null +++ b/src/apps/soundrecorder/UpDownButton.h @@ -0,0 +1,31 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ +#ifndef UPDOWNBUTTON_H +#define UPDOWNBUTTON_H + +#include +#include + +#define DRAG_ITEM 'dndi' + +class UpDownButton : public BControl +{ +public: + UpDownButton(BRect rect, BMessage *msg, uint32 resizeFlags = 0); + ~UpDownButton(); + virtual void Draw(BRect); + virtual void MouseDown(BPoint point); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void MouseUp(BPoint point); + +private: + BBitmap *fBitmapUp, *fBitmapDown, *fBitmapMiddle; + float fTrackingY; + int32 fLastValue; +}; + +#endif diff --git a/src/apps/soundrecorder/VUView.cpp b/src/apps/soundrecorder/VUView.cpp new file mode 100644 index 0000000000..b7446a5a03 --- /dev/null +++ b/src/apps/soundrecorder/VUView.cpp @@ -0,0 +1,194 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include +#include +#include +#include +#include "DrawingTidbits.h" +#include "VUView.h" + +const rgb_color back_color = {12, 36, 12}; +const rgb_color low_color = {40, 120, 40}; +const rgb_color high_color = {240, 255, 240}; + +VUView::VUView(BRect rect, uint32 resizeFlags) + : BView(rect, "vumeter", resizeFlags, B_WILL_DRAW), + fThreadId(-1), + fBitmap(NULL), + fQuitting(false) +{ + fLevelCount = int(rect.Height()) / 2; + fChannels = 2; + fCurrentLevels = new int32[fChannels]; + for (int channel=0; channel < fChannels; channel++) + fCurrentLevels[channel] = 0; + fBitmap = new BBitmap(rect, BScreen().ColorSpace(), true); + + + memset(fBitmap->Bits(), 0, fBitmap->BitsLength()); + + fBitmapView = new BView(rect, "bitmapView", B_FOLLOW_LEFT|B_FOLLOW_TOP, B_WILL_DRAW); + fBitmap->AddChild(fBitmapView); +} + + +VUView::~VUView() +{ + +} + + +void +VUView::AttachedToWindow() +{ + SetViewColor(B_TRANSPARENT_COLOR); + Run(); +} + + +void +VUView::DetachedFromWindow() +{ + Quit(); +} + + +void +VUView::Draw(BRect updateRect) +{ + DrawBitmap(fBitmap); + + Sync(); +} + + +void +VUView::Run() +{ + fThreadId = spawn_thread(&RenderLaunch, "VU view", B_NORMAL_PRIORITY, this); + if (fThreadId < 0) + return; + resume_thread(fThreadId); +} + +void +VUView::Quit() +{ + fQuitting = true; + snooze(10000); + kill_thread(fThreadId); +} + + + +int32 +VUView::RenderLaunch(void *data) +{ + VUView *vu = (VUView*) data; + vu->RenderLoop(); + return B_OK; +} + + +#define SHIFT_UNTIL(value,shift,min) value = (value - shift > min) ? (value - shift) : min + +void +VUView::RenderLoop() +{ + rgb_color levels[fLevelCount][2]; + + for (int32 i=0; i= 90) { + SHIFT_UNTIL(levels[i][channel].red, 15, low_color.red); + SHIFT_UNTIL(levels[i][channel].blue, 15, low_color.blue); + } else { + SHIFT_UNTIL(levels[i][channel].red, 7, low_color.red); + SHIFT_UNTIL(levels[i][channel].blue, 7, low_color.blue); + SHIFT_UNTIL(levels[i][channel].green, 14, low_color.green); + } + } + + levels[level][channel] = high_color; + + for (int32 i=level+1; i= 85) { + SHIFT_UNTIL(levels[i][channel].red, 15, back_color.red); + SHIFT_UNTIL(levels[i][channel].blue, 15, back_color.blue); + } else { + SHIFT_UNTIL(levels[i][channel].red, 7, back_color.red); + SHIFT_UNTIL(levels[i][channel].blue, 7, back_color.blue); + SHIFT_UNTIL(levels[i][channel].green, 14, back_color.green); + } + } + } + + /* rendering */ + fBitmap->Lock(); + fBitmapView->BeginLineArray(fLevelCount * 2); + BPoint start1, end1, start2, end2; + start1.x = 1; + start2.x = 20; + end1.x = 14; + end2.x = 33; + start1.y = end1.y = start2.y = end2.y = 2; + for (int32 i=fLevelCount-1; i>=0; i--) { + fBitmapView->AddLine(start1, end1, levels[i][0]); + fBitmapView->AddLine(start2, end2, levels[i][1]); + start1.y = end1.y = start2.y = end2.y = end2.y + 2; + } + fBitmapView->EndLineArray(); + fBitmap->Unlock(); + + /* ask drawing */ + + if (Window()->LockWithTimeout(5000) == B_OK) { + Invalidate(); + Window()->Unlock(); + snooze(50000); + } + } +} + + +void +VUView::ComputeNextLevel(void *data, size_t size) +{ + int16* samp = (int16*)data; + + for (int32 channel = 0; channel < fChannels; channel++) { + + // get the min and max values in the nibbling interval + // and set max to be the greater of the absolute value + // of these. + + int mi = 0, ma = 0; + for (uint32 ix=channel; ix samp[ix]) mi = samp[ix]; + else if (ma < samp[ix]) ma = samp[ix]; + } + if (-ma > mi) ma = (mi == -32768) ? 32767 : -mi; + + uint8 n = ma / (2 << (16-7)); + + fCurrentLevels[channel] = n; + if (fCurrentLevels[channel] < 0) + fCurrentLevels[channel] = 0; + } + +} diff --git a/src/apps/soundrecorder/VUView.h b/src/apps/soundrecorder/VUView.h new file mode 100644 index 0000000000..bf6a70298f --- /dev/null +++ b/src/apps/soundrecorder/VUView.h @@ -0,0 +1,40 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#ifndef VUVIEW_H +#define VUVIEW_H + +#include +#include + + +class VUView : public BView +{ +public: + VUView(BRect rect, uint32 resizeFlags); + ~VUView(); + void AttachedToWindow(); + void DetachedFromWindow(); + void Draw(BRect updateRect); + void ComputeNextLevel(void *data, size_t size); + +private: + void Run(); + void Quit(); + static int32 RenderLaunch(void *data); + void RenderLoop(); + + thread_id fThreadId; + BBitmap *fBitmap; + BView *fBitmapView; + bool fQuitting; + int32 fLevelCount; + int32 *fCurrentLevels; + int32 fChannels; +}; + +#endif /* VUVIEW_H */ diff --git a/src/apps/soundrecorder/VolumeSlider.cpp b/src/apps/soundrecorder/VolumeSlider.cpp new file mode 100644 index 0000000000..6627b759d6 --- /dev/null +++ b/src/apps/soundrecorder/VolumeSlider.cpp @@ -0,0 +1,176 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +#include + +#include "VolumeSlider.h" +#include "icon_button.h" + +#define VOLUME_CHANGED 'vlcg' +#define RATIO 2.0f + +VolumeSlider::VolumeSlider(BRect rect, const char *title, uint32 resizeFlags) + : BControl(rect, "slider", NULL, new BMessage(VOLUME_CHANGED), resizeFlags, B_WILL_DRAW), + fLeftBitmap(BRect(0, 0, kLeftVolumeWidth - 1, kLeftVolumeHeight - 1), B_CMAP8), + fRightBitmap(BRect(0, 0, kRightVolumeWidth - 1, kRightVolumeHeight - 1), B_CMAP8), + fButtonBitmap(BRect(0, 0, kThumbWidth - 1, kThumbHeight - 1), B_CMAP8), + fSoundPlayer(NULL) +{ + fLeftBitmap.SetBits(kLeftVolumeBits, kLeftVolumeWidth * kLeftVolumeHeight, 0, B_CMAP8); + fRightBitmap.SetBits(kRightVolumeBits, kRightVolumeWidth * kRightVolumeHeight, 0, B_CMAP8); + fButtonBitmap.SetBits(kThumbBits, kThumbWidth * kThumbHeight, 0, B_CMAP8); + + fRight = Bounds().right - 15; +} + + +VolumeSlider::~VolumeSlider() +{ + +} + + +void +VolumeSlider::Draw(BRect updateRect) +{ + SetHighColor(189,186,189); + StrokeLine(BPoint(11,1), BPoint(fRight,1)); + SetHighColor(0,0,0); + StrokeLine(BPoint(11,2), BPoint(fRight,2)); + SetHighColor(255,255,255); + StrokeLine(BPoint(11,14), BPoint(fRight,14)); + SetHighColor(231,227,231); + StrokeLine(BPoint(11,15), BPoint(fRight,15)); + + SetLowColor(ViewColor()); + + SetDrawingMode(B_OP_OVER); + + DrawBitmapAsync(&fLeftBitmap, BPoint(5,1)); + DrawBitmapAsync(&fRightBitmap, BPoint(fRight + 1,1)); + + float position = 11 + (fRight - 11) * (fSoundPlayer ? fSoundPlayer->Volume() / RATIO : 0); + SetHighColor(102,152,102); + FillRect(BRect(11,3,position,4)); + SetHighColor(152,203,152); + FillRect(BRect(11,5,position,13)); + + if (fSoundPlayer) + SetHighColor(152,152,152); + else + SetHighColor(200,200,200); + FillRect(BRect(position,3,fRight,13)); + + SetHighColor(102,152,102); + for (int i=15; i<=fRight + 1; i+=5) { + if (i>position) + SetHighColor(128,128,128); + StrokeLine(BPoint(i,8), BPoint(i,9)); + } + + DrawBitmapAsync(&fButtonBitmap, BPoint(position-5,3)); + + Sync(); + + SetDrawingMode(B_OP_COPY); +} + + +void +VolumeSlider::MouseMoved(BPoint point, uint32 transit, const BMessage *message) +{ + if (!IsTracking()) + return; + + uint32 mouseButtons; + BPoint where; + GetMouse(&where, &mouseButtons, true); + + // button not pressed, exit + if (! (mouseButtons & B_PRIMARY_MOUSE_BUTTON)) { + Invoke(); + SetTracking(false); + } + + if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point)) + return; + + UpdateVolume(point); +} + + +void +VolumeSlider::MouseDown(BPoint point) +{ + if (!fSoundPlayer || !Bounds().InsetBySelf(2,2).Contains(point)) + return; + + UpdateVolume(point); + SetTracking(true); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); +} + + +void +VolumeSlider::MouseUp(BPoint point) +{ + if (!IsTracking()) + return; + if (fSoundPlayer && Bounds().InsetBySelf(2,2).Contains(point)) { + UpdateVolume(point); + } + + Invoke(); + SetTracking(false); + Draw(Bounds()); + Flush(); +} + + +void +VolumeSlider::UpdateVolume(BPoint point) +{ + fVolume = MIN(MAX(point.x, 11), fRight); + fVolume = (fVolume - 11) / (fRight - 11); + fVolume = MAX(MIN(fVolume,1), 0); + Draw(Bounds()); + Flush(); + if (fSoundPlayer) + fSoundPlayer->SetVolume(fVolume * RATIO); +} + +void +VolumeSlider::SetSoundPlayer(BSoundPlayer *player) +{ + fSoundPlayer = player; + Invalidate(); +} + + +SpeakerView::SpeakerView(BRect rect, uint32 resizeFlags) + : BBox(rect, "speaker", resizeFlags, B_WILL_DRAW, B_NO_BORDER), + fSpeakerBitmap(BRect(0, 0, kSpeakerIconBitmapWidth - 1, kSpeakerIconBitmapHeight - 1), B_CMAP8) +{ + fSpeakerBitmap.SetBits(kSpeakerIconBits, kSpeakerIconBitmapWidth * kSpeakerIconBitmapHeight, 0, B_CMAP8); +} + + +SpeakerView::~SpeakerView() +{ + +} + + +void +SpeakerView::Draw(BRect updateRect) +{ + SetDrawingMode(B_OP_OVER); + + DrawBitmap(&fSpeakerBitmap); + + SetDrawingMode(B_OP_COPY); +} diff --git a/src/apps/soundrecorder/VolumeSlider.h b/src/apps/soundrecorder/VolumeSlider.h new file mode 100644 index 0000000000..132890a732 --- /dev/null +++ b/src/apps/soundrecorder/VolumeSlider.h @@ -0,0 +1,44 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ +#ifndef VOLUMESLIDER_H +#define VOLUMESLIDER_H + +#include +#include +#include +#include + +class VolumeSlider : public BControl +{ +public: + VolumeSlider(BRect rect, const char* title, uint32 resizeFlags); + ~VolumeSlider(); + virtual void Draw(BRect); + virtual void MouseMoved(BPoint point, uint32 transit, const BMessage *message); + virtual void MouseUp(BPoint point); + virtual void MouseDown(BPoint point); + void SetSoundPlayer(BSoundPlayer *player); +private: + void UpdateVolume(BPoint point); + BBitmap fLeftBitmap, fRightBitmap, fButtonBitmap; + float fRight; + float fVolume; + BSoundPlayer *fSoundPlayer; +}; + +class SpeakerView : public BBox +{ +public: + SpeakerView(BRect rect, uint32 resizeFlags); + ~SpeakerView(); + void Draw(BRect updateRect); + +private: + BBitmap fSpeakerBitmap; +}; + +#endif diff --git a/src/apps/soundrecorder/array_delete.h b/src/apps/soundrecorder/array_delete.h new file mode 100644 index 0000000000..9568203399 --- /dev/null +++ b/src/apps/soundrecorder/array_delete.h @@ -0,0 +1,30 @@ +/******************************************************************************* +/ +/ File: array_delete.h +/ +/ Description: Template for deleting a new[] array of something. +/ +/ Copyright 1998-1999, Be Incorporated, All Rights Reserved +/ +*******************************************************************************/ + + +#if !defined( _array_delete_h ) +#define _array_delete_h + +// Oooh! It's a template! +template class array_delete { + C * & m_ptr; +public: + // auto_ptr<> uses delete, not delete[], so we have to write our own. + // I like hanging on to a reference, because if we manually delete the + // array and set the pointer to NULL (or otherwise change the pointer) + // it will still work. Others like the more elaborate implementation + // of auto_ptr<>. Your Mileage May Vary. + array_delete(C * & ptr) : m_ptr(ptr) {} + ~array_delete() { delete[] m_ptr; } +}; + + +#endif /* array_delete_h */ + diff --git a/src/apps/soundrecorder/icon_button.h b/src/apps/soundrecorder/icon_button.h new file mode 100644 index 0000000000..2a73d3bb25 --- /dev/null +++ b/src/apps/soundrecorder/icon_button.h @@ -0,0 +1,2061 @@ +/* + * Copyright 2005, Jérôme Duval. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Inspired by SoundCapture from Be newsletter (Media Kit Basics: Consumers and Producers) + */ + +const int32 kUpDownButtonWidth = 16; +const int32 kUpDownButtonHeight = 22; +const color_space kUpDownButtonColorSpace = B_CMAP8; +const BPoint kUpDownButtonSize(kUpDownButtonWidth - 1, kUpDownButtonHeight - 1); + +const unsigned char kButtonUpBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x18,0x16,0x14,0x14,0x16,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x18,0x13,0x0d,0x09,0x08,0x09,0x0c,0x10,0x16,0x19,0x1a,0xff,0xff, + 0xff,0xff,0x18,0x11,0x09,0x0d,0x19,0x1b,0x1e,0x1a,0x17,0x10,0x16,0xff,0xff,0xff, + 0xff,0x1a,0x13,0x09,0x13,0x1b,0x1e,0x1d,0x1d,0x1c,0x1b,0x17,0x13,0x18,0x1c,0xff, + 0xff,0x17,0x0d,0x0d,0x1b,0x1d,0x1d,0x1d,0x1c,0x1b,0x1a,0x18,0x16,0x16,0xff,0xff, + 0xff,0x16,0x09,0x16,0x1d,0x1d,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x16,0x13,0x1a,0xff, + 0xff,0x14,0x08,0x1a,0x1c,0x1c,0x1b,0x1b,0x1b,0x1a,0x19,0x18,0x16,0x13,0x19,0xff, + 0xff,0x14,0x08,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x16,0x14,0x12,0x19,0xff, + 0xff,0x14,0x0a,0x17,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x14,0x13,0x11,0x19,0xff, + 0xff,0x14,0x08,0x13,0x17,0x17,0x17,0x17,0x17,0x16,0x16,0x13,0x11,0x11,0x19,0xff, + 0xff,0x14,0x09,0x0f,0x16,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x12,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0e,0x16,0x12,0x12,0x12,0x12,0x11,0x11,0x10,0x14,0x11,0x19,0xff, + 0xff,0x14,0x09,0x0e,0x17,0x10,0x13,0x10,0x0f,0x10,0x14,0x0f,0x16,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0e,0x16,0x0f,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x16,0x11,0x19,0xff, + 0xff,0x16,0x0d,0x0d,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x17,0x0f,0x16,0x11,0x1a,0xff, + 0xff,0x18,0x11,0x0d,0x17,0x0f,0x17,0x0f,0x16,0x0f,0x16,0x0f,0x14,0x16,0x1d,0xff, + 0xff,0x1a,0x16,0x13,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x17,0x0f,0x14,0x1b,0x1e,0xff, + 0xff,0xff,0x1a,0x18,0x17,0x10,0x17,0x0f,0x16,0x0f,0x16,0x11,0x1b,0x1e,0x1d,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x11,0x17,0x12,0x19,0x1b,0x1e,0x1d,0x1c,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1d,0x1e,0x1e,0x1e,0x1d,0x1d,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const unsigned char kButtonMiddleBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x18,0x16,0x14,0x14,0x16,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x18,0x13,0x0d,0x09,0x08,0x09,0x0c,0x10,0x16,0x19,0x1a,0xff,0xff, + 0xff,0xff,0x18,0x11,0x09,0x09,0x11,0x0e,0x12,0x0f,0x12,0x0e,0x16,0xff,0xff,0xff, + 0xff,0x1a,0x13,0x09,0x0d,0x0e,0x14,0x0f,0x14,0x0f,0x14,0x10,0x12,0x18,0x1c,0xff, + 0xff,0x17,0x0d,0x09,0x14,0x0f,0x17,0x0f,0x17,0x0f,0x16,0x0f,0x16,0x16,0xff,0xff, + 0xff,0x14,0x0a,0x0e,0x16,0x12,0x1b,0x1c,0x1e,0x1a,0x19,0x11,0x17,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0e,0x19,0x1b,0x1e,0x1d,0x1d,0x1c,0x1b,0x17,0x17,0x11,0x19,0xff, + 0xff,0x14,0x09,0x11,0x1c,0x1d,0x1d,0x1d,0x1c,0x1b,0x1a,0x18,0x16,0x12,0x19,0xff, + 0xff,0x14,0x08,0x17,0x1d,0x1d,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x16,0x12,0x19,0xff, + 0xff,0x14,0x08,0x1a,0x1c,0x1c,0x1b,0x1b,0x1b,0x1a,0x19,0x18,0x16,0x13,0x19,0xff, + 0xff,0x14,0x09,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x16,0x14,0x12,0x19,0xff, + 0xff,0x14,0x08,0x17,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x14,0x13,0x11,0x19,0xff, + 0xff,0x14,0x09,0x13,0x17,0x17,0x17,0x17,0x17,0x16,0x16,0x13,0x11,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0f,0x16,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x12,0x11,0x19,0xff, + 0xff,0x16,0x0d,0x0e,0x16,0x12,0x12,0x12,0x12,0x11,0x11,0x10,0x14,0x11,0x1a,0xff, + 0xff,0x18,0x11,0x0e,0x17,0x10,0x13,0x10,0x0f,0x10,0x14,0x0f,0x14,0x16,0x1d,0xff, + 0xff,0x1a,0x16,0x13,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x17,0x0f,0x14,0x1b,0x1e,0xff, + 0xff,0xff,0x1a,0x18,0x17,0x10,0x17,0x0f,0x16,0x0f,0x16,0x11,0x1b,0x1e,0x1d,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x11,0x17,0x12,0x19,0x1b,0x1e,0x1d,0x1c,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1d,0x1e,0x1e,0x1e,0x1d,0x1d,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const unsigned char kButtonDownBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x18,0x16,0x14,0x14,0x16,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x18,0x13,0x0d,0x09,0x08,0x09,0x0c,0x10,0x16,0x19,0x1a,0xff,0xff, + 0xff,0xff,0x18,0x11,0x09,0x09,0x11,0x0e,0x12,0x0f,0x12,0x0e,0x16,0xff,0xff,0xff, + 0xff,0x1a,0x13,0x09,0x0d,0x0e,0x14,0x0f,0x14,0x0f,0x14,0x10,0x12,0x18,0x1c,0xff, + 0xff,0x17,0x0d,0x09,0x14,0x0f,0x17,0x0f,0x17,0x0f,0x16,0x0f,0x16,0x16,0xff,0xff, + 0xff,0x16,0x09,0x0b,0x16,0x0f,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x19,0x11,0x1a,0xff, + 0xff,0x14,0x08,0x0d,0x17,0x0f,0x17,0x0f,0x17,0x0f,0x16,0x0f,0x17,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0e,0x16,0x0f,0x16,0x0f,0x16,0x0f,0x17,0x0f,0x16,0x11,0x19,0xff, + 0xff,0x14,0x0a,0x0e,0x16,0x12,0x1b,0x1c,0x1e,0x1a,0x19,0x11,0x17,0x11,0x19,0xff, + 0xff,0x14,0x08,0x0e,0x19,0x1b,0x1e,0x1d,0x1d,0x1c,0x1b,0x17,0x17,0x11,0x19,0xff, + 0xff,0x14,0x09,0x11,0x1c,0x1d,0x1d,0x1d,0x1c,0x1b,0x1a,0x18,0x16,0x12,0x19,0xff, + 0xff,0x14,0x08,0x17,0x1d,0x1d,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x16,0x12,0x19,0xff, + 0xff,0x14,0x09,0x1a,0x1c,0x1c,0x1b,0x1b,0x1b,0x1a,0x19,0x18,0x16,0x13,0x19,0xff, + 0xff,0x14,0x08,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x16,0x14,0x12,0x19,0xff, + 0xff,0x16,0x0d,0x17,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x14,0x13,0x11,0x1a,0xff, + 0xff,0x18,0x11,0x13,0x17,0x17,0x17,0x17,0x17,0x16,0x16,0x13,0x11,0x13,0x1d,0xff, + 0xff,0x1a,0x16,0x13,0x16,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x11,0x19,0x1e,0xff, + 0xff,0xff,0x1a,0x18,0x16,0x12,0x12,0x12,0x12,0x11,0x11,0x10,0x18,0x1e,0x1d,0xff, + 0xff,0xff,0xff,0xff,0xff,0x18,0x14,0x10,0x0f,0x11,0x14,0x19,0x1e,0x1d,0x1c,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1d,0x1e,0x1e,0x1e,0x1d,0x1d,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const int32 kSpeakerIconBitmapWidth = 16; +const int32 kSpeakerIconBitmapHeight = 9; +const BPoint kSpeakerIconBitmapSize(kSpeakerIconBitmapWidth - 1, kSpeakerIconBitmapHeight - 1); + +const unsigned char kSpeakerIconBits [] = { + 0xff,0xff,0xff,0xff,0xff,0x10,0x10,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,0xff, + 0x10,0x10,0x10,0xff,0x10,0x1d,0x10,0xff,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff, + 0x10,0x1d,0x10,0x10,0x1d,0x1d,0x10,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,0xff, + 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff, + 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0x10,0xff,0x10,0xff,0xff,0x10,0xff,0xff, + 0x10,0x1d,0x10,0x1d,0x1d,0x1d,0x10,0xff,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff, + 0x10,0x1d,0x10,0x10,0x1d,0x1d,0x10,0xff,0xff,0x10,0xff,0xff,0x10,0xff,0xff,0xff, + 0x10,0x10,0x10,0xff,0x10,0x1d,0x10,0xff,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x10,0x10,0xff,0xff,0xff,0xff,0x10,0xff,0xff,0xff,0xff, +}; + + +// #pragma mark play + +const int32 kPlayPauseBitmapWidth = 48; +const int32 kPlayPauseBitmapHeight = 22; +const BPoint kPlayButtonSize(kPlayPauseBitmapWidth - 1, kPlayPauseBitmapHeight - 1); + +const unsigned char kPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff, + 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff, + 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff, + 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff, + 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff, + 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff, + 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff, + 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff, + 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff, + 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kDisabledPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18, + 0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1b,0x19,0x18,0x18,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0x1a, + 0x19,0x18,0x19,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a, + 0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x1a,0x1c, + 0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a, + 0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x16, + 0x16,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16, + 0x16,0x1b,0x1b,0x1b,0x16,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16,0x16,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b, + 0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18, + 0x19,0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff, + 0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x16, + 0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b, + 0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x18,0x18,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x1c,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff, + 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16, + 0x19,0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x16,0x19,0x19,0x1c,0x1b,0x1b,0x16,0x19,0x19,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x1a,0x18,0x19, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1a,0x17,0x1a,0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18,0x1c,0x1c, + 0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x1b,0x1c,0xff,0xff,0xff,0xff,0xff, + 0xff,0x19,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18, + 0x17,0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18, + 0x18,0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18,0x1b,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1a,0x19,0x17,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x19,0x1a,0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff, +}; + + +const unsigned char kPressedPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19, + 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f, + 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a, + 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +const unsigned char kPlayingPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c, + 0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19, + 0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14, + 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a, + 0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17, + 0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x00, + 0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00, + 0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00,0x00,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a, + 0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12, + 0x13,0xff,0xff,0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff, + 0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34, + 0x34,0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00, + 0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x1d,0x19, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34, + 0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a, + 0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18, + 0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x3f,0x3f,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x34,0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x00,0x17,0x17,0x3f,0x1a,0x1a,0x00,0x17,0x17,0x3f,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff,0xff,0x17,0x11,0x13, + 0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x3f,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f, + 0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x14,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c, + 0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff, + 0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10, + 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11, + 0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff, +}; + + +const unsigned char kPressedPlayingPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19, + 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f, + 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a, + 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17, + 0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13, + 0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f, + 0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x34,0x34,0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x34, + 0x34,0x34,0x34,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19, + 0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x34,0x34,0x34,0x34,0x19, + 0x19,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10, + 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13, + 0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x34, + 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10, + 0x19,0x13,0x13,0x00,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13, + 0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x19,0x19,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10, + 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c, + 0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff, + 0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10, + 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10, + 0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff, +}; + +const unsigned char kPausedPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff, + 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff, + 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff, + 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff, + 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff, + 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff, + 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x00,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff, + 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff, + 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff, + 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +const unsigned char kPressedPausedPlayButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0x19, + 0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f, + 0x11,0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a, + 0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17, + 0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x10,0x13, + 0x13,0x00,0x00,0x00,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f, + 0x13,0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19, + 0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x19, + 0x19,0x13,0x13,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34, + 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13, + 0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10, + 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34, + 0x19,0x13,0x13,0x00,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13, + 0x12,0x10,0x1a,0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x19,0x19,0x19,0x13,0x13,0x10, + 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c, + 0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff, + 0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10, + 0x12,0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10, + 0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff, +}; + +// #pragma mark stop + +const int32 kStopBitmapWidth = 32; +const int32 kStopBitmapHeight = 22; +const BPoint kStopButtonSize(kStopBitmapWidth - 1, kStopBitmapHeight - 1); + + +const unsigned char kStopButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a, + 0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16, + 0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff, + 0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12, + 0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11, + 0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11, + 0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d, + 0x1d,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17, + 0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13, + 0xff,0xff,0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10,0x3f,0x19, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17, + 0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f, + 0xff,0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13,0x10,0x19,0x19,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x17, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x17,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x16,0x12,0x16,0x1e,0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff,0xff, + 0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15, + 0x10,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19, + 0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff, +}; + + +const unsigned char kDisabledStopButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a, + 0x1a,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a, + 0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x18, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1c,0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19, + 0x18,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x18, + 0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19, + 0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19, + 0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19, + 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c, + 0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x16,0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,0xff,0x19,0x16,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x19, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff, + 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16, + 0x19,0x19,0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a,0x1c,0xff,0xff, + 0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a, + 0x18,0x18,0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x1b,0x1c,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17,0x1a, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18,0x18, + 0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x18,0x17,0x18,0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1c,0x1c,0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a,0x1c,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1d,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff, +}; + + +const unsigned char kPressedStopButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a, + 0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff,0xff,0xff, + 0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,0x12, + 0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11, + 0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11, + 0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13, + 0xff,0xff,0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10,0x0d,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10, + 0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f, + 0xff,0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13,0x10,0x0d,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10, + 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13, + 0x13,0x12,0x0f,0x16,0x1e,0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x10,0x10,0x10, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff,0xff, + 0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x16,0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19, + 0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff, +}; + +// #pragma mark rewind + +const int32 kRewindBitmapWidth = 40; +const int32 kRewindBitmapHeight = 22; +const BPoint kSkipButtonSize(kRewindBitmapWidth - 1, kRewindBitmapHeight - 1); + +const unsigned char kRewindBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11,0x12,0x19,0xff,0xff,0xff, + 0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x14,0x11,0x16,0x1a,0xff,0xff, + 0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x11,0x1a,0xff,0xff, + 0xff,0x17,0x11,0x18,0x3f,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff, + 0xff,0x14,0x11,0x1d,0x1d,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff, + 0xff,0x13,0x10,0x1e,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff, + 0xff,0x13,0x10,0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x00,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e,0xff, + 0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a,0x1e,0xff, + 0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16,0x1e,0x1c,0xff, + 0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12,0x19,0x3f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12,0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kDisabledRewindBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a, + 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18, + 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c, + 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16, + 0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16, + 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x19,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x19, + 0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x19,0x19,0x19,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x16,0x16,0x19,0x19, + 0x19,0x19,0x19,0x1c,0x1b,0x16,0x16,0x19,0x19,0x19,0x19,0x19,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19, + 0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1c,0x1c,0x19, + 0x19,0x19,0x19,0x19,0x1c,0x1b,0x1c,0x1c,0x19,0x19,0x19,0x19,0x19, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff, + 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1c,0x1c,0x19,0x19, + 0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff, + 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1c,0x1c,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c, + 0x1c,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c, + 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a, + 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18, + 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17, + 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18, + 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c, + 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a, + 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kPressedRewindBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11,0x12,0x19,0xff,0xff,0xff, + 0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x16,0x1a,0xff,0xff, + 0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x1a,0xff,0xff, + 0xff,0x17,0x11,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff, + 0xff,0x14,0x11,0x0a,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff, + 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff, + 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e,0xff, + 0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a,0x1e,0xff, + 0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x0f,0x16,0x1e,0x1c,0xff, + 0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12,0x1b,0x3f,0xff,0xff, + 0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12,0x19,0x3f,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16,0x1b,0x3f,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a,0x1d,0x3f,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +// #pragma mark skip back + +const unsigned char kSkipBackBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18, + 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x3f,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17, + 0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17,0x17,0x17,0x17, + 0x17,0x3f,0x1a,0x00,0x00,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17, + 0x17,0x17,0x3f,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x17,0x17,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f, + 0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x17,0x17,0x17,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x3f,0x3f,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x17, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12, + 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +const unsigned char kDisabledSkipBackBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a, + 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18, + 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c, + 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1c,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b, + 0x1c,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1c,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19, + 0x16,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1c,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff, + 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1c,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff, + 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1c,0x1c,0x1b,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c, + 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a, + 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18, + 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17, + 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18, + 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c, + 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a, + 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kPressedSkipBackBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10,0x19,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10, + 0x10,0x10,0x19,0x13,0x13,0x13,0x00,0x00,0x10,0x10,0x10,0x19,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x10,0x10, + 0x10,0x10,0x10,0x19,0x13,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x19, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x10, + 0x10,0x10,0x10,0x10,0x19,0x13,0x19,0x19,0x10,0x10,0x10,0x10,0x10, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x19,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x19,0x19,0x10,0x10, + 0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x19,0x19,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x19, + 0x19,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kSkippingSkipBackBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18, + 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x3f,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34, + 0x3f,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34,0x3f,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x34,0x34,0x34,0x34, + 0x34,0x3f,0x1a,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x3f,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x34,0x34,0x34, + 0x34,0x34,0x3f,0x1a,0x3f,0x3f,0x34,0x34,0x34,0x34,0x34,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f, + 0x34,0x34,0x34,0x3f,0x1a,0x1a,0x1a,0x3f,0x3f,0x34,0x34,0x34,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x3f,0x3f,0x34,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x34, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12, + 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kPressedSkippingSkipBackBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x19,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34, + 0x34,0x34,0x19,0x13,0x13,0x13,0x00,0x00,0x34,0x34,0x34,0x19,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x34,0x34, + 0x34,0x34,0x34,0x19,0x13,0x00,0x00,0x34,0x34,0x34,0x34,0x34,0x19, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x34, + 0x34,0x34,0x34,0x34,0x19,0x13,0x19,0x19,0x34,0x34,0x34,0x34,0x34, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x19,0x34,0x34,0x34,0x19,0x13,0x13,0x13,0x19,0x19,0x34,0x34, + 0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x19,0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x19, + 0x19,0x34,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +// #pragma mark skip forward + +const unsigned char kSkipForwardBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18, + 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x00,0x17,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00, + 0x00,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x00,0x00,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17, + 0x17,0x17,0x00,0x00,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x00,0x00, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17, + 0x17,0x17,0x17,0x3f,0x3f,0x1a,0x00,0x17,0x17,0x17,0x17,0x17,0x3f, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17, + 0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17,0x3f,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x3f,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12, + 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kDisabledSkipForwardBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x1a,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x1a,0x19,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x19,0x1a,0x1a,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x18,0x1a,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x19,0x18,0x18,0x1a, + 0x1a,0xff,0xff,0xff,0xff,0xff,0x1a,0x19,0x18,0x19,0x1c,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x18, + 0x18,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x19,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c, + 0x1a,0x18,0x1a,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x19,0x18,0x1c,0xff,0xff,0xff,0x1a,0x18,0x1a,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x18,0x1a,0x1c,0xff,0xff,0x19,0x17,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x16,0x16,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x16,0x19,0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c,0xff,0xff,0x19,0x16,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16, + 0x16,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x16,0x16,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x17,0x1c,0xff,0xff,0x19,0x16, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19, + 0x19,0x19,0x16,0x16,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x16,0x16, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x1c,0xff,0xff,0x19, + 0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19, + 0x19,0x19,0x19,0x1c,0x1c,0x1b,0x16,0x19,0x19,0x19,0x19,0x19,0x1c, + 0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff,0xff, + 0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19, + 0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19,0x1c,0x1c, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x18,0x1c,0xff, + 0xff,0x19,0x17,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16, + 0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x1c,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x19,0x1c, + 0xff,0xff,0x1a,0x18,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x17,0x1a, + 0x1c,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x18, + 0x1c,0x1c,0xff,0xff,0xff,0x1a,0x19,0x18,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x18,0x19,0x1a,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x18,0x17, + 0x1a,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1a,0x18,0x18, + 0x18,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x17,0x18, + 0x1b,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c, + 0x1a,0x19,0x17,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x19,0x1a, + 0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kPressedSkipForwardBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00, + 0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x00,0x00,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10, + 0x10,0x00,0x00,0x13,0x13,0x13,0x00,0x10,0x10,0x10,0x00,0x00,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10, + 0x10,0x10,0x10,0x10,0x00,0x00,0x13,0x00,0x10,0x10,0x10,0x10,0x10, + 0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x10,0x10,0x10,0x10,0x10,0x19,0x19,0x13,0x00,0x10,0x10,0x10,0x10, + 0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x00,0x10,0x10,0x10, + 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x00,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x19, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kSkippingSkipForwardBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x16,0x1d,0x1e, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1c,0x19,0x16,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x17,0x1c,0x1e,0x1e, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x14,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x17,0x1e,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18, + 0x14,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x12,0x1d,0x1e,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x16,0x12,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x18,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x19,0x14,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x1d,0x1d, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x00,0x00,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x00,0x34,0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x15,0x12,0x13,0xff,0xff,0xff,0x13,0x10,0x1e, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00, + 0x00,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x00,0x00,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x3f,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34, + 0x34,0x34,0x00,0x00,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x00,0x00, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x1d,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x34, + 0x34,0x34,0x34,0x3f,0x3f,0x1a,0x00,0x34,0x34,0x34,0x34,0x34,0x3f, + 0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34, + 0x34,0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x00,0x34,0x34,0x34,0x3f,0x3f, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x15,0x18,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x34,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x34,0x3f,0x3f,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x13,0x16,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f,0x3f,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x14,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x14,0x19,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x14,0x18,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x15,0x10,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x14,0x17,0x18, + 0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x18,0x17,0x12,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x11,0x12, + 0x12,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x12,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x16,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + + +const unsigned char kPressedSkippingSkipForwardBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x18,0x18,0x17,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x17,0x18,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x15,0x14,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x18,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x14,0x11,0x11,0x0e,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x12,0x11,0x11,0x19, + 0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x0d,0x0a,0x0f,0x10, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x0f,0x11, + 0x12,0x19,0xff,0xff,0xff,0xff,0x1a,0x16,0x10,0x0d,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x0f,0x11,0x16,0x1a,0xff,0xff,0xff,0x1a,0x11,0x0d,0x0a,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x0f,0x11,0x1a,0xff,0xff,0xff,0x17,0x11,0x0d,0x11,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x0f,0x11,0x15,0xff,0xff,0xff,0x14,0x11,0x0a,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0xff,0xff,0xff,0x13,0x10,0x0d, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00, + 0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x00,0x00,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x1c,0xff,0xff,0x13,0x10, + 0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x34, + 0x34,0x00,0x00,0x13,0x13,0x13,0x00,0x34,0x34,0x34,0x00,0x00,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff,0x13, + 0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x34, + 0x34,0x34,0x34,0x34,0x00,0x00,0x13,0x00,0x34,0x34,0x34,0x34,0x34, + 0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff,0xff, + 0x13,0x10,0x0d,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00, + 0x34,0x34,0x34,0x34,0x34,0x19,0x19,0x13,0x00,0x34,0x34,0x34,0x34, + 0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x10,0x3f,0xff, + 0xff,0x15,0x10,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x34,0x34,0x34,0x19,0x19,0x13,0x13,0x13,0x00,0x34,0x34,0x34, + 0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1e, + 0xff,0xff,0x17,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x00,0x34,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x00,0x34,0x19, + 0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x1a, + 0x1e,0xff,0xff,0xff,0x13,0x11,0x11,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x19,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x19, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x16, + 0x1e,0x1c,0xff,0xff,0xff,0x18,0x11,0x12,0x10,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x0f,0x12, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0x18,0x11,0x11,0x11,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x12, + 0x19,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x12,0x10,0x11, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x10,0x10,0x16, + 0x1b,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x19,0x19, + 0x14,0x13,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x14,0x17,0x1a, + 0x1d,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +}; + +const int32 kRecordButtonWidth = 32; +const int32 kRecordButtonHeight = 22; +const BPoint kRecordButtonSize(kRecordButtonWidth - 1, kRecordButtonHeight - 1); + +const unsigned char kRecordButtonBitmapBits [] = { + 0xff,0x1b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1a,0x19,0x17,0x14,0x13,0x11,0x11,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x12,0x14,0x16,0x18,0x19,0x1a,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1a,0x18,0x14,0x10,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x13,0x17,0x1a,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x17,0x11,0x0b,0x10,0x16,0x1a,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x19,0x12,0x12,0x16,0x19,0xff,0xff,0xff, + 0xff,0x1a,0x17,0x10,0x0d,0x16,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x18,0x14,0x17,0x1a,0xff,0xff, + 0xff,0x18,0x11,0x0d,0x18,0x1e,0x1d,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x19,0x16,0x19,0x1a,0xff, + 0xff,0x14,0x0c,0x16,0x1e,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x18,0x1a,0xff, + 0xff,0x11,0x10,0x1d,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x18,0xff,0xff, + 0xff,0x0f,0x17,0x1d,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x17, + 0x17,0x17,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x16,0xff,0xff, + 0xff,0x0f,0x1b,0x1c,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17, + 0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x1c,0xff, + 0xff,0x0f,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x0f,0x1c,0xff, + 0xff,0x10,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x0f,0x1d,0xff, + 0xff,0x11,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x0e,0x1d,0xff, + 0xff,0x13,0x19,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x17,0x17, + 0x17,0x17,0x17,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1d,0xff, + 0xff,0x16,0x17,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x17, + 0x17,0x17,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x16,0x0f,0x13,0x1d,0xff, + 0xff,0x19,0x17,0x18,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x0c,0x19,0x1d,0xff, + 0xff,0xff,0x19,0x17,0x16,0x17,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x0c,0x13,0x1e,0x1d,0xff, + 0xff,0xff,0xff,0x1a,0x16,0x13,0x16,0x17,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x16,0x12,0x0b,0x10,0x1c,0x1d,0x1c,0xff, + 0xff,0xff,0xff,0xff,0xff,0x16,0x10,0x10,0x12,0x13,0x13,0x14,0x14,0x14,0x14,0x14, + 0x14,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x0d,0x0a,0x11,0x1c,0x1e,0x1c,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1c,0x1c,0x19,0x13,0x0f,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a, + 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0f,0x19,0x1e,0x1e,0x1c,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1c,0x1c,0xff,0xff,0xff,0xff,0xff,0xff +}; + + +const unsigned char kDisabledRecordButtonBitmapBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x18,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x19,0x16,0x16,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x18,0x16,0x16,0x19,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x18,0x16,0x18,0x1b,0x1b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x18,0x16,0x18,0xff,0xff,0xff,0xff, + 0xff,0xff,0x19,0x16,0x1a,0x1b,0x1b,0x1b,0x1b,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1a,0x16,0x19,0xff,0xff,0xff, + 0x1b,0x1b,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x1b,0x1b,0x1b, + 0x1b,0x18,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16, + 0x16,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x18,0x1b,0x1b, + 0x1b,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x16,0x19, + 0x19,0x19,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x1b,0x1b, + 0x1b,0x14,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19, + 0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x14,0x1b,0x1b, + 0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b, + 0x1b,0x13,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x13,0x1b,0x1b, + 0x1b,0x14,0x19,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x14,0x1b,0x1b, + 0x1b,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x19,0x19, + 0x19,0x19,0x19,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x1b,0x1b, + 0x1b,0x18,0x16,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x19, + 0x19,0x19,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x18,0x1b,0x1b, + 0x1b,0x1b,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c, + 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x19,0x16,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x16,0x19,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x18,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x18,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x19,0x16,0x16,0x18,0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19, + 0x19,0x19,0x19,0x19,0x19,0x19,0x18,0x18,0x16,0x16,0x19,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16, + 0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x18,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b +}; + + +const unsigned char kPressedRecordButtonBitmapBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x19,0x18,0x18,0x18,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x19,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x14,0x13,0x12,0x11,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x12,0x14,0x16,0x19,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1a,0x18,0x14,0x11,0x0d,0x0b,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09, + 0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0c,0x0e,0x12,0x14,0x18,0x1a,0x1a,0x1b,0x1b, + 0x1b,0x1a,0x17,0x13,0x0e,0x0b,0x0c,0x0d,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x0d,0x0d,0x0f,0x11,0x14,0x18,0x1a,0x1a,0x1b, + 0x1a,0x18,0x13,0x0d,0x0c,0x0e,0x11,0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x12,0x11,0x0f,0x0f,0x13,0x16,0x19,0x1a,0x1b, + 0x19,0x14,0x0e,0x0c,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x10,0x16,0x18,0x1a,0x1b, + 0x17,0x11,0x0c,0x0e,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0x18,0x1b,0x1b, + 0x16,0x0d,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x17,0x1b,0x1b, + 0x14,0x0d,0x0e,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x10,0x10,0x10,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x16,0x1c,0x1b, + 0x14,0x0d,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10, + 0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x16,0x1c,0x1b, + 0x14,0x0e,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1c,0x1b, + 0x16,0x0e,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x17,0x1c,0x1b, + 0x17,0x10,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x18,0x1c,0x1b, + 0x18,0x12,0x0f,0x10,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x10, + 0x10,0x10,0x10,0x10,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x13,0x1a,0x1c,0x1b, + 0x1a,0x16,0x11,0x0f,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19, + 0x10,0x10,0x10,0x19,0x19,0x13,0x13,0x13,0x13,0x12,0x11,0x11,0x18,0x1b,0x1c,0x1b, + 0x1b,0x1a,0x16,0x11,0x0f,0x11,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x12,0x12,0x11,0x10,0x16,0x1b,0x1d,0x1c,0x1b, + 0x1b,0x1b,0x1a,0x16,0x12,0x10,0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x10,0x11,0x16,0x1b,0x1c,0x1d,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x12,0x10,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x11,0x14,0x19,0x1b,0x1d,0x1d,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1c,0x1d,0x1d,0x1c,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1c,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b +}; + + +const unsigned char kRecordingRecordButtonBitmapBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x14,0x13,0x11,0x11,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x12,0x14,0x16,0x18,0x19,0x1a,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x18,0x14,0x10,0x0d,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b, + 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0f,0x13,0x17,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1a,0x17,0x11,0x0b,0x10,0x16,0x1a,0x1d,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x19,0x12,0x12,0x16,0x19,0x1b,0x1b,0x1b, + 0x1b,0x1a,0x17,0x10,0x0d,0x16,0x1e,0x1e,0x1d,0x1d,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x18,0x14,0x17,0x1a,0x1b,0x1b, + 0x1b,0x18,0x11,0x0d,0x18,0x1e,0x1d,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x19,0x16,0x19,0x1a,0x1b, + 0x1b,0x14,0x0c,0x16,0x1e,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x18,0x1a,0x1b, + 0x1b,0x11,0x10,0x1d,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00, + 0x00,0x00,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x17,0x18,0x1b,0x1b, + 0x1b,0x0f,0x17,0x1d,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x00,0x9d, + 0x9d,0x9d,0x00,0x10,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x16,0x1b,0x1b, + 0x1b,0x0f,0x1b,0x1c,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x12,0x1c,0x1b, + 0x1b,0x0f,0x1c,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x9d,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x0f,0x1c,0x1b, + 0x1b,0x10,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x9d,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x16,0x0f,0x1d,0x1b, + 0x1b,0x11,0x1b,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x9d,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x14,0x0e,0x1d,0x1b, + 0x1b,0x13,0x19,0x1b,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x00,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x10,0x1d,0x1b, + 0x1b,0x16,0x17,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x10,0x3f,0x9d, + 0x9d,0x9d,0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x16,0x0f,0x13,0x1d,0x1b, + 0x1b,0x19,0x17,0x18,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x3f, + 0x3f,0x3f,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x12,0x0c,0x19,0x1d,0x1b, + 0x1b,0x1b,0x19,0x17,0x16,0x17,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x18,0x13,0x0c,0x13,0x1e,0x1d,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x16,0x13,0x16,0x17,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x19,0x16,0x12,0x0b,0x10,0x1c,0x1d,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x16,0x10,0x10,0x12,0x13,0x13,0x14,0x14,0x14,0x14,0x14, + 0x14,0x14,0x14,0x14,0x14,0x14,0x13,0x11,0x0d,0x0a,0x11,0x1c,0x1e,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x19,0x13,0x0f,0x0b,0x0b,0x0b,0x0a,0x0a,0x0a,0x0a, + 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0f,0x19,0x1e,0x1e,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1d,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e, + 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1d,0x1c,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b +}; + + +const unsigned char kPressedRecordingRecordButtonBitmapBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x19,0x18,0x18,0x18,0x17,0x17,0x17,0x17,0x17, + 0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x18,0x19,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1a,0x19,0x17,0x14,0x13,0x12,0x11,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x12,0x14,0x16,0x19,0x1a,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1a,0x18,0x14,0x11,0x0d,0x0b,0x0a,0x09,0x09,0x09,0x09,0x09,0x09,0x09, + 0x09,0x09,0x09,0x09,0x09,0x09,0x0a,0x0c,0x0e,0x12,0x14,0x18,0x1a,0x1a,0x1b,0x1b, + 0x1b,0x1a,0x17,0x13,0x0e,0x0b,0x0c,0x0d,0x0f,0x10,0x10,0x10,0x10,0x10,0x10,0x10, + 0x10,0x10,0x10,0x10,0x10,0x10,0x0f,0x0d,0x0d,0x0f,0x11,0x14,0x18,0x1a,0x1a,0x1b, + 0x1a,0x18,0x13,0x0d,0x0c,0x0e,0x11,0x12,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x12,0x11,0x0f,0x0f,0x13,0x16,0x19,0x1a,0x1b, + 0x19,0x14,0x0e,0x0c,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x10,0x16,0x18,0x1a,0x1b, + 0x17,0x11,0x0c,0x0e,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x13,0x18,0x1b,0x1b, + 0x16,0x0d,0x0d,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x00,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x10,0x17,0x1b,0x1b, + 0x14,0x0d,0x0e,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x00, + 0x9d,0x9d,0x9d,0x00,0x00,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x16,0x1c,0x1b, + 0x14,0x0d,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x19,0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x16,0x1c,0x1b, + 0x14,0x0e,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x16,0x1c,0x1b, + 0x16,0x0e,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x17,0x1c,0x1b, + 0x17,0x10,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x9d,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x9d,0x19,0x13,0x13,0x13,0x13,0x13,0x11,0x11,0x18,0x1c,0x1b, + 0x18,0x12,0x0f,0x10,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x9d, + 0x9d,0x9d,0x9d,0x9d,0x19,0x13,0x13,0x13,0x13,0x13,0x12,0x10,0x13,0x1a,0x1c,0x1b, + 0x1a,0x16,0x11,0x0f,0x11,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x00,0x19, + 0x9d,0x9d,0x9d,0x19,0x19,0x13,0x13,0x13,0x13,0x12,0x11,0x11,0x18,0x1b,0x1c,0x1b, + 0x1b,0x1a,0x16,0x11,0x0f,0x11,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x19,0x19,0x13,0x13,0x13,0x13,0x12,0x12,0x11,0x10,0x16,0x1b,0x1d,0x1c,0x1b, + 0x1b,0x1b,0x1a,0x16,0x12,0x10,0x10,0x11,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12, + 0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x11,0x10,0x11,0x16,0x1b,0x1c,0x1d,0x1c,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x18,0x16,0x12,0x10,0x0f,0x0f,0x0f,0x0f,0x0e,0x0e,0x0e,0x0f, + 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x11,0x14,0x19,0x1b,0x1d,0x1d,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1c,0x1a,0x19,0x19,0x19,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1c,0x1d,0x1d,0x1c,0x1c,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d, + 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1c,0x1c,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c, + 0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b +}; + + +const int32 kThumbWidth = 16; +const int32 kThumbHeight = 11; +const color_space kThumbColorSpace = B_CMAP8; + +const unsigned char kThumbBits [] = { + 0xff,0xff,0xff,0x18,0x1d,0x3f,0x1d,0x19,0x12,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x15,0x1d,0x1e,0x1e,0x1d,0x1e,0x1b,0x19,0x12,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1e,0x1e,0x1d,0x1d,0x3f,0x1d,0x1d,0x1b,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x1e,0x1d,0x1d,0x1d,0x13,0x1d,0x1d,0x1d,0x19,0x12,0xff,0xff,0xff,0xff,0xff, + 0x1e,0x1e,0x1d,0x1d,0x1d,0x3f,0x1d,0x1d,0x1d,0x19,0x11,0xff,0xff,0xff,0xff,0xff, + 0x3f,0x1d,0x1d,0x1d,0x1d,0x13,0x1d,0x1d,0x1d,0x1c,0x0e,0xff,0xff,0xff,0xff,0xff, + 0x1e,0x1e,0x1d,0x1d,0x1d,0x3f,0x1d,0x1d,0x1d,0x19,0x11,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x1d,0x1d,0x1d,0x1d,0x13,0x1d,0x1d,0x1d,0x15,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1a,0x19,0x1d,0x1d,0x1d,0x1d,0x1d,0x17,0x12,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x16,0xff,0x15,0x19,0x1c,0x19,0x15,0x12,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x14,0x11,0x0e,0x11,0x14,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const int32 kLeftVolumeWidth = 16; +const int32 kLeftVolumeHeight = 15; +const color_space kLeftVolumeColorSpace = B_CMAP8; + +const unsigned char kLeftVolumeBits [] = { + 0xff,0xff,0xff,0xff,0x19,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1a,0x18,0x11,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x19,0x15,0x0b,0x06,0x0a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x15,0x09,0x09,0xb6,0x8f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x18,0x0b,0x09,0x8f,0x8f,0x8f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x11,0x07,0xb6,0x8f,0x8f,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x0c,0x0c,0x8f,0x8f,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x07,0x10,0x8f,0x68,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x16,0x12,0x8f,0x68,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x16,0x11,0x68,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x1a,0x18,0x68,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x1c,0x19,0x68,0x68,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x1d,0x1c,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0x1d,0x1e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const int32 kRightVolumeWidth = 16; +const int32 kRightVolumeHeight = 15; +const color_space kRightVolumeColorSpace = B_CMAP8; + +const unsigned char kRightVolumeBits [] = { + 0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x11,0x18,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x08,0x0d,0x16,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x11,0x0c,0x0f,0x17,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x10,0x14,0x19,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x13,0x15,0x19,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x13,0x16,0x1a,0x1a,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x13,0x15,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x13,0x19,0x1e,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x13,0x15,0x1d,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x13,0x14,0x1a,0x1e,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x15,0xff,0x3f,0x1d,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1d,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1d,0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const int32 kDiskButtonWidth = 20; +const int32 kDiskButtonHeight = 20; +const color_space kDiskButtonColorSpace = B_CMAP8; +const BPoint kDiskButtonSize(kDiskButtonWidth - 1, kDiskButtonHeight - 1); + +const unsigned char kDiskButtonBitmapsBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x1d,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x00,0x11,0x00,0x18,0x18,0x19,0x18, + 0x18,0x19,0x18,0x19,0x00,0x18,0x00,0x15,0x16,0x18,0x1a,0x1b,0x1b,0x00,0x11,0x00, + 0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19,0x00,0x00,0x00,0x10,0x13,0x16,0x19,0x1b, + 0x1b,0x00,0x11,0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19,0x00,0x11,0x00,0x0d, + 0x10,0x15,0x18,0x1a,0x1b,0x00,0x11,0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19, + 0x00,0x11,0x00,0x0b,0x0f,0x14,0x18,0x1a,0x1b,0x00,0x11,0x00,0x18,0x18,0x19,0x18, + 0x18,0x19,0x18,0x19,0x00,0x11,0x00,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x00,0x11,0x11, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x00,0x0a,0x0e,0x14,0x18,0x1a, + 0x1b,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x00,0x0a, + 0x0e,0x14,0x18,0x1a,0x1b,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x11,0x00,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x00,0x11,0x11,0x00,0x00,0x00,0x00, + 0x00,0x00,0x19,0x18,0x00,0x11,0x00,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x00,0x11,0x11, + 0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x18,0x00,0x11,0x00,0x0a,0x0e,0x14,0x18,0x1a, + 0x1b,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x18,0x00,0x11,0x00,0x0a, + 0x0f,0x14,0x18,0x1a,0x1b,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x09,0x0b,0x0f,0x14,0x18,0x1a,0x1b,0x19,0x16,0x11,0x0d,0x0b,0x0a,0x0a, + 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0d,0x11,0x16,0x19,0x1b,0x1b,0x1a,0x18,0x14, + 0x11,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x11,0x14,0x18,0x1a,0x1b, + 0x1b,0x1a,0x19,0x18,0x16,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x16, + 0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1a,0x1a,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x19,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b +}; + +const unsigned char kPressedDiskButtonBitmapsBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1a,0x1d,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1d,0x16,0x18,0x1a,0x1b,0x1b,0x19,0x00,0x11, + 0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19,0x00,0x18,0x00,0x13,0x16,0x19,0x1b, + 0x1b,0x18,0x00,0x11,0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19,0x00,0x00,0x00, + 0x10,0x15,0x18,0x1a,0x1b,0x18,0x00,0x11,0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18, + 0x19,0x00,0x11,0x00,0x0f,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11,0x00,0x18,0x18,0x19, + 0x18,0x18,0x19,0x18,0x19,0x00,0x11,0x00,0x0e,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11, + 0x00,0x18,0x18,0x19,0x18,0x18,0x19,0x18,0x19,0x00,0x11,0x00,0x0e,0x14,0x18,0x1a, + 0x1b,0x18,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x00, + 0x0e,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x11,0x00,0x0e,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11,0x11,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x0e,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11, + 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x18,0x00,0x11,0x00,0x0e,0x14,0x18,0x1a, + 0x1b,0x18,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x18,0x00,0x11,0x00, + 0x0f,0x14,0x18,0x1a,0x1b,0x18,0x00,0x11,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x19, + 0x18,0x00,0x11,0x00,0x0f,0x14,0x18,0x1a,0x1b,0x19,0x16,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x11,0x16,0x19,0x1b,0x1b,0x1a,0x18,0x14, + 0x11,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x11,0x14,0x18,0x1a,0x1b, + 0x1b,0x1a,0x19,0x18,0x16,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x16, + 0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1a,0x1a,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x19,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b +}; + +const unsigned char kDisabledDiskButtonBitmapsBits [] = { + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x19,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x19,0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x11,0x15,0x11,0x17,0x17,0x18,0x17, + 0x17,0x18,0x17,0x18,0x11,0x17,0x11,0x15,0x16,0x18,0x1a,0x1b,0x1b,0x11,0x15,0x11, + 0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x18,0x11,0x11,0x11,0x10,0x13,0x16,0x19,0x1b, + 0x1b,0x11,0x15,0x11,0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x18,0x11,0x15,0x11,0x0d, + 0x10,0x15,0x18,0x1a,0x1b,0x11,0x15,0x11,0x17,0x17,0x18,0x17,0x17,0x18,0x17,0x18, + 0x11,0x15,0x11,0x0b,0x0f,0x14,0x18,0x1a,0x1b,0x11,0x15,0x11,0x17,0x17,0x18,0x17, + 0x17,0x18,0x17,0x18,0x11,0x15,0x11,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x11,0x15,0x15, + 0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x15,0x15,0x11,0x0a,0x0e,0x14,0x18,0x1a, + 0x1b,0x11,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x11,0x0a, + 0x0e,0x14,0x18,0x1a,0x1b,0x11,0x15,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x15,0x11,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x11,0x15,0x15,0x11,0x11,0x11,0x11, + 0x11,0x11,0x18,0x17,0x11,0x15,0x11,0x0a,0x0e,0x14,0x18,0x1a,0x1b,0x11,0x15,0x15, + 0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x17,0x11,0x15,0x11,0x0a,0x0e,0x14,0x18,0x1a, + 0x1b,0x11,0x15,0x15,0x11,0x11,0x11,0x11,0x11,0x11,0x18,0x17,0x11,0x15,0x11,0x0a, + 0x0f,0x14,0x18,0x1a,0x1b,0x18,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, + 0x11,0x11,0x13,0x0b,0x0f,0x14,0x18,0x1a,0x1b,0x19,0x16,0x11,0x0d,0x0b,0x0a,0x0a, + 0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0b,0x0d,0x11,0x16,0x19,0x1b,0x1b,0x1a,0x18,0x14, + 0x11,0x0f,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0e,0x0f,0x11,0x14,0x18,0x1a,0x1b, + 0x1b,0x1a,0x19,0x18,0x16,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x16, + 0x18,0x19,0x1a,0x1b,0x1b,0x1b,0x1a,0x1a,0x19,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x19,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1a,0x1a,0x1a, + 0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b, + 0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b,0x1b +}; + + +const int32 kLeftRightTrackSliderWidth = 16; +const int32 kLeftRightTrackSliderHeight = 18; +const BPoint kLeftRightTrackSliderSize(kLeftRightTrackSliderWidth - 1, kLeftRightTrackSliderHeight - 1); + +const unsigned char kLeftTrackSliderBits [] = { + 0xff,0xff,0xff,0xff,0xff,0x19,0x19,0x18,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17, + 0xff,0xff,0xff,0x1a,0x18,0x11,0x0b,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0xff,0xff,0x19,0x15,0x0b,0x06,0x0a,0x0f,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0xff,0x1a,0x15,0x09,0x09,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0xff,0x18,0x0b,0x09,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x11,0x07,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0x19,0x0c,0x0c,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x18,0x09,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x17,0x0b,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x18,0x10,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x18,0x10,0x12,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x19,0x14,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0x1a,0x18,0x16,0x14,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x16,0x13,0x13, + 0xff,0x19,0x1a,0x18,0x14,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0xff,0xff,0x1a,0x1c,0x19,0x15,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0xff,0xff,0xff,0xff,0x1d,0x1c,0x19,0x16,0x14,0x13,0x13,0x13,0x13,0x13,0x13,0x13, + 0xff,0xff,0xff,0xff,0xff,0x1d,0x1e,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + +const unsigned char kRightTrackSliderBits [] = { + 0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x18,0x19,0x19,0xff,0xff,0xff,0xff,0xff,0xff, + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x0c,0x11,0x18,0x1a,0xff,0xff,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x12,0x0f,0x0c,0x08,0x0d,0x16,0x1a,0xff,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x11,0x0c,0x0f,0x17,0x1a,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x10,0x14,0x19,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x19,0x1a,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x1a,0x1a,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x1c,0xff,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x3f,0x1c,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x1e,0x1c,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x16,0x1e,0x1c,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x19,0x1e,0x1c,0xff, + 0x13,0x10,0x16,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0x1d,0x1d,0x1c,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x1a,0x1e,0x1c,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x15,0xff,0x3f,0x1d,0xff,0xff,0xff, + 0x13,0x13,0x13,0x13,0x13,0x13,0x14,0x16,0x19,0x1d,0x1e,0x1d,0xff,0xff,0xff,0xff, + 0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x1e,0x1d,0x1c,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +}; + + +const int32 kLeftRightThumbWidth = 16; +const int32 kLeftRightThumbHeight = 14; +const BPoint kLeftRightThumbSize(kLeftRightThumbWidth - 1, kLeftRightThumbHeight - 1); + +const unsigned char kLeftThumbBits [] = { + 0xff,0xff,0xff,0x16,0x16,0x19,0x19,0x1d,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x17,0x1c,0x1d,0x1c,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x18,0x1e,0x1c,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x16,0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x18,0x1e,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1c,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1e,0x1b,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1e,0x1b,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1c,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x18,0x1c,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x15,0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x17,0x17,0x18,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x14,0x13,0x14,0x17,0x1a,0x1a,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0x14,0x10,0x0d,0x0d,0x0d,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff +};/* +const unsigned char kLeftThumbBits [] = { + 0xff,0xff,0x16,0x16,0x19,0x19,0x1d,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x17,0x1c,0x1d,0x1c,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x18,0x1e,0x1c,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1c,0x1b,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1e,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1b,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1b,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1c,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x1a,0x1a,0x1b,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0x17,0x17,0x18,0x1b,0x1b,0x1b,0x1b,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0x14,0x13,0x14,0x17,0x1a,0x1a,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0x14,0x10,0x0d,0x0d,0x0d,0x0c,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff +};*/ + +const unsigned char kRightThumbBits [] = { + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1d,0x1c,0x18,0x15,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x1b,0x19,0x16,0x11,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x1b,0x1b,0x18,0x14,0x11,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x11,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x14,0x11,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x17,0x11,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x1a,0x10,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x1a,0x10,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x3f,0x1b,0x3f,0x1b,0x1b,0x18,0x10,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x17,0x1b,0x17,0x1b,0x14,0x12,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x1b,0x1b,0x1b,0x17,0x11,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1b,0x1b,0x1b,0x1b,0x17,0x12,0x12,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x1a,0x17,0x17,0x14,0x10,0x11,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0x11,0x11,0x10,0x0e,0x0e,0xff,0xff,0xff,0xff,0xff +}; +