├── .gitignore ├── LICENSE ├── README.md ├── iTunes.h ├── ios ├── .gitignore └── iFrisbee │ ├── iFrisbee.xcodeproj │ └── project.pbxproj │ ├── iFrisbee │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── DetailViewController.h │ ├── DetailViewController.m │ ├── MasterViewController.h │ ├── MasterViewController.m │ ├── en.lproj │ │ ├── InfoPlist.strings │ │ ├── MainStoryboard_iPad.storyboard │ │ └── MainStoryboard_iPhone.storyboard │ ├── iFrisbee-Info.plist │ ├── iFrisbee-Prefix.pch │ └── main.m │ └── iFrisbeeTests │ ├── en.lproj │ └── InfoPlist.strings │ ├── iFrisbeeTests-Info.plist │ ├── iFrisbeeTests.h │ └── iFrisbeeTests.m ├── mac ├── .gitignore └── Frisbee │ ├── Frisbee.xcodeproj │ └── project.pbxproj │ ├── Frisbee │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Frisbee-Info.plist │ ├── Frisbee-Prefix.pch │ ├── en.lproj │ │ ├── Credits.rtf │ │ ├── InfoPlist.strings │ │ └── MainMenu.xib │ └── main.m │ ├── FrisbeeTests │ ├── FrisbeeTests-Info.plist │ ├── FrisbeeTests.h │ ├── FrisbeeTests.m │ └── en.lproj │ │ └── InfoPlist.strings │ └── growlTunes.png ├── nginx.conf ├── package.json ├── src ├── bookmarklet.coffee ├── client.coffee ├── handler.coffee └── server.coffee └── static ├── bookmarklet.html ├── css └── home.css ├── handler.html ├── img ├── article.png ├── cloud1.png ├── cloud2.png ├── cloud3.png ├── frisbee-logo.png ├── frisbee.png ├── grass-left.png ├── grass-right.png ├── kid1.png ├── kid2.png ├── music.png ├── swoosh.png └── video.png ├── js └── libs │ ├── jquery-ui-1.8.18.custom.min.js │ ├── jquery.js │ └── shake.js └── sound ├── whoosh.mp3 └── whoosh.ogg /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Javascript 2 | /js 3 | 4 | # Installed packages 5 | node_modules 6 | 7 | # Numerous always-ignore extensions 8 | *.diff 9 | *.err 10 | *.orig 11 | *.log 12 | *.rej 13 | *.swo 14 | *.swp 15 | *.vi 16 | *~ 17 | *.sass-cache 18 | 19 | # OS or Editor folders 20 | .DS_Store 21 | Thumbs.db 22 | .cache 23 | .project 24 | .settings 25 | .tmproj 26 | *.esproj 27 | nbproject 28 | *.sublime-project 29 | *.sublime-workspace 30 | 31 | # Dreamweaver added files 32 | _notes 33 | dwsync.xml 34 | 35 | # Komodo 36 | *.komodoproject 37 | .komodotools 38 | 39 | # Folders to ignore 40 | .hg 41 | .svn 42 | .CVS 43 | intermediate 44 | publish 45 | .idea 46 | 47 | # build script local files 48 | build/buildinfo.properties 49 | build/config/buildinfo.properties 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Feross Aboukhadijeh, Abi Raja, Alexandria Hicks-Nelson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Fling Readme 2 | ============ 3 | 4 | Developed by [Abi Raja](http://abi.sh), [Feross Aboukhadijeh](http://feross.org), and Alex Hicks-Nelson for [Stanford ACM](http://stanfordacm.com) Big Hack 2012. We won second place. 5 | 6 | Fling your content around! 7 | -------------------------- 8 | 9 | Fling is an iPhone app and bookmarklet that let's you fling content (like music, web urls, and youtube videos) from your phone onto a nearby computer. The computer you're sending too only needs a web browser to receive flings. We also built a Mac app so if you're a regular flinger you can fling without even opening a browser window! This is super handy if you like to continue listening to your iPod music on your desktop speakers when you get home. 10 | 11 | ## How to Run It 12 | 13 | The server is written in Node.js and CoffeeScript. Objective C for the Mac and iPhone apps and JavaScript for the bookmarklet, of course. All the code is hackathon-quality and we haven't touched it since the hackathon, so we make no guarantees about code quality or runability of anything! Here be dragons... 14 | 15 | ### Server 16 | 17 | To get the server running, 18 | 19 | ```coffee 20 | npm install 21 | coffee src/server.coffee 22 | open http://localhost:5000 23 | ``` 24 | 25 | Run this in a new terminal window 26 | ``` 27 | coffee -w -o js/ -c src/*.coffee 28 | ``` 29 | 30 | ### Endpoints 31 | 32 | * /new with geolocation 33 | 34 | Messsaging: 35 | 36 | id -> {name, geolocation, ip} 37 | frisbee -> do animation, etc. -------------------------------------------------------------------------------- /iTunes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * iTunes.h 3 | */ 4 | 5 | #import 6 | #import 7 | 8 | 9 | @class iTunesPrintSettings, iTunesApplication, iTunesItem, iTunesArtwork, iTunesEncoder, iTunesEQPreset, iTunesPlaylist, iTunesAudioCDPlaylist, iTunesDevicePlaylist, iTunesLibraryPlaylist, iTunesRadioTunerPlaylist, iTunesSource, iTunesTrack, iTunesAudioCDTrack, iTunesDeviceTrack, iTunesFileTrack, iTunesSharedTrack, iTunesURLTrack, iTunesUserPlaylist, iTunesFolderPlaylist, iTunesVisual, iTunesWindow, iTunesBrowserWindow, iTunesEQWindow, iTunesPlaylistWindow; 10 | 11 | enum iTunesEKnd { 12 | iTunesEKndTrackListing = 'kTrk' /* a basic listing of tracks within a playlist */, 13 | iTunesEKndAlbumListing = 'kAlb' /* a listing of a playlist grouped by album */, 14 | iTunesEKndCdInsert = 'kCDi' /* a printout of the playlist for jewel case inserts */ 15 | }; 16 | typedef enum iTunesEKnd iTunesEKnd; 17 | 18 | enum iTunesEnum { 19 | iTunesEnumStandard = 'lwst' /* Standard PostScript error handling */, 20 | iTunesEnumDetailed = 'lwdt' /* print a detailed report of PostScript errors */ 21 | }; 22 | typedef enum iTunesEnum iTunesEnum; 23 | 24 | enum iTunesEPlS { 25 | iTunesEPlSStopped = 'kPSS', 26 | iTunesEPlSPlaying = 'kPSP', 27 | iTunesEPlSPaused = 'kPSp', 28 | iTunesEPlSFastForwarding = 'kPSF', 29 | iTunesEPlSRewinding = 'kPSR' 30 | }; 31 | typedef enum iTunesEPlS iTunesEPlS; 32 | 33 | enum iTunesERpt { 34 | iTunesERptOff = 'kRpO', 35 | iTunesERptOne = 'kRp1', 36 | iTunesERptAll = 'kAll' 37 | }; 38 | typedef enum iTunesERpt iTunesERpt; 39 | 40 | enum iTunesEVSz { 41 | iTunesEVSzSmall = 'kVSS', 42 | iTunesEVSzMedium = 'kVSM', 43 | iTunesEVSzLarge = 'kVSL' 44 | }; 45 | typedef enum iTunesEVSz iTunesEVSz; 46 | 47 | enum iTunesESrc { 48 | iTunesESrcLibrary = 'kLib', 49 | iTunesESrcIPod = 'kPod', 50 | iTunesESrcAudioCD = 'kACD', 51 | iTunesESrcMP3CD = 'kMCD', 52 | iTunesESrcDevice = 'kDev', 53 | iTunesESrcRadioTuner = 'kTun', 54 | iTunesESrcSharedLibrary = 'kShd', 55 | iTunesESrcUnknown = 'kUnk' 56 | }; 57 | typedef enum iTunesESrc iTunesESrc; 58 | 59 | enum iTunesESrA { 60 | iTunesESrAAlbums = 'kSrL' /* albums only */, 61 | iTunesESrAAll = 'kAll' /* all text fields */, 62 | iTunesESrAArtists = 'kSrR' /* artists only */, 63 | iTunesESrAComposers = 'kSrC' /* composers only */, 64 | iTunesESrADisplayed = 'kSrV' /* visible text fields */, 65 | iTunesESrASongs = 'kSrS' /* song names only */ 66 | }; 67 | typedef enum iTunesESrA iTunesESrA; 68 | 69 | enum iTunesESpK { 70 | iTunesESpKNone = 'kNon', 71 | iTunesESpKBooks = 'kSpA', 72 | iTunesESpKFolder = 'kSpF', 73 | iTunesESpKGenius = 'kSpG', 74 | iTunesESpKITunesU = 'kSpU', 75 | iTunesESpKLibrary = 'kSpL', 76 | iTunesESpKMovies = 'kSpI', 77 | iTunesESpKMusic = 'kSpZ', 78 | iTunesESpKPartyShuffle = 'kSpS', 79 | iTunesESpKPodcasts = 'kSpP', 80 | iTunesESpKPurchasedMusic = 'kSpM', 81 | iTunesESpKTVShows = 'kSpT' 82 | }; 83 | typedef enum iTunesESpK iTunesESpK; 84 | 85 | enum iTunesEVdK { 86 | iTunesEVdKNone = 'kNon' /* not a video or unknown video kind */, 87 | iTunesEVdKMovie = 'kVdM' /* movie track */, 88 | iTunesEVdKMusicVideo = 'kVdV' /* music video track */, 89 | iTunesEVdKTVShow = 'kVdT' /* TV show track */ 90 | }; 91 | typedef enum iTunesEVdK iTunesEVdK; 92 | 93 | enum iTunesERtK { 94 | iTunesERtKUser = 'kRtU' /* user-specified rating */, 95 | iTunesERtKComputed = 'kRtC' /* iTunes-computed rating */ 96 | }; 97 | typedef enum iTunesERtK iTunesERtK; 98 | 99 | 100 | 101 | /* 102 | * Standard Suite 103 | */ 104 | 105 | @interface iTunesPrintSettings : SBObject 106 | 107 | @property (readonly) NSInteger copies; // the number of copies of a document to be printed 108 | @property (readonly) BOOL collating; // Should printed copies be collated? 109 | @property (readonly) NSInteger startingPage; // the first page of the document to be printed 110 | @property (readonly) NSInteger endingPage; // the last page of the document to be printed 111 | @property (readonly) NSInteger pagesAcross; // number of logical pages laid across a physical page 112 | @property (readonly) NSInteger pagesDown; // number of logical pages laid out down a physical page 113 | @property (readonly) iTunesEnum errorHandling; // how errors are handled 114 | @property (copy, readonly) NSDate *requestedPrintTime; // the time at which the desktop printer should print the document 115 | @property (copy, readonly) NSArray *printerFeatures; // printer specific options 116 | @property (copy, readonly) NSString *faxNumber; // for fax number 117 | @property (copy, readonly) NSString *targetPrinter; // for target printer 118 | 119 | - (void) printPrintDialog:(BOOL)printDialog withProperties:(iTunesPrintSettings *)withProperties kind:(iTunesEKnd)kind theme:(NSString *)theme; // Print the specified object(s) 120 | - (void) close; // Close an object 121 | - (void) delete; // Delete an element from an object 122 | - (SBObject *) duplicateTo:(SBObject *)to; // Duplicate one or more object(s) 123 | - (BOOL) exists; // Verify if an object exists 124 | - (void) open; // open the specified object(s) 125 | - (void) playOnce:(BOOL)once; // play the current track or the specified track or file. 126 | 127 | @end 128 | 129 | 130 | 131 | /* 132 | * iTunes Suite 133 | */ 134 | 135 | // The application program 136 | @interface iTunesApplication : SBApplication 137 | 138 | - (SBElementArray *) browserWindows; 139 | - (SBElementArray *) encoders; 140 | - (SBElementArray *) EQPresets; 141 | - (SBElementArray *) EQWindows; 142 | - (SBElementArray *) playlistWindows; 143 | - (SBElementArray *) sources; 144 | - (SBElementArray *) visuals; 145 | - (SBElementArray *) windows; 146 | 147 | @property (copy) iTunesEncoder *currentEncoder; // the currently selected encoder (MP3, AIFF, WAV, etc.) 148 | @property (copy) iTunesEQPreset *currentEQPreset; // the currently selected equalizer preset 149 | @property (copy, readonly) iTunesPlaylist *currentPlaylist; // the playlist containing the currently targeted track 150 | @property (copy, readonly) NSString *currentStreamTitle; // the name of the current song in the playing stream (provided by streaming server) 151 | @property (copy, readonly) NSString *currentStreamURL; // the URL of the playing stream or streaming web site (provided by streaming server) 152 | @property (copy, readonly) iTunesTrack *currentTrack; // the current targeted track 153 | @property (copy) iTunesVisual *currentVisual; // the currently selected visual plug-in 154 | @property BOOL EQEnabled; // is the equalizer enabled? 155 | @property BOOL fixedIndexing; // true if all AppleScript track indices should be independent of the play order of the owning playlist. 156 | @property BOOL frontmost; // is iTunes the frontmost application? 157 | @property BOOL fullScreen; // are visuals displayed using the entire screen? 158 | @property (copy, readonly) NSString *name; // the name of the application 159 | @property BOOL mute; // has the sound output been muted? 160 | @property NSInteger playerPosition; // the player’s position within the currently playing track in seconds. 161 | @property (readonly) iTunesEPlS playerState; // is iTunes stopped, paused, or playing? 162 | @property (copy, readonly) SBObject *selection; // the selection visible to the user 163 | @property NSInteger soundVolume; // the sound output volume (0 = minimum, 100 = maximum) 164 | @property (copy, readonly) NSString *version; // the version of iTunes 165 | @property BOOL visualsEnabled; // are visuals currently being displayed? 166 | @property iTunesEVSz visualSize; // the size of the displayed visual 167 | 168 | - (void) printPrintDialog:(BOOL)printDialog withProperties:(iTunesPrintSettings *)withProperties kind:(iTunesEKnd)kind theme:(NSString *)theme; // Print the specified object(s) 169 | - (void) run; // run iTunes 170 | - (void) quit; // quit iTunes 171 | - (iTunesTrack *) add:(NSArray *)x to:(SBObject *)to; // add one or more files to a playlist 172 | - (void) backTrack; // reposition to beginning of current track or go to previous track if already at start of current track 173 | - (iTunesTrack *) convert:(NSArray *)x; // convert one or more files or tracks 174 | - (void) fastForward; // skip forward in a playing track 175 | - (void) nextTrack; // advance to the next track in the current playlist 176 | - (void) pause; // pause playback 177 | - (void) playOnce:(BOOL)once; // play the current track or the specified track or file. 178 | - (void) playpause; // toggle the playing/paused state of the current track 179 | - (void) previousTrack; // return to the previous track in the current playlist 180 | - (void) resume; // disable fast forward/rewind and resume playback, if playing. 181 | - (void) rewind; // skip backwards in a playing track 182 | - (void) stop; // stop playback 183 | - (void) update; // update the specified iPod 184 | - (void) eject; // eject the specified iPod 185 | - (void) subscribe:(NSString *)x; // subscribe to a podcast feed 186 | - (void) updateAllPodcasts; // update all subscribed podcast feeds 187 | - (void) updatePodcast; // update podcast feed 188 | - (void) openLocation:(NSString *)x; // Opens a Music Store or audio stream URL 189 | 190 | @end 191 | 192 | // an item 193 | @interface iTunesItem : SBObject 194 | 195 | @property (copy, readonly) SBObject *container; // the container of the item 196 | - (NSInteger) id; // the id of the item 197 | @property (readonly) NSInteger index; // The index of the item in internal application order. 198 | @property (copy) NSString *name; // the name of the item 199 | @property (copy, readonly) NSString *persistentID; // the id of the item as a hexidecimal string. This id does not change over time. 200 | 201 | - (void) printPrintDialog:(BOOL)printDialog withProperties:(iTunesPrintSettings *)withProperties kind:(iTunesEKnd)kind theme:(NSString *)theme; // Print the specified object(s) 202 | - (void) close; // Close an object 203 | - (void) delete; // Delete an element from an object 204 | - (SBObject *) duplicateTo:(SBObject *)to; // Duplicate one or more object(s) 205 | - (BOOL) exists; // Verify if an object exists 206 | - (void) open; // open the specified object(s) 207 | - (void) playOnce:(BOOL)once; // play the current track or the specified track or file. 208 | - (void) reveal; // reveal and select a track or playlist 209 | 210 | @end 211 | 212 | // a piece of art within a track 213 | @interface iTunesArtwork : iTunesItem 214 | 215 | @property (copy) NSImage *data; // data for this artwork, in the form of a picture 216 | @property (copy) NSString *objectDescription; // description of artwork as a string 217 | @property (readonly) BOOL downloaded; // was this artwork downloaded by iTunes? 218 | @property (copy, readonly) NSNumber *format; // the data format for this piece of artwork 219 | @property NSInteger kind; // kind or purpose of this piece of artwork 220 | @property (copy) NSData *rawData; // data for this artwork, in original format 221 | 222 | 223 | @end 224 | 225 | // converts a track to a specific file format 226 | @interface iTunesEncoder : iTunesItem 227 | 228 | @property (copy, readonly) NSString *format; // the data format created by the encoder 229 | 230 | 231 | @end 232 | 233 | // equalizer preset configuration 234 | @interface iTunesEQPreset : iTunesItem 235 | 236 | @property double band1; // the equalizer 32 Hz band level (-12.0 dB to +12.0 dB) 237 | @property double band2; // the equalizer 64 Hz band level (-12.0 dB to +12.0 dB) 238 | @property double band3; // the equalizer 125 Hz band level (-12.0 dB to +12.0 dB) 239 | @property double band4; // the equalizer 250 Hz band level (-12.0 dB to +12.0 dB) 240 | @property double band5; // the equalizer 500 Hz band level (-12.0 dB to +12.0 dB) 241 | @property double band6; // the equalizer 1 kHz band level (-12.0 dB to +12.0 dB) 242 | @property double band7; // the equalizer 2 kHz band level (-12.0 dB to +12.0 dB) 243 | @property double band8; // the equalizer 4 kHz band level (-12.0 dB to +12.0 dB) 244 | @property double band9; // the equalizer 8 kHz band level (-12.0 dB to +12.0 dB) 245 | @property double band10; // the equalizer 16 kHz band level (-12.0 dB to +12.0 dB) 246 | @property (readonly) BOOL modifiable; // can this preset be modified? 247 | @property double preamp; // the equalizer preamp level (-12.0 dB to +12.0 dB) 248 | @property BOOL updateTracks; // should tracks which refer to this preset be updated when the preset is renamed or deleted? 249 | 250 | 251 | @end 252 | 253 | // a list of songs/streams 254 | @interface iTunesPlaylist : iTunesItem 255 | 256 | - (SBElementArray *) tracks; 257 | 258 | @property (readonly) NSInteger duration; // the total length of all songs (in seconds) 259 | @property (copy) NSString *name; // the name of the playlist 260 | @property (copy, readonly) iTunesPlaylist *parent; // folder which contains this playlist (if any) 261 | @property BOOL shuffle; // play the songs in this playlist in random order? 262 | @property (readonly) long long size; // the total size of all songs (in bytes) 263 | @property iTunesERpt songRepeat; // playback repeat mode 264 | @property (readonly) iTunesESpK specialKind; // special playlist kind 265 | @property (copy, readonly) NSString *time; // the length of all songs in MM:SS format 266 | @property (readonly) BOOL visible; // is this playlist visible in the Source list? 267 | 268 | - (void) moveTo:(SBObject *)to; // Move playlist(s) to a new location 269 | - (iTunesTrack *) searchFor:(NSString *)for_ only:(iTunesESrA)only; // search a playlist for tracks matching the search string. Identical to entering search text in the Search field in iTunes. 270 | 271 | @end 272 | 273 | // a playlist representing an audio CD 274 | @interface iTunesAudioCDPlaylist : iTunesPlaylist 275 | 276 | - (SBElementArray *) audioCDTracks; 277 | 278 | @property (copy) NSString *artist; // the artist of the CD 279 | @property BOOL compilation; // is this CD a compilation album? 280 | @property (copy) NSString *composer; // the composer of the CD 281 | @property NSInteger discCount; // the total number of discs in this CD’s album 282 | @property NSInteger discNumber; // the index of this CD disc in the source album 283 | @property (copy) NSString *genre; // the genre of the CD 284 | @property NSInteger year; // the year the album was recorded/released 285 | 286 | 287 | @end 288 | 289 | // a playlist representing the contents of a portable device 290 | @interface iTunesDevicePlaylist : iTunesPlaylist 291 | 292 | - (SBElementArray *) deviceTracks; 293 | 294 | 295 | @end 296 | 297 | // the master music library playlist 298 | @interface iTunesLibraryPlaylist : iTunesPlaylist 299 | 300 | - (SBElementArray *) fileTracks; 301 | - (SBElementArray *) URLTracks; 302 | - (SBElementArray *) sharedTracks; 303 | 304 | 305 | @end 306 | 307 | // the radio tuner playlist 308 | @interface iTunesRadioTunerPlaylist : iTunesPlaylist 309 | 310 | - (SBElementArray *) URLTracks; 311 | 312 | 313 | @end 314 | 315 | // a music source (music library, CD, device, etc.) 316 | @interface iTunesSource : iTunesItem 317 | 318 | - (SBElementArray *) audioCDPlaylists; 319 | - (SBElementArray *) devicePlaylists; 320 | - (SBElementArray *) libraryPlaylists; 321 | - (SBElementArray *) playlists; 322 | - (SBElementArray *) radioTunerPlaylists; 323 | - (SBElementArray *) userPlaylists; 324 | 325 | @property (readonly) long long capacity; // the total size of the source if it has a fixed size 326 | @property (readonly) long long freeSpace; // the free space on the source if it has a fixed size 327 | @property (readonly) iTunesESrc kind; 328 | 329 | - (void) update; // update the specified iPod 330 | - (void) eject; // eject the specified iPod 331 | 332 | @end 333 | 334 | // playable audio source 335 | @interface iTunesTrack : iTunesItem 336 | 337 | - (SBElementArray *) artworks; 338 | 339 | @property (copy) NSString *album; // the album name of the track 340 | @property (copy) NSString *albumArtist; // the album artist of the track 341 | @property NSInteger albumRating; // the rating of the album for this track (0 to 100) 342 | @property (readonly) iTunesERtK albumRatingKind; // the rating kind of the album rating for this track 343 | @property (copy) NSString *artist; // the artist/source of the track 344 | @property (readonly) NSInteger bitRate; // the bit rate of the track (in kbps) 345 | @property double bookmark; // the bookmark time of the track in seconds 346 | @property BOOL bookmarkable; // is the playback position for this track remembered? 347 | @property NSInteger bpm; // the tempo of this track in beats per minute 348 | @property (copy) NSString *category; // the category of the track 349 | @property (copy) NSString *comment; // freeform notes about the track 350 | @property BOOL compilation; // is this track from a compilation album? 351 | @property (copy) NSString *composer; // the composer of the track 352 | @property (readonly) NSInteger databaseID; // the common, unique ID for this track. If two tracks in different playlists have the same database ID, they are sharing the same data. 353 | @property (copy, readonly) NSDate *dateAdded; // the date the track was added to the playlist 354 | @property (copy) NSString *objectDescription; // the description of the track 355 | @property NSInteger discCount; // the total number of discs in the source album 356 | @property NSInteger discNumber; // the index of the disc containing this track on the source album 357 | @property (readonly) double duration; // the length of the track in seconds 358 | @property BOOL enabled; // is this track checked for playback? 359 | @property (copy) NSString *episodeID; // the episode ID of the track 360 | @property NSInteger episodeNumber; // the episode number of the track 361 | @property (copy) NSString *EQ; // the name of the EQ preset of the track 362 | @property double finish; // the stop time of the track in seconds 363 | @property BOOL gapless; // is this track from a gapless album? 364 | @property (copy) NSString *genre; // the music/audio genre (category) of the track 365 | @property (copy) NSString *grouping; // the grouping (piece) of the track. Generally used to denote movements within a classical work. 366 | @property (copy, readonly) NSString *kind; // a text description of the track 367 | @property (copy) NSString *longDescription; 368 | @property (copy) NSString *lyrics; // the lyrics of the track 369 | @property (copy, readonly) NSDate *modificationDate; // the modification date of the content of this track 370 | @property NSInteger playedCount; // number of times this track has been played 371 | @property (copy) NSDate *playedDate; // the date and time this track was last played 372 | @property (readonly) BOOL podcast; // is this track a podcast episode? 373 | @property NSInteger rating; // the rating of this track (0 to 100) 374 | @property (readonly) iTunesERtK ratingKind; // the rating kind of this track 375 | @property (copy, readonly) NSDate *releaseDate; // the release date of this track 376 | @property (readonly) NSInteger sampleRate; // the sample rate of the track (in Hz) 377 | @property NSInteger seasonNumber; // the season number of the track 378 | @property BOOL shufflable; // is this track included when shuffling? 379 | @property NSInteger skippedCount; // number of times this track has been skipped 380 | @property (copy) NSDate *skippedDate; // the date and time this track was last skipped 381 | @property (copy) NSString *show; // the show name of the track 382 | @property (copy) NSString *sortAlbum; // override string to use for the track when sorting by album 383 | @property (copy) NSString *sortArtist; // override string to use for the track when sorting by artist 384 | @property (copy) NSString *sortAlbumArtist; // override string to use for the track when sorting by album artist 385 | @property (copy) NSString *sortName; // override string to use for the track when sorting by name 386 | @property (copy) NSString *sortComposer; // override string to use for the track when sorting by composer 387 | @property (copy) NSString *sortShow; // override string to use for the track when sorting by show name 388 | @property (readonly) NSInteger size; // the size of the track (in bytes) 389 | @property double start; // the start time of the track in seconds 390 | @property (copy, readonly) NSString *time; // the length of the track in MM:SS format 391 | @property NSInteger trackCount; // the total number of tracks on the source album 392 | @property NSInteger trackNumber; // the index of the track on the source album 393 | @property BOOL unplayed; // is this track unplayed? 394 | @property iTunesEVdK videoKind; // kind of video track 395 | @property NSInteger volumeAdjustment; // relative volume adjustment of the track (-100% to 100%) 396 | @property NSInteger year; // the year the track was recorded/released 397 | 398 | 399 | @end 400 | 401 | // a track on an audio CD 402 | @interface iTunesAudioCDTrack : iTunesTrack 403 | 404 | @property (copy, readonly) NSURL *location; // the location of the file represented by this track 405 | 406 | 407 | @end 408 | 409 | // a track residing on a portable music player 410 | @interface iTunesDeviceTrack : iTunesTrack 411 | 412 | 413 | @end 414 | 415 | // a track representing an audio file (MP3, AIFF, etc.) 416 | @interface iTunesFileTrack : iTunesTrack 417 | 418 | @property (copy) NSURL *location; // the location of the file represented by this track 419 | 420 | - (void) refresh; // update file track information from the current information in the track’s file 421 | 422 | @end 423 | 424 | // a track residing in a shared library 425 | @interface iTunesSharedTrack : iTunesTrack 426 | 427 | 428 | @end 429 | 430 | // a track representing a network stream 431 | @interface iTunesURLTrack : iTunesTrack 432 | 433 | @property (copy) NSString *address; // the URL for this track 434 | 435 | - (void) download; // download podcast episode 436 | 437 | @end 438 | 439 | // custom playlists created by the user 440 | @interface iTunesUserPlaylist : iTunesPlaylist 441 | 442 | - (SBElementArray *) fileTracks; 443 | - (SBElementArray *) URLTracks; 444 | - (SBElementArray *) sharedTracks; 445 | 446 | @property BOOL shared; // is this playlist shared? 447 | @property (readonly) BOOL smart; // is this a Smart Playlist? 448 | 449 | 450 | @end 451 | 452 | // a folder that contains other playlists 453 | @interface iTunesFolderPlaylist : iTunesUserPlaylist 454 | 455 | 456 | @end 457 | 458 | // a visual plug-in 459 | @interface iTunesVisual : iTunesItem 460 | 461 | 462 | @end 463 | 464 | // any window 465 | @interface iTunesWindow : iTunesItem 466 | 467 | @property NSRect bounds; // the boundary rectangle for the window 468 | @property (readonly) BOOL closeable; // does the window have a close box? 469 | @property (readonly) BOOL collapseable; // does the window have a collapse (windowshade) box? 470 | @property BOOL collapsed; // is the window collapsed? 471 | @property NSPoint position; // the upper left position of the window 472 | @property (readonly) BOOL resizable; // is the window resizable? 473 | @property BOOL visible; // is the window visible? 474 | @property (readonly) BOOL zoomable; // is the window zoomable? 475 | @property BOOL zoomed; // is the window zoomed? 476 | 477 | 478 | @end 479 | 480 | // the main iTunes window 481 | @interface iTunesBrowserWindow : iTunesWindow 482 | 483 | @property BOOL minimized; // is the small player visible? 484 | @property (copy, readonly) SBObject *selection; // the selected songs 485 | @property (copy) iTunesPlaylist *view; // the playlist currently displayed in the window 486 | 487 | 488 | @end 489 | 490 | // the iTunes equalizer window 491 | @interface iTunesEQWindow : iTunesWindow 492 | 493 | @property BOOL minimized; // is the small EQ window visible? 494 | 495 | 496 | @end 497 | 498 | // a sub-window showing a single playlist 499 | @interface iTunesPlaylistWindow : iTunesWindow 500 | 501 | @property (copy, readonly) SBObject *selection; // the selected songs 502 | @property (copy, readonly) iTunesPlaylist *view; // the playlist displayed in the window 503 | 504 | 505 | @end 506 | 507 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0042B08B153A9D00001DBD51 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B08A153A9D00001DBD51 /* UIKit.framework */; }; 11 | 0042B08D153A9D00001DBD51 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B08C153A9D00001DBD51 /* Foundation.framework */; }; 12 | 0042B08F153A9D00001DBD51 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B08E153A9D00001DBD51 /* CoreGraphics.framework */; }; 13 | 0042B095153A9D00001DBD51 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0042B093153A9D00001DBD51 /* InfoPlist.strings */; }; 14 | 0042B097153A9D00001DBD51 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B096153A9D00001DBD51 /* main.m */; }; 15 | 0042B09B153A9D00001DBD51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B09A153A9D00001DBD51 /* AppDelegate.m */; }; 16 | 0042B09E153A9D00001DBD51 /* MainStoryboard_iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0042B09C153A9D00001DBD51 /* MainStoryboard_iPhone.storyboard */; }; 17 | 0042B0A1153A9D00001DBD51 /* MainStoryboard_iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0042B09F153A9D00001DBD51 /* MainStoryboard_iPad.storyboard */; }; 18 | 0042B0A4153A9D00001DBD51 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B0A3153A9D00001DBD51 /* MasterViewController.m */; }; 19 | 0042B0A7153A9D00001DBD51 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B0A6153A9D00001DBD51 /* DetailViewController.m */; }; 20 | 0042B0AF153A9D01001DBD51 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B0AE153A9D01001DBD51 /* SenTestingKit.framework */; }; 21 | 0042B0B0153A9D01001DBD51 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B08A153A9D00001DBD51 /* UIKit.framework */; }; 22 | 0042B0B1153A9D01001DBD51 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B08C153A9D00001DBD51 /* Foundation.framework */; }; 23 | 0042B0B9153A9D01001DBD51 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0042B0B7153A9D01001DBD51 /* InfoPlist.strings */; }; 24 | 0042B0BC153A9D01001DBD51 /* iFrisbeeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B0BB153A9D01001DBD51 /* iFrisbeeTests.m */; }; 25 | 0042B0C6153A9E25001DBD51 /* MediaPlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B0C5153A9E25001DBD51 /* MediaPlayer.framework */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 0042B0B2153A9D01001DBD51 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 0042B07D153A9CFF001DBD51 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 0042B085153A9D00001DBD51; 34 | remoteInfo = iFrisbee; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 0042B086153A9D00001DBD51 /* iFrisbee.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iFrisbee.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 0042B08A153A9D00001DBD51 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 41 | 0042B08C153A9D00001DBD51 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 42 | 0042B08E153A9D00001DBD51 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 43 | 0042B092153A9D00001DBD51 /* iFrisbee-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iFrisbee-Info.plist"; sourceTree = ""; }; 44 | 0042B094153A9D00001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 45 | 0042B096153A9D00001DBD51 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 46 | 0042B098153A9D00001DBD51 /* iFrisbee-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "iFrisbee-Prefix.pch"; sourceTree = ""; }; 47 | 0042B099153A9D00001DBD51 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 48 | 0042B09A153A9D00001DBD51 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 49 | 0042B09D153A9D00001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPhone.storyboard; sourceTree = ""; }; 50 | 0042B0A0153A9D00001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard_iPad.storyboard; sourceTree = ""; }; 51 | 0042B0A2153A9D00001DBD51 /* MasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 52 | 0042B0A3153A9D00001DBD51 /* MasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 53 | 0042B0A5153A9D00001DBD51 /* DetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 54 | 0042B0A6153A9D00001DBD51 /* DetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 55 | 0042B0AD153A9D01001DBD51 /* iFrisbeeTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = iFrisbeeTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 0042B0AE153A9D01001DBD51 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 57 | 0042B0B6153A9D01001DBD51 /* iFrisbeeTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iFrisbeeTests-Info.plist"; sourceTree = ""; }; 58 | 0042B0B8153A9D01001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 59 | 0042B0BA153A9D01001DBD51 /* iFrisbeeTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iFrisbeeTests.h; sourceTree = ""; }; 60 | 0042B0BB153A9D01001DBD51 /* iFrisbeeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iFrisbeeTests.m; sourceTree = ""; }; 61 | 0042B0C5153A9E25001DBD51 /* MediaPlayer.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MediaPlayer.framework; path = System/Library/Frameworks/MediaPlayer.framework; sourceTree = SDKROOT; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 0042B083153A9D00001DBD51 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 0042B0C6153A9E25001DBD51 /* MediaPlayer.framework in Frameworks */, 70 | 0042B08B153A9D00001DBD51 /* UIKit.framework in Frameworks */, 71 | 0042B08D153A9D00001DBD51 /* Foundation.framework in Frameworks */, 72 | 0042B08F153A9D00001DBD51 /* CoreGraphics.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | 0042B0A9153A9D01001DBD51 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | 0042B0AF153A9D01001DBD51 /* SenTestingKit.framework in Frameworks */, 81 | 0042B0B0153A9D01001DBD51 /* UIKit.framework in Frameworks */, 82 | 0042B0B1153A9D01001DBD51 /* Foundation.framework in Frameworks */, 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | /* End PBXFrameworksBuildPhase section */ 87 | 88 | /* Begin PBXGroup section */ 89 | 0042B07B153A9CFF001DBD51 = { 90 | isa = PBXGroup; 91 | children = ( 92 | 0042B0C5153A9E25001DBD51 /* MediaPlayer.framework */, 93 | 0042B090153A9D00001DBD51 /* iFrisbee */, 94 | 0042B0B4153A9D01001DBD51 /* iFrisbeeTests */, 95 | 0042B089153A9D00001DBD51 /* Frameworks */, 96 | 0042B087153A9D00001DBD51 /* Products */, 97 | ); 98 | sourceTree = ""; 99 | }; 100 | 0042B087153A9D00001DBD51 /* Products */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 0042B086153A9D00001DBD51 /* iFrisbee.app */, 104 | 0042B0AD153A9D01001DBD51 /* iFrisbeeTests.octest */, 105 | ); 106 | name = Products; 107 | sourceTree = ""; 108 | }; 109 | 0042B089153A9D00001DBD51 /* Frameworks */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 0042B08A153A9D00001DBD51 /* UIKit.framework */, 113 | 0042B08C153A9D00001DBD51 /* Foundation.framework */, 114 | 0042B08E153A9D00001DBD51 /* CoreGraphics.framework */, 115 | 0042B0AE153A9D01001DBD51 /* SenTestingKit.framework */, 116 | ); 117 | name = Frameworks; 118 | sourceTree = ""; 119 | }; 120 | 0042B090153A9D00001DBD51 /* iFrisbee */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 0042B099153A9D00001DBD51 /* AppDelegate.h */, 124 | 0042B09A153A9D00001DBD51 /* AppDelegate.m */, 125 | 0042B09C153A9D00001DBD51 /* MainStoryboard_iPhone.storyboard */, 126 | 0042B09F153A9D00001DBD51 /* MainStoryboard_iPad.storyboard */, 127 | 0042B0A2153A9D00001DBD51 /* MasterViewController.h */, 128 | 0042B0A3153A9D00001DBD51 /* MasterViewController.m */, 129 | 0042B0A5153A9D00001DBD51 /* DetailViewController.h */, 130 | 0042B0A6153A9D00001DBD51 /* DetailViewController.m */, 131 | 0042B091153A9D00001DBD51 /* Supporting Files */, 132 | ); 133 | path = iFrisbee; 134 | sourceTree = ""; 135 | }; 136 | 0042B091153A9D00001DBD51 /* Supporting Files */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 0042B092153A9D00001DBD51 /* iFrisbee-Info.plist */, 140 | 0042B093153A9D00001DBD51 /* InfoPlist.strings */, 141 | 0042B096153A9D00001DBD51 /* main.m */, 142 | 0042B098153A9D00001DBD51 /* iFrisbee-Prefix.pch */, 143 | ); 144 | name = "Supporting Files"; 145 | sourceTree = ""; 146 | }; 147 | 0042B0B4153A9D01001DBD51 /* iFrisbeeTests */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 0042B0BA153A9D01001DBD51 /* iFrisbeeTests.h */, 151 | 0042B0BB153A9D01001DBD51 /* iFrisbeeTests.m */, 152 | 0042B0B5153A9D01001DBD51 /* Supporting Files */, 153 | ); 154 | path = iFrisbeeTests; 155 | sourceTree = ""; 156 | }; 157 | 0042B0B5153A9D01001DBD51 /* Supporting Files */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 0042B0B6153A9D01001DBD51 /* iFrisbeeTests-Info.plist */, 161 | 0042B0B7153A9D01001DBD51 /* InfoPlist.strings */, 162 | ); 163 | name = "Supporting Files"; 164 | sourceTree = ""; 165 | }; 166 | /* End PBXGroup section */ 167 | 168 | /* Begin PBXNativeTarget section */ 169 | 0042B085153A9D00001DBD51 /* iFrisbee */ = { 170 | isa = PBXNativeTarget; 171 | buildConfigurationList = 0042B0BF153A9D01001DBD51 /* Build configuration list for PBXNativeTarget "iFrisbee" */; 172 | buildPhases = ( 173 | 0042B082153A9D00001DBD51 /* Sources */, 174 | 0042B083153A9D00001DBD51 /* Frameworks */, 175 | 0042B084153A9D00001DBD51 /* Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = iFrisbee; 182 | productName = iFrisbee; 183 | productReference = 0042B086153A9D00001DBD51 /* iFrisbee.app */; 184 | productType = "com.apple.product-type.application"; 185 | }; 186 | 0042B0AC153A9D01001DBD51 /* iFrisbeeTests */ = { 187 | isa = PBXNativeTarget; 188 | buildConfigurationList = 0042B0C2153A9D01001DBD51 /* Build configuration list for PBXNativeTarget "iFrisbeeTests" */; 189 | buildPhases = ( 190 | 0042B0A8153A9D01001DBD51 /* Sources */, 191 | 0042B0A9153A9D01001DBD51 /* Frameworks */, 192 | 0042B0AA153A9D01001DBD51 /* Resources */, 193 | 0042B0AB153A9D01001DBD51 /* ShellScript */, 194 | ); 195 | buildRules = ( 196 | ); 197 | dependencies = ( 198 | 0042B0B3153A9D01001DBD51 /* PBXTargetDependency */, 199 | ); 200 | name = iFrisbeeTests; 201 | productName = iFrisbeeTests; 202 | productReference = 0042B0AD153A9D01001DBD51 /* iFrisbeeTests.octest */; 203 | productType = "com.apple.product-type.bundle"; 204 | }; 205 | /* End PBXNativeTarget section */ 206 | 207 | /* Begin PBXProject section */ 208 | 0042B07D153A9CFF001DBD51 /* Project object */ = { 209 | isa = PBXProject; 210 | attributes = { 211 | LastUpgradeCheck = 0430; 212 | ORGANIZATIONNAME = "The Greatest Company"; 213 | }; 214 | buildConfigurationList = 0042B080153A9CFF001DBD51 /* Build configuration list for PBXProject "iFrisbee" */; 215 | compatibilityVersion = "Xcode 3.2"; 216 | developmentRegion = English; 217 | hasScannedForEncodings = 0; 218 | knownRegions = ( 219 | en, 220 | ); 221 | mainGroup = 0042B07B153A9CFF001DBD51; 222 | productRefGroup = 0042B087153A9D00001DBD51 /* Products */; 223 | projectDirPath = ""; 224 | projectRoot = ""; 225 | targets = ( 226 | 0042B085153A9D00001DBD51 /* iFrisbee */, 227 | 0042B0AC153A9D01001DBD51 /* iFrisbeeTests */, 228 | ); 229 | }; 230 | /* End PBXProject section */ 231 | 232 | /* Begin PBXResourcesBuildPhase section */ 233 | 0042B084153A9D00001DBD51 /* Resources */ = { 234 | isa = PBXResourcesBuildPhase; 235 | buildActionMask = 2147483647; 236 | files = ( 237 | 0042B095153A9D00001DBD51 /* InfoPlist.strings in Resources */, 238 | 0042B09E153A9D00001DBD51 /* MainStoryboard_iPhone.storyboard in Resources */, 239 | 0042B0A1153A9D00001DBD51 /* MainStoryboard_iPad.storyboard in Resources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | 0042B0AA153A9D01001DBD51 /* Resources */ = { 244 | isa = PBXResourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | 0042B0B9153A9D01001DBD51 /* InfoPlist.strings in Resources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | /* End PBXResourcesBuildPhase section */ 252 | 253 | /* Begin PBXShellScriptBuildPhase section */ 254 | 0042B0AB153A9D01001DBD51 /* ShellScript */ = { 255 | isa = PBXShellScriptBuildPhase; 256 | buildActionMask = 2147483647; 257 | files = ( 258 | ); 259 | inputPaths = ( 260 | ); 261 | outputPaths = ( 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | shellPath = /bin/sh; 265 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 266 | }; 267 | /* End PBXShellScriptBuildPhase section */ 268 | 269 | /* Begin PBXSourcesBuildPhase section */ 270 | 0042B082153A9D00001DBD51 /* Sources */ = { 271 | isa = PBXSourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | 0042B097153A9D00001DBD51 /* main.m in Sources */, 275 | 0042B09B153A9D00001DBD51 /* AppDelegate.m in Sources */, 276 | 0042B0A4153A9D00001DBD51 /* MasterViewController.m in Sources */, 277 | 0042B0A7153A9D00001DBD51 /* DetailViewController.m in Sources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | 0042B0A8153A9D01001DBD51 /* Sources */ = { 282 | isa = PBXSourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | 0042B0BC153A9D01001DBD51 /* iFrisbeeTests.m in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | /* End PBXSourcesBuildPhase section */ 290 | 291 | /* Begin PBXTargetDependency section */ 292 | 0042B0B3153A9D01001DBD51 /* PBXTargetDependency */ = { 293 | isa = PBXTargetDependency; 294 | target = 0042B085153A9D00001DBD51 /* iFrisbee */; 295 | targetProxy = 0042B0B2153A9D01001DBD51 /* PBXContainerItemProxy */; 296 | }; 297 | /* End PBXTargetDependency section */ 298 | 299 | /* Begin PBXVariantGroup section */ 300 | 0042B093153A9D00001DBD51 /* InfoPlist.strings */ = { 301 | isa = PBXVariantGroup; 302 | children = ( 303 | 0042B094153A9D00001DBD51 /* en */, 304 | ); 305 | name = InfoPlist.strings; 306 | sourceTree = ""; 307 | }; 308 | 0042B09C153A9D00001DBD51 /* MainStoryboard_iPhone.storyboard */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 0042B09D153A9D00001DBD51 /* en */, 312 | ); 313 | name = MainStoryboard_iPhone.storyboard; 314 | sourceTree = ""; 315 | }; 316 | 0042B09F153A9D00001DBD51 /* MainStoryboard_iPad.storyboard */ = { 317 | isa = PBXVariantGroup; 318 | children = ( 319 | 0042B0A0153A9D00001DBD51 /* en */, 320 | ); 321 | name = MainStoryboard_iPad.storyboard; 322 | sourceTree = ""; 323 | }; 324 | 0042B0B7153A9D01001DBD51 /* InfoPlist.strings */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | 0042B0B8153A9D01001DBD51 /* en */, 328 | ); 329 | name = InfoPlist.strings; 330 | sourceTree = ""; 331 | }; 332 | /* End PBXVariantGroup section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | 0042B0BD153A9D01001DBD51 /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 342 | COPY_PHASE_STRIP = NO; 343 | GCC_C_LANGUAGE_STANDARD = gnu99; 344 | GCC_DYNAMIC_NO_PIC = NO; 345 | GCC_OPTIMIZATION_LEVEL = 0; 346 | GCC_PREPROCESSOR_DEFINITIONS = ( 347 | "DEBUG=1", 348 | "$(inherited)", 349 | ); 350 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 351 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 353 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 354 | GCC_WARN_UNUSED_VARIABLE = YES; 355 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 356 | SDKROOT = iphoneos; 357 | TARGETED_DEVICE_FAMILY = "1,2"; 358 | }; 359 | name = Debug; 360 | }; 361 | 0042B0BE153A9D01001DBD51 /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | ALWAYS_SEARCH_USER_PATHS = NO; 365 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 368 | COPY_PHASE_STRIP = YES; 369 | GCC_C_LANGUAGE_STANDARD = gnu99; 370 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 371 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 373 | GCC_WARN_UNUSED_VARIABLE = YES; 374 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 375 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 376 | SDKROOT = iphoneos; 377 | TARGETED_DEVICE_FAMILY = "1,2"; 378 | VALIDATE_PRODUCT = YES; 379 | }; 380 | name = Release; 381 | }; 382 | 0042B0C0153A9D01001DBD51 /* Debug */ = { 383 | isa = XCBuildConfiguration; 384 | buildSettings = { 385 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 386 | GCC_PREFIX_HEADER = "iFrisbee/iFrisbee-Prefix.pch"; 387 | INFOPLIST_FILE = "iFrisbee/iFrisbee-Info.plist"; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | WRAPPER_EXTENSION = app; 390 | }; 391 | name = Debug; 392 | }; 393 | 0042B0C1153A9D01001DBD51 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 397 | GCC_PREFIX_HEADER = "iFrisbee/iFrisbee-Prefix.pch"; 398 | INFOPLIST_FILE = "iFrisbee/iFrisbee-Info.plist"; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | WRAPPER_EXTENSION = app; 401 | }; 402 | name = Release; 403 | }; 404 | 0042B0C3153A9D01001DBD51 /* Debug */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iFrisbee.app/iFrisbee"; 408 | FRAMEWORK_SEARCH_PATHS = ( 409 | "$(SDKROOT)/Developer/Library/Frameworks", 410 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 411 | ); 412 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 413 | GCC_PREFIX_HEADER = "iFrisbee/iFrisbee-Prefix.pch"; 414 | INFOPLIST_FILE = "iFrisbeeTests/iFrisbeeTests-Info.plist"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | TEST_HOST = "$(BUNDLE_LOADER)"; 417 | WRAPPER_EXTENSION = octest; 418 | }; 419 | name = Debug; 420 | }; 421 | 0042B0C4153A9D01001DBD51 /* Release */ = { 422 | isa = XCBuildConfiguration; 423 | buildSettings = { 424 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/iFrisbee.app/iFrisbee"; 425 | FRAMEWORK_SEARCH_PATHS = ( 426 | "$(SDKROOT)/Developer/Library/Frameworks", 427 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 428 | ); 429 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 430 | GCC_PREFIX_HEADER = "iFrisbee/iFrisbee-Prefix.pch"; 431 | INFOPLIST_FILE = "iFrisbeeTests/iFrisbeeTests-Info.plist"; 432 | PRODUCT_NAME = "$(TARGET_NAME)"; 433 | TEST_HOST = "$(BUNDLE_LOADER)"; 434 | WRAPPER_EXTENSION = octest; 435 | }; 436 | name = Release; 437 | }; 438 | /* End XCBuildConfiguration section */ 439 | 440 | /* Begin XCConfigurationList section */ 441 | 0042B080153A9CFF001DBD51 /* Build configuration list for PBXProject "iFrisbee" */ = { 442 | isa = XCConfigurationList; 443 | buildConfigurations = ( 444 | 0042B0BD153A9D01001DBD51 /* Debug */, 445 | 0042B0BE153A9D01001DBD51 /* Release */, 446 | ); 447 | defaultConfigurationIsVisible = 0; 448 | defaultConfigurationName = Release; 449 | }; 450 | 0042B0BF153A9D01001DBD51 /* Build configuration list for PBXNativeTarget "iFrisbee" */ = { 451 | isa = XCConfigurationList; 452 | buildConfigurations = ( 453 | 0042B0C0153A9D01001DBD51 /* Debug */, 454 | 0042B0C1153A9D01001DBD51 /* Release */, 455 | ); 456 | defaultConfigurationIsVisible = 0; 457 | }; 458 | 0042B0C2153A9D01001DBD51 /* Build configuration list for PBXNativeTarget "iFrisbeeTests" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 0042B0C3153A9D01001DBD51 /* Debug */, 462 | 0042B0C4153A9D01001DBD51 /* Release */, 463 | ); 464 | defaultConfigurationIsVisible = 0; 465 | }; 466 | /* End XCConfigurationList section */ 467 | }; 468 | rootObject = 0042B07D153A9CFF001DBD51 /* Project object */; 469 | } 470 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | 12 | @implementation AppDelegate 13 | 14 | @synthesize window = _window; 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | // Override point for customization after application launch. 19 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 20 | UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController; 21 | UINavigationController *navigationController = [splitViewController.viewControllers lastObject]; 22 | splitViewController.delegate = (id)navigationController.topViewController; 23 | } 24 | 25 | 26 | 27 | return YES; 28 | } 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application 31 | { 32 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 33 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 34 | } 35 | 36 | - (void)applicationDidEnterBackground:(UIApplication *)application 37 | { 38 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 39 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | } 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application 43 | { 44 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 45 | } 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application 48 | { 49 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 50 | } 51 | 52 | - (void)applicationWillTerminate:(UIApplication *)application 53 | { 54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @property (strong, nonatomic) id detailItem; 14 | 15 | @property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | 11 | @interface DetailViewController () 12 | @property (strong, nonatomic) UIPopoverController *masterPopoverController; 13 | - (void)configureView; 14 | @end 15 | 16 | @implementation DetailViewController 17 | 18 | @synthesize detailItem = _detailItem; 19 | @synthesize detailDescriptionLabel = _detailDescriptionLabel; 20 | @synthesize masterPopoverController = _masterPopoverController; 21 | 22 | #pragma mark - Managing the detail item 23 | 24 | - (void)setDetailItem:(id)newDetailItem 25 | { 26 | if (_detailItem != newDetailItem) { 27 | _detailItem = newDetailItem; 28 | 29 | // Update the view. 30 | [self configureView]; 31 | } 32 | 33 | if (self.masterPopoverController != nil) { 34 | [self.masterPopoverController dismissPopoverAnimated:YES]; 35 | } 36 | } 37 | 38 | - (void)configureView 39 | { 40 | // Update the user interface for the detail item. 41 | 42 | if (self.detailItem) { 43 | self.detailDescriptionLabel.text = [self.detailItem description]; 44 | } 45 | } 46 | 47 | - (void)viewDidLoad 48 | { 49 | [super viewDidLoad]; 50 | // Do any additional setup after loading the view, typically from a nib. 51 | [self configureView]; 52 | } 53 | 54 | - (void)viewDidUnload 55 | { 56 | [super viewDidUnload]; 57 | // Release any retained subviews of the main view. 58 | self.detailDescriptionLabel = nil; 59 | } 60 | 61 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 62 | { 63 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 64 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 65 | } else { 66 | return YES; 67 | } 68 | } 69 | 70 | #pragma mark - Split view 71 | 72 | - (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController 73 | { 74 | barButtonItem.title = NSLocalizedString(@"Master", @"Master"); 75 | [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; 76 | self.masterPopoverController = popoverController; 77 | } 78 | 79 | - (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem 80 | { 81 | // Called when the view is shown again in the split view, invalidating the button and popover controller. 82 | [self.navigationItem setLeftBarButtonItem:nil animated:YES]; 83 | self.masterPopoverController = nil; 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/MasterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.h 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DetailViewController; 12 | 13 | @interface MasterViewController : UITableViewController 14 | 15 | @property (strong, nonatomic) DetailViewController *detailViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/MasterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.m 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "MasterViewController.h" 10 | #import "DetailViewController.h" 11 | #import 12 | #import 13 | #include 14 | 15 | #define SERVER_IP "50.116.7.184" 16 | //CHANGE HERE 17 | 18 | @interface MasterViewController () { 19 | NSMutableArray *_objects; 20 | } 21 | @end 22 | 23 | @implementation MasterViewController 24 | 25 | @synthesize detailViewController = _detailViewController; 26 | 27 | - (void)awakeFromNib 28 | { 29 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 30 | self.clearsSelectionOnViewWillAppear = NO; 31 | self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); 32 | } 33 | [super awakeFromNib]; 34 | } 35 | 36 | - (void)viewDidLoad 37 | { 38 | [super viewDidLoad]; 39 | // Do any additional setup after loading the view, typically from a nib. 40 | self.navigationItem.leftBarButtonItem = self.editButtonItem; 41 | 42 | UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)]; 43 | self.navigationItem.rightBarButtonItem = addButton; 44 | self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController]; 45 | 46 | } 47 | 48 | - (void)viewDidAppear:(BOOL)animated { 49 | [super viewDidAppear:animated]; 50 | [self becomeFirstResponder]; 51 | } 52 | 53 | - (BOOL)canBecomeFirstResponder { 54 | return YES; 55 | } 56 | 57 | - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event 58 | { 59 | NSLog(@"Motion ended"); 60 | } 61 | 62 | - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event 63 | { 64 | NSLog(@"Motion began"); 65 | 66 | MPMediaItem * song = [[MPMusicPlayerController iPodMusicPlayer] nowPlayingItem]; 67 | NSString * title = [song valueForProperty:MPMediaItemPropertyTitle]; 68 | NSString * album = [song valueForProperty:MPMediaItemPropertyAlbumTitle]; 69 | NSString * artist = [song valueForProperty:MPMediaItemPropertyArtist]; 70 | NSString *time = [NSString stringWithFormat:@"%f", [[MPMusicPlayerController iPodMusicPlayer] currentPlaybackTime]]; 71 | 72 | NSLog(time); 73 | 74 | struct sockaddr_in addr; 75 | int sockfd; 76 | 77 | // Create a socket 78 | sockfd = socket( AF_INET, SOCK_STREAM, 0 ); 79 | addr.sin_family = AF_INET; 80 | addr.sin_addr.s_addr = inet_addr(SERVER_IP); 81 | addr.sin_port = htons( 5003 ); 82 | 83 | int conn = connect(sockfd, &addr, sizeof(addr)); 84 | 85 | if (!conn) { 86 | NSData* data = [[[[[title stringByAppendingString:@" - "] stringByAppendingString:artist] stringByAppendingString:@"|"] stringByAppendingString:time] dataUsingEncoding:NSUTF8StringEncoding]; 87 | ssize_t datasend = send(sockfd, [data bytes], [data length], 0); 88 | close(sockfd); 89 | }else{ 90 | NSLog(@"Did not connect"); 91 | } 92 | 93 | sleep(1); 94 | [[MPMusicPlayerController iPodMusicPlayer] pause]; 95 | 96 | } 97 | 98 | - (void)viewDidUnload 99 | { 100 | [super viewDidUnload]; 101 | // Release any retained subviews of the main view. 102 | } 103 | 104 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 105 | { 106 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 107 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 108 | } else { 109 | return YES; 110 | } 111 | } 112 | 113 | - (void)insertNewObject:(id)sender 114 | { 115 | if (!_objects) { 116 | _objects = [[NSMutableArray alloc] init]; 117 | } 118 | [_objects insertObject:[NSDate date] atIndex:0]; 119 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; 120 | [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; 121 | } 122 | 123 | #pragma mark - Table View 124 | 125 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 126 | { 127 | return 1; 128 | } 129 | 130 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 131 | { 132 | return _objects.count; 133 | } 134 | 135 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 136 | { 137 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; 138 | 139 | NSDate *object = [_objects objectAtIndex:indexPath.row]; 140 | cell.textLabel.text = [object description]; 141 | return cell; 142 | } 143 | 144 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 145 | { 146 | // Return NO if you do not want the specified item to be editable. 147 | return YES; 148 | } 149 | 150 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 151 | { 152 | if (editingStyle == UITableViewCellEditingStyleDelete) { 153 | [_objects removeObjectAtIndex:indexPath.row]; 154 | [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 155 | } else if (editingStyle == UITableViewCellEditingStyleInsert) { 156 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. 157 | } 158 | } 159 | 160 | /* 161 | // Override to support rearranging the table view. 162 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 163 | { 164 | } 165 | */ 166 | 167 | /* 168 | // Override to support conditional rearranging of the table view. 169 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath 170 | { 171 | // Return NO if you do not want the item to be re-orderable. 172 | return YES; 173 | } 174 | */ 175 | 176 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 177 | { 178 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 179 | NSDate *object = [_objects objectAtIndex:indexPath.row]; 180 | self.detailViewController.detailItem = object; 181 | } 182 | } 183 | 184 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 185 | { 186 | if ([[segue identifier] isEqualToString:@"showDetail"]) { 187 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 188 | NSDate *object = [_objects objectAtIndex:indexPath.row]; 189 | [[segue destinationViewController] setDetailItem:object]; 190 | } 191 | } 192 | 193 | @end 194 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/en.lproj/MainStoryboard_iPad.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/en.lproj/MainStoryboard_iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/iFrisbee-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | Frisbee.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | MainStoryboard_iPhone 29 | UIMainStoryboardFile~ipad 30 | MainStoryboard_iPad 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/iFrisbee-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'iFrisbee' target in the 'iFrisbee' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbee/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // iFrisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbeeTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbeeTests/iFrisbeeTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Frisbee.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbeeTests/iFrisbeeTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // iFrisbeeTests.h 3 | // iFrisbeeTests 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface iFrisbeeTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ios/iFrisbee/iFrisbeeTests/iFrisbeeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // iFrisbeeTests.m 3 | // iFrisbeeTests 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "iFrisbeeTests.h" 10 | 11 | @implementation iFrisbeeTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | STFail(@"Unit tests are not implemented yet in iFrisbeeTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /mac/.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0042AFE9153A5E51001DBD51 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042AFE8153A5E51001DBD51 /* Cocoa.framework */; }; 11 | 0042AFF3153A5E51001DBD51 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0042AFF1153A5E51001DBD51 /* InfoPlist.strings */; }; 12 | 0042AFF5153A5E51001DBD51 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042AFF4153A5E51001DBD51 /* main.m */; }; 13 | 0042AFF9153A5E51001DBD51 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 0042AFF7153A5E51001DBD51 /* Credits.rtf */; }; 14 | 0042AFFC153A5E51001DBD51 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042AFFB153A5E51001DBD51 /* AppDelegate.m */; }; 15 | 0042AFFF153A5E52001DBD51 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0042AFFD153A5E52001DBD51 /* MainMenu.xib */; }; 16 | 0042B007153A5E52001DBD51 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042B006153A5E52001DBD51 /* SenTestingKit.framework */; }; 17 | 0042B008153A5E52001DBD51 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0042AFE8153A5E51001DBD51 /* Cocoa.framework */; }; 18 | 0042B010153A5E52001DBD51 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0042B00E153A5E52001DBD51 /* InfoPlist.strings */; }; 19 | 0042B013153A5E52001DBD51 /* FrisbeeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0042B012153A5E52001DBD51 /* FrisbeeTests.m */; }; 20 | 0042B01E153A61AA001DBD51 /* growlTunes.png in Resources */ = {isa = PBXBuildFile; fileRef = 0042B01D153A61AA001DBD51 /* growlTunes.png */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 0042B009153A5E52001DBD51 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 0042AFDB153A5E51001DBD51 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 0042AFE3153A5E51001DBD51; 29 | remoteInfo = Frisbee; 30 | }; 31 | /* End PBXContainerItemProxy section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 0042AFE4153A5E51001DBD51 /* Frisbee.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Frisbee.app; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 0042AFE8153A5E51001DBD51 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 36 | 0042AFEB153A5E51001DBD51 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 37 | 0042AFEC153A5E51001DBD51 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 38 | 0042AFED153A5E51001DBD51 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 39 | 0042AFF0153A5E51001DBD51 /* Frisbee-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Frisbee-Info.plist"; sourceTree = ""; }; 40 | 0042AFF2153A5E51001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 41 | 0042AFF4153A5E51001DBD51 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | 0042AFF6153A5E51001DBD51 /* Frisbee-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Frisbee-Prefix.pch"; sourceTree = ""; }; 43 | 0042AFF8153A5E51001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 44 | 0042AFFA153A5E51001DBD51 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 45 | 0042AFFB153A5E51001DBD51 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 46 | 0042AFFE153A5E52001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 47 | 0042B005153A5E52001DBD51 /* FrisbeeTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FrisbeeTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 0042B006153A5E52001DBD51 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 49 | 0042B00D153A5E52001DBD51 /* FrisbeeTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FrisbeeTests-Info.plist"; sourceTree = ""; }; 50 | 0042B00F153A5E52001DBD51 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 51 | 0042B011153A5E52001DBD51 /* FrisbeeTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrisbeeTests.h; sourceTree = ""; }; 52 | 0042B012153A5E52001DBD51 /* FrisbeeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FrisbeeTests.m; sourceTree = ""; }; 53 | 0042B01D153A61AA001DBD51 /* growlTunes.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = growlTunes.png; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 0042AFE1153A5E51001DBD51 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 0042AFE9153A5E51001DBD51 /* Cocoa.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | 0042B001153A5E52001DBD51 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 0042B007153A5E52001DBD51 /* SenTestingKit.framework in Frameworks */, 70 | 0042B008153A5E52001DBD51 /* Cocoa.framework in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | /* End PBXFrameworksBuildPhase section */ 75 | 76 | /* Begin PBXGroup section */ 77 | 0042AFD9153A5E51001DBD51 = { 78 | isa = PBXGroup; 79 | children = ( 80 | 0042B01C153A6187001DBD51 /* Resources */, 81 | 0042AFEE153A5E51001DBD51 /* Frisbee */, 82 | 0042B00B153A5E52001DBD51 /* FrisbeeTests */, 83 | 0042AFE7153A5E51001DBD51 /* Frameworks */, 84 | 0042AFE5153A5E51001DBD51 /* Products */, 85 | ); 86 | sourceTree = ""; 87 | }; 88 | 0042AFE5153A5E51001DBD51 /* Products */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 0042AFE4153A5E51001DBD51 /* Frisbee.app */, 92 | 0042B005153A5E52001DBD51 /* FrisbeeTests.octest */, 93 | ); 94 | name = Products; 95 | sourceTree = ""; 96 | }; 97 | 0042AFE7153A5E51001DBD51 /* Frameworks */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 0042AFE8153A5E51001DBD51 /* Cocoa.framework */, 101 | 0042B006153A5E52001DBD51 /* SenTestingKit.framework */, 102 | 0042AFEA153A5E51001DBD51 /* Other Frameworks */, 103 | ); 104 | name = Frameworks; 105 | sourceTree = ""; 106 | }; 107 | 0042AFEA153A5E51001DBD51 /* Other Frameworks */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 0042AFEB153A5E51001DBD51 /* AppKit.framework */, 111 | 0042AFEC153A5E51001DBD51 /* CoreData.framework */, 112 | 0042AFED153A5E51001DBD51 /* Foundation.framework */, 113 | ); 114 | name = "Other Frameworks"; 115 | sourceTree = ""; 116 | }; 117 | 0042AFEE153A5E51001DBD51 /* Frisbee */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 0042AFFA153A5E51001DBD51 /* AppDelegate.h */, 121 | 0042AFFB153A5E51001DBD51 /* AppDelegate.m */, 122 | 0042AFFD153A5E52001DBD51 /* MainMenu.xib */, 123 | 0042AFEF153A5E51001DBD51 /* Supporting Files */, 124 | ); 125 | path = Frisbee; 126 | sourceTree = ""; 127 | }; 128 | 0042AFEF153A5E51001DBD51 /* Supporting Files */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 0042AFF0153A5E51001DBD51 /* Frisbee-Info.plist */, 132 | 0042AFF1153A5E51001DBD51 /* InfoPlist.strings */, 133 | 0042AFF4153A5E51001DBD51 /* main.m */, 134 | 0042AFF6153A5E51001DBD51 /* Frisbee-Prefix.pch */, 135 | 0042AFF7153A5E51001DBD51 /* Credits.rtf */, 136 | ); 137 | name = "Supporting Files"; 138 | sourceTree = ""; 139 | }; 140 | 0042B00B153A5E52001DBD51 /* FrisbeeTests */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 0042B011153A5E52001DBD51 /* FrisbeeTests.h */, 144 | 0042B012153A5E52001DBD51 /* FrisbeeTests.m */, 145 | 0042B00C153A5E52001DBD51 /* Supporting Files */, 146 | ); 147 | path = FrisbeeTests; 148 | sourceTree = ""; 149 | }; 150 | 0042B00C153A5E52001DBD51 /* Supporting Files */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 0042B00D153A5E52001DBD51 /* FrisbeeTests-Info.plist */, 154 | 0042B00E153A5E52001DBD51 /* InfoPlist.strings */, 155 | ); 156 | name = "Supporting Files"; 157 | sourceTree = ""; 158 | }; 159 | 0042B01C153A6187001DBD51 /* Resources */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 0042B01D153A61AA001DBD51 /* growlTunes.png */, 163 | ); 164 | name = Resources; 165 | sourceTree = ""; 166 | }; 167 | /* End PBXGroup section */ 168 | 169 | /* Begin PBXNativeTarget section */ 170 | 0042AFE3153A5E51001DBD51 /* Frisbee */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = 0042B016153A5E52001DBD51 /* Build configuration list for PBXNativeTarget "Frisbee" */; 173 | buildPhases = ( 174 | 0042AFE0153A5E51001DBD51 /* Sources */, 175 | 0042AFE1153A5E51001DBD51 /* Frameworks */, 176 | 0042AFE2153A5E51001DBD51 /* Resources */, 177 | ); 178 | buildRules = ( 179 | ); 180 | dependencies = ( 181 | ); 182 | name = Frisbee; 183 | productName = Frisbee; 184 | productReference = 0042AFE4153A5E51001DBD51 /* Frisbee.app */; 185 | productType = "com.apple.product-type.application"; 186 | }; 187 | 0042B004153A5E52001DBD51 /* FrisbeeTests */ = { 188 | isa = PBXNativeTarget; 189 | buildConfigurationList = 0042B019153A5E52001DBD51 /* Build configuration list for PBXNativeTarget "FrisbeeTests" */; 190 | buildPhases = ( 191 | 0042B000153A5E52001DBD51 /* Sources */, 192 | 0042B001153A5E52001DBD51 /* Frameworks */, 193 | 0042B002153A5E52001DBD51 /* Resources */, 194 | 0042B003153A5E52001DBD51 /* ShellScript */, 195 | ); 196 | buildRules = ( 197 | ); 198 | dependencies = ( 199 | 0042B00A153A5E52001DBD51 /* PBXTargetDependency */, 200 | ); 201 | name = FrisbeeTests; 202 | productName = FrisbeeTests; 203 | productReference = 0042B005153A5E52001DBD51 /* FrisbeeTests.octest */; 204 | productType = "com.apple.product-type.bundle"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | 0042AFDB153A5E51001DBD51 /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | LastUpgradeCheck = 0430; 213 | ORGANIZATIONNAME = "The Greatest Company"; 214 | }; 215 | buildConfigurationList = 0042AFDE153A5E51001DBD51 /* Build configuration list for PBXProject "Frisbee" */; 216 | compatibilityVersion = "Xcode 3.2"; 217 | developmentRegion = English; 218 | hasScannedForEncodings = 0; 219 | knownRegions = ( 220 | en, 221 | ); 222 | mainGroup = 0042AFD9153A5E51001DBD51; 223 | productRefGroup = 0042AFE5153A5E51001DBD51 /* Products */; 224 | projectDirPath = ""; 225 | projectRoot = ""; 226 | targets = ( 227 | 0042AFE3153A5E51001DBD51 /* Frisbee */, 228 | 0042B004153A5E52001DBD51 /* FrisbeeTests */, 229 | ); 230 | }; 231 | /* End PBXProject section */ 232 | 233 | /* Begin PBXResourcesBuildPhase section */ 234 | 0042AFE2153A5E51001DBD51 /* Resources */ = { 235 | isa = PBXResourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 0042AFF3153A5E51001DBD51 /* InfoPlist.strings in Resources */, 239 | 0042AFF9153A5E51001DBD51 /* Credits.rtf in Resources */, 240 | 0042AFFF153A5E52001DBD51 /* MainMenu.xib in Resources */, 241 | 0042B01E153A61AA001DBD51 /* growlTunes.png in Resources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | 0042B002153A5E52001DBD51 /* Resources */ = { 246 | isa = PBXResourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | 0042B010153A5E52001DBD51 /* InfoPlist.strings in Resources */, 250 | ); 251 | runOnlyForDeploymentPostprocessing = 0; 252 | }; 253 | /* End PBXResourcesBuildPhase section */ 254 | 255 | /* Begin PBXShellScriptBuildPhase section */ 256 | 0042B003153A5E52001DBD51 /* ShellScript */ = { 257 | isa = PBXShellScriptBuildPhase; 258 | buildActionMask = 2147483647; 259 | files = ( 260 | ); 261 | inputPaths = ( 262 | ); 263 | outputPaths = ( 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | shellPath = /bin/sh; 267 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 268 | }; 269 | /* End PBXShellScriptBuildPhase section */ 270 | 271 | /* Begin PBXSourcesBuildPhase section */ 272 | 0042AFE0153A5E51001DBD51 /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | 0042AFF5153A5E51001DBD51 /* main.m in Sources */, 277 | 0042AFFC153A5E51001DBD51 /* AppDelegate.m in Sources */, 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | }; 281 | 0042B000153A5E52001DBD51 /* Sources */ = { 282 | isa = PBXSourcesBuildPhase; 283 | buildActionMask = 2147483647; 284 | files = ( 285 | 0042B013153A5E52001DBD51 /* FrisbeeTests.m in Sources */, 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | /* End PBXSourcesBuildPhase section */ 290 | 291 | /* Begin PBXTargetDependency section */ 292 | 0042B00A153A5E52001DBD51 /* PBXTargetDependency */ = { 293 | isa = PBXTargetDependency; 294 | target = 0042AFE3153A5E51001DBD51 /* Frisbee */; 295 | targetProxy = 0042B009153A5E52001DBD51 /* PBXContainerItemProxy */; 296 | }; 297 | /* End PBXTargetDependency section */ 298 | 299 | /* Begin PBXVariantGroup section */ 300 | 0042AFF1153A5E51001DBD51 /* InfoPlist.strings */ = { 301 | isa = PBXVariantGroup; 302 | children = ( 303 | 0042AFF2153A5E51001DBD51 /* en */, 304 | ); 305 | name = InfoPlist.strings; 306 | sourceTree = ""; 307 | }; 308 | 0042AFF7153A5E51001DBD51 /* Credits.rtf */ = { 309 | isa = PBXVariantGroup; 310 | children = ( 311 | 0042AFF8153A5E51001DBD51 /* en */, 312 | ); 313 | name = Credits.rtf; 314 | sourceTree = ""; 315 | }; 316 | 0042AFFD153A5E52001DBD51 /* MainMenu.xib */ = { 317 | isa = PBXVariantGroup; 318 | children = ( 319 | 0042AFFE153A5E52001DBD51 /* en */, 320 | ); 321 | name = MainMenu.xib; 322 | sourceTree = ""; 323 | }; 324 | 0042B00E153A5E52001DBD51 /* InfoPlist.strings */ = { 325 | isa = PBXVariantGroup; 326 | children = ( 327 | 0042B00F153A5E52001DBD51 /* en */, 328 | ); 329 | name = InfoPlist.strings; 330 | sourceTree = ""; 331 | }; 332 | /* End PBXVariantGroup section */ 333 | 334 | /* Begin XCBuildConfiguration section */ 335 | 0042B014153A5E52001DBD51 /* Debug */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | COPY_PHASE_STRIP = NO; 342 | GCC_C_LANGUAGE_STANDARD = gnu99; 343 | GCC_DYNAMIC_NO_PIC = NO; 344 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 345 | GCC_OPTIMIZATION_LEVEL = 0; 346 | GCC_PREPROCESSOR_DEFINITIONS = ( 347 | "DEBUG=1", 348 | "$(inherited)", 349 | ); 350 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 351 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 352 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 353 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 354 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 355 | GCC_WARN_UNUSED_VARIABLE = YES; 356 | MACOSX_DEPLOYMENT_TARGET = 10.7; 357 | ONLY_ACTIVE_ARCH = YES; 358 | SDKROOT = macosx; 359 | }; 360 | name = Debug; 361 | }; 362 | 0042B015153A5E52001DBD51 /* Release */ = { 363 | isa = XCBuildConfiguration; 364 | buildSettings = { 365 | ALWAYS_SEARCH_USER_PATHS = NO; 366 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 367 | CLANG_ENABLE_OBJC_ARC = YES; 368 | COPY_PHASE_STRIP = YES; 369 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 370 | GCC_C_LANGUAGE_STANDARD = gnu99; 371 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 372 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 373 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 374 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 376 | GCC_WARN_UNUSED_VARIABLE = YES; 377 | MACOSX_DEPLOYMENT_TARGET = 10.7; 378 | SDKROOT = macosx; 379 | }; 380 | name = Release; 381 | }; 382 | 0042B017153A5E52001DBD51 /* Debug */ = { 383 | isa = XCBuildConfiguration; 384 | buildSettings = { 385 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 386 | GCC_PREFIX_HEADER = "Frisbee/Frisbee-Prefix.pch"; 387 | INFOPLIST_FILE = "Frisbee/Frisbee-Info.plist"; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | WRAPPER_EXTENSION = app; 390 | }; 391 | name = Debug; 392 | }; 393 | 0042B018153A5E52001DBD51 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 397 | GCC_PREFIX_HEADER = "Frisbee/Frisbee-Prefix.pch"; 398 | INFOPLIST_FILE = "Frisbee/Frisbee-Info.plist"; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | WRAPPER_EXTENSION = app; 401 | }; 402 | name = Release; 403 | }; 404 | 0042B01A153A5E52001DBD51 /* Debug */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Frisbee.app/Contents/MacOS/Frisbee"; 408 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 409 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 410 | GCC_PREFIX_HEADER = "Frisbee/Frisbee-Prefix.pch"; 411 | INFOPLIST_FILE = "FrisbeeTests/FrisbeeTests-Info.plist"; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | TEST_HOST = "$(BUNDLE_LOADER)"; 414 | WRAPPER_EXTENSION = octest; 415 | }; 416 | name = Debug; 417 | }; 418 | 0042B01B153A5E52001DBD51 /* Release */ = { 419 | isa = XCBuildConfiguration; 420 | buildSettings = { 421 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Frisbee.app/Contents/MacOS/Frisbee"; 422 | FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; 423 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 424 | GCC_PREFIX_HEADER = "Frisbee/Frisbee-Prefix.pch"; 425 | INFOPLIST_FILE = "FrisbeeTests/FrisbeeTests-Info.plist"; 426 | PRODUCT_NAME = "$(TARGET_NAME)"; 427 | TEST_HOST = "$(BUNDLE_LOADER)"; 428 | WRAPPER_EXTENSION = octest; 429 | }; 430 | name = Release; 431 | }; 432 | /* End XCBuildConfiguration section */ 433 | 434 | /* Begin XCConfigurationList section */ 435 | 0042AFDE153A5E51001DBD51 /* Build configuration list for PBXProject "Frisbee" */ = { 436 | isa = XCConfigurationList; 437 | buildConfigurations = ( 438 | 0042B014153A5E52001DBD51 /* Debug */, 439 | 0042B015153A5E52001DBD51 /* Release */, 440 | ); 441 | defaultConfigurationIsVisible = 0; 442 | defaultConfigurationName = Release; 443 | }; 444 | 0042B016153A5E52001DBD51 /* Build configuration list for PBXNativeTarget "Frisbee" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | 0042B017153A5E52001DBD51 /* Debug */, 448 | 0042B018153A5E52001DBD51 /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | }; 452 | 0042B019153A5E52001DBD51 /* Build configuration list for PBXNativeTarget "FrisbeeTests" */ = { 453 | isa = XCConfigurationList; 454 | buildConfigurations = ( 455 | 0042B01A153A5E52001DBD51 /* Debug */, 456 | 0042B01B153A5E52001DBD51 /* Release */, 457 | ); 458 | defaultConfigurationIsVisible = 0; 459 | }; 460 | /* End XCConfigurationList section */ 461 | }; 462 | rootObject = 0042AFDB153A5E51001DBD51 /* Project object */; 463 | } 464 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Frisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject { 12 | NSStatusItem *statusItem; 13 | } 14 | 15 | @property (assign) IBOutlet NSWindow *window; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Frisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | #import 12 | #include 13 | 14 | #define SERVER_IP "50.116.7.184" 15 | 16 | @implementation AppDelegate 17 | 18 | @synthesize window = _window; 19 | 20 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 21 | { 22 | [self createStatusItem]; 23 | 24 | // Poll the server constantly (this should be on a seperate thread, but the UI thread 25 | struct sockaddr_in addr; 26 | int sockfd; 27 | 28 | while(true){ 29 | // Create a socket 30 | sockfd = socket( AF_INET, SOCK_STREAM, 0 ); 31 | addr.sin_family = AF_INET; 32 | addr.sin_addr.s_addr = inet_addr(SERVER_IP); 33 | addr.sin_port = htons( 5002 ); 34 | 35 | int conn = connect(sockfd, &addr, sizeof(addr)); 36 | 37 | if (!conn) { 38 | NSString *msg = @"poll"; 39 | NSData* data = [msg dataUsingEncoding:NSUTF8StringEncoding]; 40 | ssize_t datasend = send(sockfd, [data bytes], [data length], 0); 41 | 42 | char buf[100]; 43 | memset(buf, 0, sizeof(buf)); 44 | 45 | int numbytes = recv(sockfd, buf, sizeof(buf)-1, 0); 46 | buf[numbytes] = '\0'; 47 | 48 | NSString *cmd = [NSString stringWithUTF8String: buf]; 49 | 50 | NSLog(cmd); 51 | 52 | if(![cmd isEqualToString:@"empty"]){ 53 | NSString *prefix = @"http://50.116.7.184/?"; 54 | NSString *URL = [prefix stringByAppendingString:cmd]; 55 | NSLog(URL); 56 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:URL]]; 57 | } 58 | 59 | close(sockfd); 60 | }else{ 61 | NSLog(@"Did not connect"); 62 | } 63 | // Sleep for 0.1 seconds 64 | usleep(100000); 65 | } 66 | 67 | 68 | } 69 | 70 | 71 | - (void) createStatusItem { 72 | NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; 73 | statusItem = [statusBar statusItemWithLength:NSSquareStatusItemLength]; 74 | if (statusItem) { 75 | [statusItem setMenu:[self statusItemMenu]]; 76 | [statusItem setHighlightMode:YES]; 77 | [statusItem setImage:[NSImage imageNamed:@"growlTunes.png"]]; 78 | [statusItem setAlternateImage:[NSImage imageNamed:@"growlTunes-selected.png"]]; 79 | [statusItem setToolTip:NSLocalizedString(@"2:06 PM", /*comment*/ nil)]; 80 | } 81 | } 82 | 83 | - (NSMenu *) statusItemMenu { 84 | //NSLog(@"In statusItemMenu"); 85 | NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"TwoOSixPM"]; 86 | if (menu) { 87 | NSMenuItem * item; 88 | NSString *empty = @""; //used for the key equivalent of all the menu items. 89 | 90 | item = [menu addItemWithTitle:NSLocalizedString(@"Open Music Log", @"") action:@selector(openTextFile:) keyEquivalent:empty]; 91 | [item setTarget:self]; 92 | 93 | item = [menu addItemWithTitle:NSLocalizedString(@"About 2:06PM", @"") action:@selector(openAboutPage:) keyEquivalent:empty]; 94 | [item setTarget:self]; 95 | 96 | item = [menu addItemWithTitle:NSLocalizedString(@"Quit 2:06PM", @"") action:@selector(quit206AM:) keyEquivalent:empty]; 97 | [item setTarget:self]; 98 | 99 | } 100 | return menu; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/Frisbee-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | Frisbee.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2012 The Greatest Company. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/Frisbee-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Frisbee' target in the 'Frisbee' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /mac/Frisbee/Frisbee/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Frisbee 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /mac/Frisbee/FrisbeeTests/FrisbeeTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Frisbee.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | LSUIElement 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /mac/Frisbee/FrisbeeTests/FrisbeeTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // FrisbeeTests.h 3 | // FrisbeeTests 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FrisbeeTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /mac/Frisbee/FrisbeeTests/FrisbeeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // FrisbeeTests.m 3 | // FrisbeeTests 4 | // 5 | // Created by Abimanyu Raja on 4/14/12. 6 | // Copyright (c) 2012 The Greatest Company. All rights reserved. 7 | // 8 | 9 | #import "FrisbeeTests.h" 10 | 11 | @implementation FrisbeeTests 12 | 13 | - (void)setUp 14 | { 15 | [super setUp]; 16 | 17 | // Set-up code here. 18 | } 19 | 20 | - (void)tearDown 21 | { 22 | // Tear-down code here. 23 | 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample 28 | { 29 | STFail(@"Unit tests are not implemented yet in FrisbeeTests"); 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /mac/Frisbee/FrisbeeTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /mac/Frisbee/growlTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/mac/Frisbee/growlTunes.png -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | upstream fling-frontends { 2 | server 127.0.0.1:5000; 3 | } 4 | 5 | server { 6 | listen 80; 7 | server_name fling.io; 8 | 9 | # Allow file uploads 10 | client_max_body_size 50M; 11 | 12 | location / { 13 | proxy_pass_header Server; 14 | proxy_set_header Host $http_host; 15 | proxy_redirect off; 16 | proxy_set_header X-Real-IP $remote_addr; 17 | proxy_set_header X-Scheme $scheme; 18 | proxy_pass http://fling-frontends; 19 | } 20 | } 21 | 22 | server { 23 | listen 50.116.7.184:80; 24 | server_name www.fling.io; 25 | rewrite ^ http://fling.io$request_uri permanent; 26 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Frisbee", 3 | "version": "0.1.0", 4 | "private" : "true", 5 | "author" : "Abi Raja ", 6 | "description": "Fling your photos/music around", 7 | "dependencies": { 8 | "underscore" : "*", 9 | "underscore.string" : "*", 10 | "node_util" : "*", 11 | "solid" : "*", 12 | "socket.io" : ">0.8.x" 13 | }, 14 | "devDependencies": { 15 | "coffee-script": "1.1.x" 16 | }, 17 | "scripts": { 18 | "test": "mocha" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/bookmarklet.coffee: -------------------------------------------------------------------------------- 1 | LOCAL = off 2 | SERVER = if LOCAL then "http://localhost:5000" else "http://50.116.7.184" 3 | 4 | url = window.location.href 5 | 6 | window.location.href = "#{SERVER}/static/handler.html?#{url}"; -------------------------------------------------------------------------------- /src/client.coffee: -------------------------------------------------------------------------------- 1 | SERVER = if LOCAL then "http://localhost" else "http://50.116.7.184" 2 | 3 | window.socket = socket = io.connect SERVER 4 | 5 | percentOfHeight = (percent) -> $(window).height() * (percent / 100) 6 | percentOfWidth = (percent) -> $(window).width() * (percent / 100) 7 | 8 | playWhoosh = -> 9 | $('body').append '' 10 | 11 | $(document).ready -> 12 | $('#frisbee-button').click -> 13 | socket.emit 'frisbee', {lat: 5, lng: 5} 14 | 15 | navigator.geolocation.getCurrentPosition (position) -> 16 | console.log(position.coords.latitude, position.coords.longitude) 17 | # TODO: ask the user for their name 18 | socket.emit 'id', {lat: position.coords.latitude, lng: position.coords.longitude, name: 'test'} 19 | 20 | # TODO: Handle denials, in the case of denial, just fail 21 | 22 | handleData = (data) -> 23 | {type, content} = data 24 | 25 | switch type 26 | when "url" 27 | a = $("") 28 | a.css width: percentOfWidth(100) - 100, height: percentOfHeight(100) - 100 29 | when "youtube" 30 | time = if data.time then data.time else "" 31 | a = $("") 32 | a.css width: percentOfWidth(100) - 100, height: percentOfHeight(100) - 100 33 | 34 | when "image" 35 | $("body").append $("") 36 | when "spotify" 37 | document.location = "spotify:track:#{content}" 38 | else 39 | alert("Unknown") 40 | return 41 | a.hide() 42 | a.appendTo('.content') 43 | a.fadeIn('slow') 44 | 45 | socket.on 'frisbee', (data) -> 46 | console.log data 47 | 48 | throwFrisbee -> 49 | handleData data 50 | 51 | 52 | throwFrisbee = window.throwFrisbee = (cb) -> 53 | if !$('.content').length 54 | $("body").append $('
', class: 'content') 55 | else 56 | $('.content').empty() 57 | 58 | $('.swoosh').fadeOut().remove() 59 | oldFrisbee = $ '.frisbee' 60 | 61 | animateFrisbee = -> 62 | oldFrisbee.remove() 63 | 64 | playWhoosh() 65 | 66 | frisbee = $ '
', class: 'frisbee frisbeeContent' 67 | frisbee.css left: 145, bottom: 137, width: 50, height: 29 68 | frisbee.appendTo '#fixed' 69 | 70 | frisbee.animate width: percentOfWidth(150), height: percentOfHeight(150), 71 | duration: 1500 72 | easing: 'linear' 73 | queue: false 74 | frisbee.animate {left: percentOfWidth(75), bottom: percentOfHeight(45)}, 750, 'easeOutQuad' 75 | frisbee.animate {left: percentOfWidth(-25), bottom: percentOfHeight(-25)}, 750, 'easeInOutQuad', -> 76 | cb() 77 | 78 | if oldFrisbee.length is 0 79 | animateFrisbee() 80 | else if oldFrisbee.hasClass('frisbeeContent') 81 | oldFrisbee.fadeOut animateFrisbee 82 | else 83 | oldFrisbee.animate left: -300, 1000, 'easeInOutQuad', animateFrisbee 84 | 85 | 86 | showSwoosh = -> 87 | swoosh = $ '', class: 'swoosh', src: '/static/img/swoosh.png' 88 | swoosh.css left: 100, bottom: 150, width: percentOfWidth(75), height: percentOfHeight(60) - 50, opacity: 0 89 | swoosh.appendTo '#fixed' 90 | swoosh.animate opacity: 1, 500, 'linear' 91 | 92 | # icons = ['music', 'video', 'article'] 93 | # for type in icons 94 | # icon = $ '
', class: type 95 | # icon 96 | 97 | throwLogoFrisbee = (frisbee) -> 98 | kid2 = $ '
', class: 'kid2' 99 | kid2.css right: -50, bottom: 50 100 | kid2.appendTo '#fixed' 101 | kid2.animate right: 75, 250 102 | 103 | frisbee.animate width: 249, height: 145, 104 | duration: 2500 105 | easing: 'linear' 106 | queue: false 107 | frisbee.animate {left: percentOfWidth(75), bottom: percentOfHeight(45)}, 1250, 'easeOutQuad' 108 | frisbee.animate {left: percentOfWidth(25), bottom: percentOfHeight(60)}, 1250, 'easeInOutQuad', -> 109 | showSwoosh() 110 | 111 | createCloud = -> 112 | cloudNum = Math.floor(Math.random()*3) + 1 113 | cloudTop = Math.floor(Math.random()*200) + 1 114 | 115 | cloud = $ '
', class: 'cloud'+cloudNum 116 | cloud.css left: $(window).width(), top: cloudTop 117 | cloud.appendTo '#fixed' 118 | 119 | cloud.animate {left: -250}, 60000, 'linear', -> 120 | cloud.remove() 121 | 122 | performYTSearch = (s, cb) -> 123 | $.ajax 124 | dataType: 'jsonp' 125 | type: 'GET' 126 | url: "http://gdata.youtube.com/feeds/api/videos?q=#{ encodeURIComponent(s) }" + 127 | "&format=5&v=2&alt=jsonc" + # Force embeddable vids (format=5) 128 | "&max-results=1" 129 | success: (responseData, textStatus, XMLHttpRequest) => 130 | if videoId = responseData?.data?.items?[0].id 131 | cb (videoId) 132 | 133 | startAnimation = -> 134 | createCloud() 135 | window.setInterval -> 136 | createCloud() 137 | , 15000 138 | 139 | kid1 = $ '
', class: 'kid1' 140 | kid1.css left: -50, bottom: 50 141 | kid1.appendTo '#fixed' 142 | 143 | frisbee = $ '', class: 'frisbeeLogo frisbee', src: '/static/img/frisbee-logo.png' 144 | frisbee.css left: 20, bottom: 137, width: 50, height: 29 145 | frisbee.appendTo '#fixed' 146 | 147 | time = 500 148 | kid1.animate left: 75, time 149 | frisbee.animate left: 145, bottom: 137, time, -> 150 | window.setTimeout -> 151 | throwLogoFrisbee(frisbee) 152 | , 200 153 | 154 | $ -> 155 | search = window.location.search 156 | if search 157 | YT_SEARCH = ///youtube=([^&]*)/// 158 | result = YT_SEARCH.exec search 159 | s = result[1] 160 | s = s.replace(',', ' ') 161 | 162 | YT_TIME = ///time=([^&]*)/// 163 | result = YT_TIME.exec search 164 | time = result[1] 165 | 166 | console.log 'hey' 167 | 168 | performYTSearch s, (videoId) -> 169 | throwFrisbee -> 170 | handleData type: 'youtube', content: videoId, time: time 171 | else 172 | startAnimation() 173 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /src/handler.coffee: -------------------------------------------------------------------------------- 1 | LOCAL = off 2 | SERVER = if LOCAL then "http://localhost" else "http://50.116.7.184" 3 | 4 | window.socket = socket = io.connect SERVER 5 | 6 | window.foundLocation = false 7 | url = window.location.search.substring 1 8 | 9 | window.onShake = -> 10 | if !window.foundLocation 11 | return 12 | 13 | console.log 'shake' 14 | window.socket.emit 'frisbee', { 15 | lat: window.foundPosition.coords.latitude, 16 | lng: window.foundPosition.coords.longitude, 17 | url: url 18 | }, -> 19 | history.go -1 20 | 21 | success = (position) -> 22 | if (window.foundLocation) 23 | # not sure why we're hitting this twice in FF, I think it's to do with a cached result coming back 24 | return 25 | 26 | console.log 'found position' 27 | window.foundLocation = true 28 | window.foundPosition = position 29 | 30 | error = (msg) -> 31 | alert 'Geolocation failed. Try again and ALLOW access! ' + msg 32 | history.go -1 33 | 34 | $ -> 35 | window.addEventListener 'shake', window.onShake 36 | 37 | if (navigator.geolocation) 38 | navigator.geolocation.getCurrentPosition success, error 39 | else 40 | alert 'geolocation not supported' 41 | 42 | -------------------------------------------------------------------------------- /src/server.coffee: -------------------------------------------------------------------------------- 1 | net = require 'net' 2 | {log, inspect} = require 'util' 3 | solid = require 'solid' 4 | sio = require 'socket.io' 5 | {read} = require('node_util').sync() 6 | 7 | 8 | # Aliases 9 | # ======= 10 | 11 | dir = inspect 12 | 13 | # Configuration 14 | # ============= 15 | 16 | LOCAL = off 17 | PORT = if LOCAL then 5000 else 80 18 | SIO_PORT = 5001 19 | TCP_PORT = 5002 20 | IPHONE_TCP_PORT = 5003 21 | 22 | # App 23 | # === 24 | 25 | solid {port: PORT, cwd: "#{__dirname}/.."}, (app) -> 26 | 27 | # socket.io server 28 | io = sio.listen app.app 29 | io.configure () -> 30 | io.set 'transports', ['websocket'] 31 | io.disable 'log' 32 | 33 | io.sockets.on 'connection', (socket) -> 34 | 35 | log 'new connection!' 36 | socket.on 'id', (msg) -> 37 | socket.set('info', msg) 38 | socket.get 'info', (err, info) -> 39 | log(inspect(info)) 40 | 41 | socket.on 'frisbee', (data, cb) -> 42 | 43 | url = data.url 44 | 45 | YOUTUBE_URL = ///^https?://.*?youtube\.com/watch.*?v=([^&]*)///g 46 | result = YOUTUBE_URL.exec url 47 | if result 48 | log 'youtube' 49 | log result[1] 50 | obj = 51 | type: 'youtube' 52 | content: result[1] 53 | else 54 | obj = 55 | type: 'url' 56 | content: url 57 | 58 | for client in io.sockets.clients() 59 | 60 | # TODO: Catch error here, which happens when the messages are too fast? 61 | # while client.store.data.info isnt undefined 62 | [lat, lng, name] = [5,5, 'test'] # client.store.data.info 63 | 64 | log "Sending to #{name}..." 65 | 66 | client.emit 'frisbee', obj 67 | 68 | cb() 69 | 70 | # Messages for different kinds of content 71 | # TODO: Convert music to a spotify thing 72 | # {type: 'spotify', content: '7My5AMVGC5KUYgsxZVOQUI'} 73 | # {type: 'image', content: 'http://i.imgur.com/RJlON.jpg'} 74 | # {type: 'youtube', content: '4qYwk37F0PQ'} 75 | # {type: 'url', content: 'http://reddit.com'} 76 | 77 | app.get "/", @render (req) -> 78 | @doctype 5 79 | @html -> 80 | @head -> 81 | @title 'Frisbee' 82 | @js '/jquery.js' 83 | @js '/static/js/libs/jquery-ui-1.8.18.custom.min.js' 84 | @script "window.LOCAL = #{LOCAL};" 85 | @js '/socket.io/socket.io.js' 86 | @js 'client.js' 87 | @css '/static/css/home.css' 88 | @body -> 89 | @div '#fixed' 90 | 91 | app.post "/new", @render (req) -> 92 | # req.params.id 93 | # TODO: Send to the right socket, only the ones closest to the 94 | 95 | app.get "/home", "/" # URL rewriting/redirects 96 | app.get "/jquery.js", @jquery # Put in HTML 97 | app.get "/javascripts/client.js" , () -> type: 'text/javascript', body: read("#{__dirname}/../js/client.js") 98 | app.get "/javascripts/bookmarklet.js", () -> type: 'text/javascript', body: read("#{__dirname}/../js/bookmarklet.js") 99 | app.get "/javascripts/handler.js", () -> type: 'text/javascript', body: read("#{__dirname}/../js/handler.js") 100 | 101 | # app.namespace "/user", -> 102 | # app.get "/:id", @render (req) -> 103 | # @p "Hi, #{req.params.id}!" 104 | # 105 | # app.get "/:id/requests", (req) -> 106 | # "

#{req.params.id}: you have no requests.

" 107 | 108 | 109 | # TCP server that the Mac app polls to find out if it has received any messages 110 | # We have to kill dead connections, etc. 111 | 112 | dummy = "" 113 | 114 | # TCP Text Protocol 115 | # poll -> empty | w:[url] | m:[song] 116 | net.createServer( (socket) -> 117 | msg = "" 118 | socket.on 'data', (data) -> 119 | msg += data.toString 'ascii' 120 | console.log msg 121 | if msg is 'poll' and dummy isnt "" 122 | socket.write dummy 123 | dummy = "" 124 | else 125 | socket.write 'empty' 126 | 127 | socket.on 'end', () -> 128 | 129 | ).listen TCP_PORT 130 | 131 | log "Running Mac TCP server on #{TCP_PORT}" 132 | 133 | # iPhone TCP server 134 | 135 | net.createServer( (socket) -> 136 | msg = "" 137 | socket.on 'data', (data) -> 138 | msg += data.toString 'ascii' 139 | [search, time] = msg.split('|') 140 | dummy = "youtube=" + search.replace(/\s/g, ',') + "&time=" + Math.floor(time / 60) + "m" + Math.ceil(time % 60) + "s" 141 | console.log msg 142 | console.log dummy 143 | 144 | socket.on 'end', () -> 145 | 146 | ).listen IPHONE_TCP_PORT 147 | 148 | log "Running iPhone TCP server on #{IPHONE_TCP_PORT}" -------------------------------------------------------------------------------- /static/bookmarklet.html: -------------------------------------------------------------------------------- 1 | Frisbee! 2 | 3 | Frisbee! (localhost) -------------------------------------------------------------------------------- /static/css/home.css: -------------------------------------------------------------------------------- 1 | /* 2 | * HTML5 Boilerplate 3 | * 4 | * What follows is the result of much research on cross-browser styling. 5 | * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal, 6 | * Kroc Camen, and the H5BP dev community and team. 7 | * 8 | * Detailed information about this CSS: h5bp.com/css 9 | * 10 | * ==|== normalize ========================================================== 11 | */ 12 | 13 | 14 | /* ============================================================================= 15 | HTML5 display definitions 16 | ========================================================================== */ 17 | 18 | article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; } 19 | audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } 20 | audio:not([controls]) { display: none; } 21 | [hidden] { display: none; } 22 | 23 | 24 | /* ============================================================================= 25 | Base 26 | ========================================================================== */ 27 | 28 | /* 29 | * 1. Correct text resizing oddly in IE6/7 when body font-size is set using em units 30 | * 2. Prevent iOS text size adjust on device orientation change, without disabling user zoom: h5bp.com/g 31 | */ 32 | 33 | html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; } 34 | 35 | html, button, input, select, textarea { font-family: sans-serif; color: #222; } 36 | 37 | body { margin: 0; font-size: 1em; line-height: 1.4; } 38 | 39 | /* 40 | * Remove text-shadow in selection highlight: h5bp.com/i 41 | * These selection declarations have to be separate 42 | * Also: hot pink! (or customize the background color to match your design) 43 | */ 44 | 45 | ::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; } 46 | ::selection { background: #fe57a1; color: #fff; text-shadow: none; } 47 | 48 | 49 | /* ============================================================================= 50 | Links 51 | ========================================================================== */ 52 | 53 | a { color: #00e; } 54 | a:visited { color: #551a8b; } 55 | a:hover { color: #06e; } 56 | a:focus { outline: thin dotted; } 57 | 58 | /* Improve readability when focused and hovered in all browsers: h5bp.com/h */ 59 | a:hover, a:active { outline: 0; } 60 | 61 | 62 | /* ============================================================================= 63 | Typography 64 | ========================================================================== */ 65 | 66 | abbr[title] { border-bottom: 1px dotted; } 67 | 68 | b, strong { font-weight: bold; } 69 | 70 | blockquote { margin: 1em 40px; } 71 | 72 | dfn { font-style: italic; } 73 | 74 | hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; } 75 | 76 | ins { background: #ff9; color: #000; text-decoration: none; } 77 | 78 | mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; } 79 | 80 | /* Redeclare monospace font family: h5bp.com/j */ 81 | pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; } 82 | 83 | /* Improve readability of pre-formatted text in all browsers */ 84 | pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; } 85 | 86 | q { quotes: none; } 87 | q:before, q:after { content: ""; content: none; } 88 | 89 | small { font-size: 85%; } 90 | 91 | /* Position subscript and superscript content without affecting line-height: h5bp.com/k */ 92 | sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } 93 | sup { top: -0.5em; } 94 | sub { bottom: -0.25em; } 95 | 96 | 97 | /* ============================================================================= 98 | Lists 99 | ========================================================================== */ 100 | 101 | ul, ol { margin: 1em 0; padding: 0 0 0 40px; } 102 | dd { margin: 0 0 0 40px; } 103 | nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; } 104 | 105 | 106 | /* ============================================================================= 107 | Embedded content 108 | ========================================================================== */ 109 | 110 | /* 111 | * 1. Improve image quality when scaled in IE7: h5bp.com/d 112 | * 2. Remove the gap between images and borders on image containers: h5bp.com/i/440 113 | */ 114 | 115 | img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; } 116 | 117 | /* 118 | * Correct overflow not hidden in IE9 119 | */ 120 | 121 | svg:not(:root) { overflow: hidden; } 122 | 123 | 124 | /* ============================================================================= 125 | Figures 126 | ========================================================================== */ 127 | 128 | figure { margin: 0; } 129 | 130 | 131 | /* ============================================================================= 132 | Forms 133 | ========================================================================== */ 134 | 135 | form { margin: 0; } 136 | fieldset { border: 0; margin: 0; padding: 0; } 137 | 138 | /* Indicate that 'label' will shift focus to the associated form element */ 139 | label { cursor: pointer; } 140 | 141 | /* 142 | * 1. Correct color not inheriting in IE6/7/8/9 143 | * 2. Correct alignment displayed oddly in IE6/7 144 | */ 145 | 146 | legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; } 147 | 148 | /* 149 | * 1. Correct font-size not inheriting in all browsers 150 | * 2. Remove margins in FF3/4 S5 Chrome 151 | * 3. Define consistent vertical alignment display in all browsers 152 | */ 153 | 154 | button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; } 155 | 156 | /* 157 | * 1. Define line-height as normal to match FF3/4 (set using !important in the UA stylesheet) 158 | */ 159 | 160 | button, input { line-height: normal; } 161 | 162 | /* 163 | * 1. Display hand cursor for clickable form elements 164 | * 2. Allow styling of clickable form elements in iOS 165 | * 3. Correct inner spacing displayed oddly in IE7 (doesn't effect IE6) 166 | */ 167 | 168 | button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; } 169 | 170 | /* 171 | * Re-set default cursor for disabled elements 172 | */ 173 | 174 | button[disabled], input[disabled] { cursor: default; } 175 | 176 | /* 177 | * Consistent box sizing and appearance 178 | */ 179 | 180 | input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; } 181 | input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; } 182 | input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; } 183 | 184 | /* 185 | * Remove inner padding and border in FF3/4: h5bp.com/l 186 | */ 187 | 188 | button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } 189 | 190 | /* 191 | * 1. Remove default vertical scrollbar in IE6/7/8/9 192 | * 2. Allow only vertical resizing 193 | */ 194 | 195 | textarea { overflow: auto; vertical-align: top; resize: vertical; } 196 | 197 | /* Colors for form validity */ 198 | input:valid, textarea:valid { } 199 | input:invalid, textarea:invalid { background-color: #f0dddd; } 200 | 201 | 202 | /* ============================================================================= 203 | Tables 204 | ========================================================================== */ 205 | 206 | table { border-collapse: collapse; border-spacing: 0; } 207 | td { vertical-align: top; } 208 | 209 | 210 | /* ============================================================================= 211 | Chrome Frame Prompt 212 | ========================================================================== */ 213 | 214 | .chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; } 215 | 216 | 217 | /* ==|== primary styles ===================================================== 218 | Author: 219 | ========================================================================== */ 220 | 221 | 222 | 223 | 224 | 225 | 226 | html { 227 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), linear-gradient(top, rgb(0,132,193) 0%, rgb(0,178,214) 100%); 228 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), -o-linear-gradient(top, rgb(0,132,193) 0%, rgb(0,178,214) 100%); 229 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), -moz-linear-gradient(top, rgb(0,132,193) 0%, rgb(0,178,214) 100%); 230 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), -webkit-linear-gradient(top, rgb(0,132,193) 0%, rgb(0,178,214) 100%); 231 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), -ms-linear-gradient(top, rgb(0,132,193) 0%, rgb(0,178,214) 100%); 232 | 233 | background-image: url(/static/img/grass-left.png), url(/static/img/grass-right.png), -webkit-gradient( 234 | linear, 235 | left top, 236 | left bottom, 237 | color-stop(0, rgb(0,132,193)), 238 | color-stop(1, rgb(0,178,214)) 239 | ); 240 | background-position: bottom left, bottom right, top left; 241 | background-repeat: no-repeat, no-repeat, no-repeat; 242 | height: 100%; 243 | } 244 | 245 | #fixed * { 246 | position: fixed; 247 | } 248 | 249 | .cloud1, .cloud2, .cloud3 { 250 | position: fixed; 251 | top: 0; 252 | left: 2000px; 253 | z-index: 1; 254 | } 255 | 256 | .cloud1 { 257 | background: url(/static/img/cloud1.png) top left no-repeat; 258 | width: 184px; 259 | height: 127px; 260 | } 261 | 262 | .cloud2 { 263 | background: url(/static/img/cloud2.png) top left no-repeat; 264 | width: 249px; 265 | height: 106px; 266 | } 267 | 268 | .cloud3 { 269 | background: url(/static/img/cloud3.png) top left no-repeat; 270 | width: 199px; 271 | height: 66px; 272 | } 273 | 274 | /* Main items */ 275 | 276 | .kid1 { 277 | background: url(/static/img/kid1.png) top left no-repeat; 278 | width: 100px; 279 | height: 130px; 280 | z-index: 50; 281 | } 282 | 283 | .kid2 { 284 | background: url(/static/img/kid2.png) top left no-repeat; 285 | width: 78px; 286 | height: 136px; 287 | z-index: 50; 288 | } 289 | 290 | .swoosh { 291 | z-index: 2; 292 | } 293 | 294 | /* Frisbee */ 295 | 296 | .frisbee { 297 | z-index: 10; 298 | } 299 | 300 | .frisbeeContent { 301 | background-image: url(/static/img/frisbee.png); 302 | background-position: top left; 303 | background-repeat: no-repeat; 304 | background-size: 100% 100%; 305 | z-index: 100; 306 | } 307 | 308 | .content { 309 | position: relative; 310 | padding: 50px; 311 | width: 100%; 312 | height: 100%; 313 | z-index: 200; 314 | } 315 | 316 | iframe { 317 | width: 100%; 318 | height: 100%; 319 | } 320 | 321 | /* Icons */ 322 | 323 | .music { 324 | background: url(/static/img/music.png) top left no-repeat; 325 | width: 44px; 326 | height: 51px; 327 | } 328 | 329 | .video { 330 | background: url(/static/img/video.png) top left no-repeat; 331 | width: 82px; 332 | height: 61px; 333 | } 334 | 335 | .article { 336 | background: url(/static/img/article.png) top left no-repeat; 337 | width: 78px; 338 | height: 75px; 339 | } 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | /* ==|== media queries ====================================================== 350 | EXAMPLE Media Query for Responsive Design. 351 | This example overrides the primary ('mobile first') styles 352 | Modify as content requires. 353 | ========================================================================== */ 354 | 355 | @media only screen and (min-width: 35em) { 356 | /* Style adjustments for viewports that meet the condition */ 357 | } 358 | 359 | 360 | 361 | /* ==|== non-semantic helper classes ======================================== 362 | Please define your styles before this section. 363 | ========================================================================== */ 364 | 365 | /* For image replacement */ 366 | .ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; } 367 | .ir br { display: none; } 368 | 369 | /* Hide from both screenreaders and browsers: h5bp.com/u */ 370 | .hidden { display: none !important; visibility: hidden; } 371 | 372 | /* Hide only visually, but have it available for screenreaders: h5bp.com/v */ 373 | .visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } 374 | 375 | /* Extends the .visuallyhidden class to allow the element to be focusable when navigated to via the keyboard: h5bp.com/p */ 376 | .visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; } 377 | 378 | /* Hide visually and from screenreaders, but maintain layout */ 379 | .invisible { visibility: hidden; } 380 | 381 | /* Contain floats: h5bp.com/q */ 382 | .clearfix:before, .clearfix:after { content: ""; display: table; } 383 | .clearfix:after { clear: both; } 384 | .clearfix { *zoom: 1; } 385 | 386 | 387 | 388 | /* ==|== print styles ======================================================= 389 | Print styles. 390 | Inlined to avoid required HTTP connection: h5bp.com/r 391 | ========================================================================== */ 392 | 393 | @media print { 394 | * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */ 395 | a, a:visited { text-decoration: underline; } 396 | a[href]:after { content: " (" attr(href) ")"; } 397 | abbr[title]:after { content: " (" attr(title) ")"; } 398 | .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; } /* Don't show links for images, or javascript/internal links */ 399 | pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } 400 | thead { display: table-header-group; } /* h5bp.com/t */ 401 | tr, img { page-break-inside: avoid; } 402 | img { max-width: 100% !important; } 403 | @page { margin: 0.5cm; } 404 | p, h2, h3 { orphans: 3; widows: 3; } 405 | h2, h3 { page-break-after: avoid; } 406 | } -------------------------------------------------------------------------------- /static/handler.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

Throw your phone!

11 | 12 | -------------------------------------------------------------------------------- /static/img/article.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/article.png -------------------------------------------------------------------------------- /static/img/cloud1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/cloud1.png -------------------------------------------------------------------------------- /static/img/cloud2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/cloud2.png -------------------------------------------------------------------------------- /static/img/cloud3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/cloud3.png -------------------------------------------------------------------------------- /static/img/frisbee-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/frisbee-logo.png -------------------------------------------------------------------------------- /static/img/frisbee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/frisbee.png -------------------------------------------------------------------------------- /static/img/grass-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/grass-left.png -------------------------------------------------------------------------------- /static/img/grass-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/grass-right.png -------------------------------------------------------------------------------- /static/img/kid1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/kid1.png -------------------------------------------------------------------------------- /static/img/kid2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/kid2.png -------------------------------------------------------------------------------- /static/img/music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/music.png -------------------------------------------------------------------------------- /static/img/swoosh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/swoosh.png -------------------------------------------------------------------------------- /static/img/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/img/video.png -------------------------------------------------------------------------------- /static/js/libs/jquery-ui-1.8.18.custom.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery UI Effects 1.8.18 3 | * 4 | * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) 5 | * Dual licensed under the MIT or GPL Version 2 licenses. 6 | * http://jquery.org/license 7 | * 8 | * http://docs.jquery.com/UI/Effects/ 9 | */jQuery.effects||function(a,b){function l(b){if(!b||typeof b=="number"||a.fx.speeds[b])return!0;if(typeof b=="string"&&!a.effects[b])return!0;return!1}function k(b,c,d,e){typeof b=="object"&&(e=c,d=null,c=b,b=c.effect),a.isFunction(c)&&(e=c,d=null,c={});if(typeof c=="number"||a.fx.speeds[c])e=d,d=c,c={};a.isFunction(d)&&(e=d,d=null),c=c||{},d=d||c.duration,d=a.fx.off?0:typeof d=="number"?d:d in a.fx.speeds?a.fx.speeds[d]:a.fx.speeds._default,e=e||c.complete;return[b,c,d,e]}function j(a,b){var c={_:0},d;for(d in b)a[d]!=b[d]&&(c[d]=b[d]);return c}function i(b){var c,d;for(c in b)d=b[c],(d==null||a.isFunction(d)||c in g||/scrollbar/.test(c)||!/color/i.test(c)&&isNaN(parseFloat(d)))&&delete b[c];return b}function h(){var a=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle,b={},c,d;if(a&&a.length&&a[0]&&a[a[0]]){var e=a.length;while(e--)c=a[e],typeof a[c]=="string"&&(d=c.replace(/\-(\w)/g,function(a,b){return b.toUpperCase()}),b[d]=a[c])}else for(c in a)typeof a[c]=="string"&&(b[c]=a[c]);return b}function d(b,d){var e;do{e=a.curCSS(b,d);if(e!=""&&e!="transparent"||a.nodeName(b,"body"))break;d="backgroundColor"}while(b=b.parentNode);return c(e)}function c(b){var c;if(b&&b.constructor==Array&&b.length==3)return b;if(c=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(c[1],10),parseInt(c[2],10),parseInt(c[3],10)];if(c=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(c[1])*2.55,parseFloat(c[2])*2.55,parseFloat(c[3])*2.55];if(c=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(c[1],16),parseInt(c[2],16),parseInt(c[3],16)];if(c=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(c[1]+c[1],16),parseInt(c[2]+c[2],16),parseInt(c[3]+c[3],16)];if(c=/rgba\(0, 0, 0, 0\)/.exec(b))return e.transparent;return e[a.trim(b).toLowerCase()]}a.effects={},a.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,e){a.fx.step[e]=function(a){a.colorInit||(a.start=d(a.elem,e),a.end=c(a.end),a.colorInit=!0),a.elem.style[e]="rgb("+Math.max(Math.min(parseInt(a.pos*(a.end[0]-a.start[0])+a.start[0],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[1]-a.start[1])+a.start[1],10),255),0)+","+Math.max(Math.min(parseInt(a.pos*(a.end[2]-a.start[2])+a.start[2],10),255),0)+")"}});var e={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},f=["add","remove","toggle"],g={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};a.effects.animateClass=function(b,c,d,e){a.isFunction(d)&&(e=d,d=null);return this.queue(function(){var g=a(this),k=g.attr("style")||" ",l=i(h.call(this)),m,n=g.attr("class");a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),m=i(h.call(this)),g.attr("class",n),g.animate(j(l,m),{queue:!1,duration:c,easing:d,complete:function(){a.each(f,function(a,c){b[c]&&g[c+"Class"](b[c])}),typeof g.attr("style")=="object"?(g.attr("style").cssText="",g.attr("style").cssText=k):g.attr("style",k),e&&e.apply(this,arguments),a.dequeue(this)}})})},a.fn.extend({_addClass:a.fn.addClass,addClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{add:b},c,d,e]):this._addClass(b)},_removeClass:a.fn.removeClass,removeClass:function(b,c,d,e){return c?a.effects.animateClass.apply(this,[{remove:b},c,d,e]):this._removeClass(b)},_toggleClass:a.fn.toggleClass,toggleClass:function(c,d,e,f,g){return typeof d=="boolean"||d===b?e?a.effects.animateClass.apply(this,[d?{add:c}:{remove:c},e,f,g]):this._toggleClass(c,d):a.effects.animateClass.apply(this,[{toggle:c},d,e,f])},switchClass:function(b,c,d,e,f){return a.effects.animateClass.apply(this,[{add:c,remove:b},d,e,f])}}),a.extend(a.effects,{version:"1.8.18",save:function(a,b){for(var c=0;c
").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e=document.activeElement;b.wrap(d),(b[0]===e||a.contains(b[0],e))&&a(e).focus(),d=b.parent(),b.css("position")=="static"?(d.css({position:"relative"}),b.css({position:"relative"})):(a.extend(c,{position:b.css("position"),zIndex:b.css("z-index")}),a.each(["top","left","bottom","right"],function(a,d){c[d]=b.css(d),isNaN(parseInt(c[d],10))&&(c[d]="auto")}),b.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"}));return d.css(c).show()},removeWrapper:function(b){var c,d=document.activeElement;if(b.parent().is(".ui-effects-wrapper")){c=b.parent().replaceWith(b),(b[0]===d||a.contains(b[0],d))&&a(d).focus();return c}return b},setTransition:function(b,c,d,e){e=e||{},a.each(c,function(a,c){unit=b.cssUnit(c),unit[0]>0&&(e[c]=unit[0]*d+unit[1])});return e}}),a.fn.extend({effect:function(b,c,d,e){var f=k.apply(this,arguments),g={options:f[1],duration:f[2],callback:f[3]},h=g.options.mode,i=a.effects[b];if(a.fx.off||!i)return h?this[h](g.duration,g.callback):this.each(function(){g.callback&&g.callback.call(this)});return i.call(this,g)},_show:a.fn.show,show:function(a){if(l(a))return this._show.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="show";return this.effect.apply(this,b)},_hide:a.fn.hide,hide:function(a){if(l(a))return this._hide.apply(this,arguments);var b=k.apply(this,arguments);b[1].mode="hide";return this.effect.apply(this,b)},__toggle:a.fn.toggle,toggle:function(b){if(l(b)||typeof b=="boolean"||a.isFunction(b))return this.__toggle.apply(this,arguments);var c=k.apply(this,arguments);c[1].mode="toggle";return this.effect.apply(this,c)},cssUnit:function(b){var c=this.css(b),d=[];a.each(["em","px","%","pt"],function(a,b){c.indexOf(b)>0&&(d=[parseFloat(c),b])});return d}}),a.easing.jswing=a.easing.swing,a.extend(a.easing,{def:"easeOutQuad",swing:function(b,c,d,e,f){return a.easing[a.easing.def](b,c,d,e,f)},easeInQuad:function(a,b,c,d,e){return d*(b/=e)*b+c},easeOutQuad:function(a,b,c,d,e){return-d*(b/=e)*(b-2)+c},easeInOutQuad:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b+c;return-d/2*(--b*(b-2)-1)+c},easeInCubic:function(a,b,c,d,e){return d*(b/=e)*b*b+c},easeOutCubic:function(a,b,c,d,e){return d*((b=b/e-1)*b*b+1)+c},easeInOutCubic:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b+c;return d/2*((b-=2)*b*b+2)+c},easeInQuart:function(a,b,c,d,e){return d*(b/=e)*b*b*b+c},easeOutQuart:function(a,b,c,d,e){return-d*((b=b/e-1)*b*b*b-1)+c},easeInOutQuart:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b+c;return-d/2*((b-=2)*b*b*b-2)+c},easeInQuint:function(a,b,c,d,e){return d*(b/=e)*b*b*b*b+c},easeOutQuint:function(a,b,c,d,e){return d*((b=b/e-1)*b*b*b*b+1)+c},easeInOutQuint:function(a,b,c,d,e){if((b/=e/2)<1)return d/2*b*b*b*b*b+c;return d/2*((b-=2)*b*b*b*b+2)+c},easeInSine:function(a,b,c,d,e){return-d*Math.cos(b/e*(Math.PI/2))+d+c},easeOutSine:function(a,b,c,d,e){return d*Math.sin(b/e*(Math.PI/2))+c},easeInOutSine:function(a,b,c,d,e){return-d/2*(Math.cos(Math.PI*b/e)-1)+c},easeInExpo:function(a,b,c,d,e){return b==0?c:d*Math.pow(2,10*(b/e-1))+c},easeOutExpo:function(a,b,c,d,e){return b==e?c+d:d*(-Math.pow(2,-10*b/e)+1)+c},easeInOutExpo:function(a,b,c,d,e){if(b==0)return c;if(b==e)return c+d;if((b/=e/2)<1)return d/2*Math.pow(2,10*(b-1))+c;return d/2*(-Math.pow(2,-10*--b)+2)+c},easeInCirc:function(a,b,c,d,e){return-d*(Math.sqrt(1-(b/=e)*b)-1)+c},easeOutCirc:function(a,b,c,d,e){return d*Math.sqrt(1-(b=b/e-1)*b)+c},easeInOutCirc:function(a,b,c,d,e){if((b/=e/2)<1)return-d/2*(Math.sqrt(1-b*b)-1)+c;return d/2*(Math.sqrt(1-(b-=2)*b)+1)+c},easeInElastic:function(a,b,c,d,e){var f=1.70158,g=0,h=d;if(b==0)return c;if((b/=e)==1)return c+d;g||(g=e*.3);if(h this.threshold) && (deltaY > this.threshold)) || ((deltaX > this.threshold) && (deltaZ > this.threshold)) || ((deltaY > this.threshold) && (deltaZ > this.threshold))) { 81 | 82 | //calculate time in milliseconds since last shake registered 83 | currentTime = new Date(); 84 | timeDifference = currentTime.getTime() - this.lastTime.getTime(); 85 | 86 | if (timeDifference > 1000) { 87 | window.dispatchEvent(this.event); 88 | this.lastTime = new Date(); 89 | } 90 | } 91 | }; 92 | 93 | //event handler 94 | Shake.prototype.handleEvent = function (e) { 95 | 96 | if (typeof (this[e.type]) === 'function') { 97 | return this[e.type](e); 98 | } 99 | }; 100 | 101 | //create a new instance of shake.js. 102 | var myShakeEvent = new Shake(); 103 | myShakeEvent.start(); 104 | 105 | }(window, document)); -------------------------------------------------------------------------------- /static/sound/whoosh.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/sound/whoosh.mp3 -------------------------------------------------------------------------------- /static/sound/whoosh.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/feross/Fling/b527e3f592e70dae30deee33fb6eb1059d8c140e/static/sound/whoosh.ogg --------------------------------------------------------------------------------