├── .gitignore
├── .gitmodules
├── CONTRIBUTING.md
├── LICENSE
├── Podfile
├── Podfile.lock
├── README.md
├── SoundcloudPlayer.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ ├── StreamCloud Beta.xcscheme
│ └── StreamCloud.xcscheme
├── SoundcloudPlayer.xcworkspace
└── contents.xcworkspacedata
├── SoundcloudPlayer
├── AppDelegate.h
├── AppDelegate.m
├── AppleMediaKeyController.h
├── AppleMediaKeyController.m
├── ArtworkOverlayView.h
├── ArtworkOverlayView.m
├── Base.lproj
│ └── MainMenu.xib
├── ClickableTableView.h
├── ClickableTableView.m
├── ClickableTextField.h
├── ClickableTextField.m
├── ConnectButtonCell.h
├── ConnectButtonCell.m
├── Images.xcassets
│ ├── AppIcon Beta.appiconset
│ │ ├── Contents.json
│ │ ├── beta-128.png
│ │ ├── beta-128@2x.png
│ │ ├── beta-16.png
│ │ ├── beta-16@2x.png
│ │ ├── beta-256.png
│ │ ├── beta-256@2x.png
│ │ ├── beta-32.png
│ │ ├── beta-32@2x.png
│ │ ├── beta-512.png
│ │ └── beta-512@2x.png
│ ├── AppIcon.appiconset
│ │ ├── AppIcon128.png
│ │ ├── AppIcon128@2x.png
│ │ ├── AppIcon16.png
│ │ ├── AppIcon16@2x.png
│ │ ├── AppIcon256.png
│ │ ├── AppIcon256@2x.png
│ │ ├── AppIcon32.png
│ │ ├── AppIcon32@2x.png
│ │ ├── AppIcon512.png
│ │ ├── AppIcon512@2x.png
│ │ └── Contents.json
│ ├── icon-lastfm.imageset
│ │ ├── Contents.json
│ │ ├── icon-lastfm.png
│ │ └── icon-lastfm@2x.png
│ ├── menuBarIcon.imageset
│ │ ├── Contents.json
│ │ ├── menuBarIcon.png
│ │ └── menuBarIcon@2x.png
│ ├── menuBarIcon_active.imageset
│ │ ├── Contents.json
│ │ ├── menuBarIcon_active.png
│ │ └── menuBarIcon_active@2x.png
│ ├── plaetzchen.imageset
│ │ ├── Contents.json
│ │ ├── plaetzchen.png
│ │ └── plaetzchen@2x.png
│ └── zutrinken.imageset
│ │ ├── Contents.json
│ │ ├── zutrinken.png
│ │ └── zutrinken@2x.png
├── IsRepostedLabelView.h
├── IsRepostedLabelView.m
├── LoadSpeakerOverlayView.h
├── LoadSpeakerOverlayView.m
├── LowerShadowView.h
├── LowerShadowView.m
├── MouseOverImageView.h
├── MouseOverImageView.m
├── NSImage+RoundedCorners.h
├── NSImage+RoundedCorners.m
├── NextButtonCell.h
├── NextButtonCell.m
├── OAuth2Client.framework
│ ├── Headers
│ ├── OAuth2Client
│ ├── Resources
│ └── Versions
│ │ ├── A
│ │ ├── Headers
│ │ │ ├── NSData+NXOAuth2.h
│ │ │ ├── NSString+NXOAuth2.h
│ │ │ ├── NSURL+NXOAuth2.h
│ │ │ ├── NXOAuth2.h
│ │ │ ├── NXOAuth2AccessToken.h
│ │ │ ├── NXOAuth2Account.h
│ │ │ ├── NXOAuth2AccountStore.h
│ │ │ ├── NXOAuth2Client.h
│ │ │ ├── NXOAuth2ClientDelegate.h
│ │ │ ├── NXOAuth2Connection.h
│ │ │ ├── NXOAuth2ConnectionDelegate.h
│ │ │ ├── NXOAuth2Constants.h
│ │ │ ├── NXOAuth2FileStreamWrapper.h
│ │ │ ├── NXOAuth2PostBodyStream.h
│ │ │ ├── NXOAuth2Request.h
│ │ │ └── NXOAuth2TrustDelegate.h
│ │ ├── OAuth2Client
│ │ └── Resources
│ │ │ └── Info.plist
│ │ └── Current
├── PlayPauseButtonCell.h
├── PlayPauseButtonCell.m
├── PlayPauseOverlayView.h
├── PlayPauseOverlayView.m
├── PlayingIndicatorView.h
├── PlayingIndicatorView.m
├── PreviousButtonCell.h
├── PreviousButtonCell.m
├── ProgressIndicatorView.h
├── ProgressIndicatorView.m
├── ProgressSliderCell.h
├── ProgressSliderCell.m
├── ProgressSliderView.h
├── ProgressSliderView.m
├── RepeatButtonCell.h
├── RepeatButtonCell.m
├── SeperatorView.h
├── SeperatorView.m
├── SettingsViewController.h
├── SettingsViewController.m
├── SharedAudioPlayer.h
├── SharedAudioPlayer.m
├── ShuffleButtonCell.h
├── ShuffleButtonCell.m
├── SoundCloudAPI.framework
│ ├── Headers
│ ├── Resources
│ ├── SoundCloudAPI
│ └── Versions
│ │ ├── A
│ │ ├── Headers
│ │ │ ├── SCAPI.h
│ │ │ ├── SCAccount+Private.h
│ │ │ ├── SCAccount.h
│ │ │ ├── SCConstants.h
│ │ │ ├── SCRequest.h
│ │ │ ├── SCSoundCloud+Private.h
│ │ │ └── SCSoundCloud.h
│ │ ├── Resources
│ │ │ └── Info.plist
│ │ └── SoundCloudAPI
│ │ └── Current
├── SoundCloudAPIClient.h
├── SoundCloudAPIClient.m
├── SoundCloudItem.h
├── SoundCloudItem.m
├── SoundCloudPlaylist.h
├── SoundCloudPlaylist.m
├── SoundCloudTrack.h
├── SoundCloudTrack.m
├── SoundCloudUser.h
├── SoundCloudUser.m
├── SoundcloudPlayer-Info.plist
├── SoundcloudPlayer-Prefix.pch
├── SoundcloudPlayer.entitlements
├── StatusBarPlayerViewController.h
├── StatusBarPlayerViewController.m
├── StatusBarPlayerViewController.xib
├── StreamCloudApplication.h
├── StreamCloudApplication.m
├── StreamCloudStyles.h
├── StreamCloudStyles.m
├── TrackCellForPlaylistItemView.h
├── TrackCellForPlaylistItemView.m
├── TrackCellView.h
├── TrackCellView.m
├── UpperShadowView.h
├── UpperShadowView.m
├── VolumeButtonCell.h
├── VolumeButtonCell.m
├── WhiteBackgroundView.h
├── WhiteBackgroundView.m
├── en.lproj
│ ├── Credits.rtf
│ └── InfoPlist.strings
├── main.m
└── singleton.h
├── SoundcloudPlayerTests
├── SoundcloudPlayerTests-Info.plist
├── SoundcloudPlayerTests.m
└── en.lproj
│ └── InfoPlist.strings
├── StreamCloud copy-Info.plist
├── streamcloud-icons.pcvd
└── streamcloud_beta.plist
/.gitignore:
--------------------------------------------------------------------------------
1 | # CocoaPods
2 | #
3 | # We recommend against adding the Pods directory to your .gitignore. However
4 | # you should judge for yourself, the pros and cons are mentioned at:
5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control?
6 | #
7 | Pods/
8 | #########################
9 | # .gitignore file for Xcode4 / OS X Source projects
10 | #
11 | # NB: if you are storing "built" products, this WILL NOT WORK,
12 | # and you should use a different .gitignore (or none at all)
13 | # This file is for SOURCE projects, where there are many extra
14 | # files that we want to exclude
15 | #
16 | # For updates, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects
17 | #########################
18 |
19 | #####
20 | # OS X temporary files that should never be committed
21 |
22 | .DS_Store
23 | *.swp
24 | *.lock
25 | profile
26 | !Podfile.lock
27 |
28 | ####
29 | # Xcode temporary files that should never be committed
30 | #
31 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this...
32 |
33 | *~.nib
34 |
35 |
36 | ####
37 | # Xcode build files -
38 | #
39 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData"
40 |
41 | DerivedData/
42 |
43 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build"
44 |
45 | build/
46 |
47 |
48 | #####
49 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups)
50 | #
51 | # This is complicated:
52 | #
53 | # SOMETIMES you need to put this file in version control.
54 | # Apple designed it poorly - if you use "custom executables", they are
55 | # saved in this file.
56 | # 99% of projects do NOT use those, so they do NOT want to version control this file.
57 | # ..but if you're in the 1%, comment out the line "*.pbxuser"
58 |
59 | *.pbxuser
60 | *.mode1v3
61 | *.mode2v3
62 | *.perspectivev3
63 | # NB: also, whitelist the default ones, some projects need to use these
64 | !default.pbxuser
65 | !default.mode1v3
66 | !default.mode2v3
67 | !default.perspectivev3
68 |
69 |
70 | ####
71 | # Xcode 4 - semi-personal settings, often included in workspaces
72 | #
73 | # You can safely ignore the xcuserdata files - but do NOT ignore the files next to them
74 | #
75 |
76 | xcuserdata
77 |
78 |
79 | ####
80 | # XCode 4 workspaces - more detailed
81 | #
82 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :)
83 | #
84 | # Workspace layout is quite spammy. For reference:
85 | #
86 | # (root)/
87 | # (project-name).xcodeproj/
88 | # project.pbxproj
89 | # project.xcworkspace/
90 | # contents.xcworkspacedata
91 | # xcuserdata/
92 | # (your name)/xcuserdatad/
93 | # xcuserdata/
94 | # (your name)/xcuserdatad/
95 | #
96 | #
97 | #
98 | # Xcode 4 workspaces - SHARED
99 | #
100 | # This is UNDOCUMENTED (google: "developer.apple.com xcshareddata" - 0 results
101 | # But if you're going to kill personal workspaces, at least keep the shared ones...
102 | #
103 | #
104 | !xcshareddata
105 |
106 |
107 | ####
108 | # Xcode 4 - Deprecated classes
109 | #
110 | # Allegedly, if you manually "deprecate" your classes, they get moved here.
111 | #
112 | # We're using source-control, so this is a "feature" that we do not want!
113 |
114 | *.moved-aside
115 |
116 |
117 | ####
118 | # XCode 4 build-schemes
119 | #
120 | # PRIVATE ones are stored inside xcuserdata
121 | !xcschemes
122 |
123 | *.idea
124 |
125 | Pods
126 | *.trace
127 | *.xccheckout
128 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "OAuth2Client"]
2 | path = OAuth2Client
3 | url = https://github.com/nxtbgthng/OAuth2Client.git
4 | [submodule "CocoaSoundCloudAPI"]
5 | path = CocoaSoundCloudAPI
6 | url = https://github.com/soundcloud/CocoaSoundCloudAPI.git
7 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We love pull requests. Take a look at the [issues](https://github.com/plaetzchen/StreamCloud/issues) and filter by milestones to see what features are planned for the next release. Naturally we appreciate all kind of improvements. Here's a quick guide how to contribute.
4 |
5 | 1. Fork, then clone the repo:
6 |
7 | $ git clone git@github.com:your-username/StreamCloud.git
8 |
9 | 2. Create your feature branch:
10 |
11 | $ git checkout -b my-new-feature
12 |
13 | 3. Commit your changes:
14 |
15 | $ git commit -am 'Added some feature'
16 |
17 | 4. Push to the branch:
18 |
19 | $ git push origin my-new-feature
20 |
21 | 5. Submit a new [pull request](https://github.com/plaetzchen/StreamCloud/compare).
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2015 Peter Amende, Philip Brechler
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 | OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 |
3 | platform :osx, '10.8'
4 |
5 | abstract_target 'defaults' do
6 | pod 'AFNetworking', '~> 2.3'
7 | pod 'AXStatusItemPopup', :git => 'https://github.com/plaetzchen/AXStatusItemPopup.git', :tag => '0.0.5'
8 | pod 'LastFm', :inhibit_warnings => true
9 | pod 'HockeySDK-Mac', '~> 2.1'
10 | pod 'MASShortcut', '~> 1.2'
11 |
12 | target 'StreamCloud'
13 | target 'StreamCloud Beta'
14 | end
15 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - AFNetworking (2.5.4):
3 | - AFNetworking/NSURLConnection (= 2.5.4)
4 | - AFNetworking/NSURLSession (= 2.5.4)
5 | - AFNetworking/Reachability (= 2.5.4)
6 | - AFNetworking/Security (= 2.5.4)
7 | - AFNetworking/Serialization (= 2.5.4)
8 | - AFNetworking/UIKit (= 2.5.4)
9 | - AFNetworking/NSURLConnection (2.5.4):
10 | - AFNetworking/Reachability
11 | - AFNetworking/Security
12 | - AFNetworking/Serialization
13 | - AFNetworking/NSURLSession (2.5.4):
14 | - AFNetworking/Reachability
15 | - AFNetworking/Security
16 | - AFNetworking/Serialization
17 | - AFNetworking/Reachability (2.5.4)
18 | - AFNetworking/Security (2.5.4)
19 | - AFNetworking/Serialization (2.5.4)
20 | - AXStatusItemPopup (0.0.5)
21 | - HockeySDK-Mac (2.1.0)
22 | - KissXML (5.0)
23 | - LastFm (1.15.0):
24 | - KissXML (~> 5.0)
25 | - MASShortcut (1.3.1)
26 |
27 | DEPENDENCIES:
28 | - AFNetworking (~> 2.3)
29 | - AXStatusItemPopup (from `https://github.com/plaetzchen/AXStatusItemPopup.git`, tag `0.0.5`)
30 | - HockeySDK-Mac (~> 2.1)
31 | - LastFm
32 | - MASShortcut (~> 1.2)
33 |
34 | EXTERNAL SOURCES:
35 | AXStatusItemPopup:
36 | :git: https://github.com/plaetzchen/AXStatusItemPopup.git
37 | :tag: 0.0.5
38 |
39 | CHECKOUT OPTIONS:
40 | AXStatusItemPopup:
41 | :git: https://github.com/plaetzchen/AXStatusItemPopup.git
42 | :tag: 0.0.5
43 |
44 | SPEC CHECKSUMS:
45 | AFNetworking: 05edc0ac4c4c8cf57bcf4b84be5b0744b6d8e71e
46 | AXStatusItemPopup: 88877807fba6a95676656ad150867edd82979f99
47 | HockeySDK-Mac: c9a7743fbe181e1a1dd027043d708d65ce4c2726
48 | KissXML: ce643413d618ad69886d0d43c3792b7dedfe476e
49 | LastFm: 28c752f8e8646531524a123ce7f6722bbfc9d3c5
50 | MASShortcut: 65f5fac12bbdd3622abcb8175a633f68f553c60f
51 |
52 | PODFILE CHECKSUM: ea70c3b4a7078dfe6e0bcd0caebd9003a529b830
53 |
54 | COCOAPODS: 1.0.0
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # StreamCloud
2 |
3 | StreamCloud is a free SoundCloud app for Mac.
4 |
5 | * [Website](http://streamcloud.cc/)
6 | * [AppStore](https://itunes.apple.com/app/streamcloud/id894578573)
7 |
8 | ## How to build
9 |
10 | $ git clone git@github.com:streamcloudapp/StreamCloud.git
11 | $ cd StreamCloud
12 | $ pod install
13 | $ open SoundcloudPlayer.xcworkspace
14 |
15 | ## Contributing
16 |
17 | If you want to push StreamCloud to the next level say hi on [Twitter](https://twitter.com/StreamCloudApp) or via [email](mailto:mail@streamcloud.cc), take a look at our [contribution guide](https://github.com/streamcloudapp/StreamCloud/blob/master/CONTRIBUTING.md) and take a look at the [issues](https://github.com/streamcloudapp/StreamCloud/issues) with a lot of awesome features.
18 |
19 | For visual tasks hit on [zutrinken](https://github.com/zutrinken) to get access to the design sources. All graphics are managed with [PaintCode](http://www.paintcodeapp.com/).
20 |
21 | ## Copyright & License
22 |
23 | Copyright (c) 2014-2015 Peter Amende, Philip Brechler - Released under the [MIT license](https://github.com/streamcloudapp/StreamCloud/blob/master/LICENSE).
24 |
--------------------------------------------------------------------------------
/SoundcloudPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SoundcloudPlayer.xcodeproj/xcshareddata/xcschemes/StreamCloud Beta.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
51 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/SoundcloudPlayer.xcodeproj/xcshareddata/xcschemes/StreamCloud.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
51 |
52 |
61 |
63 |
69 |
70 |
71 |
72 |
73 |
74 |
80 |
82 |
88 |
89 |
90 |
91 |
93 |
94 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/SoundcloudPlayer.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 20.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AXStatusItemPopup.h"
11 | #import "StatusBarPlayerViewController.h"
12 | #import "ProgressSliderView.h"
13 |
14 | @interface AppDelegate : NSObject
15 |
16 | @property (assign) IBOutlet NSWindow *window;
17 | @property (nonatomic, strong) IBOutlet ProgressSliderView *playerTimeSlider;
18 | @property (nonatomic, strong) IBOutlet NSTextField *timeToGoLabel;
19 | @property (nonatomic, strong) IBOutlet NSTextField *timeGoneLabel;
20 | @property (nonatomic, strong) IBOutlet NSTableView *tableView;
21 | @property (nonatomic, strong) IBOutlet NSSlider *playerVolumeSlider;
22 | @property (nonatomic, strong) IBOutlet NSPopover *volumePopover;
23 | @property (nonatomic, strong) IBOutlet NSButton *volumeButton;
24 | @property (nonatomic, strong) AXStatusItemPopup *statusItemPopup;
25 | @property (nonatomic, strong) StatusBarPlayerViewController *statusBarPlayerViewController;
26 | @property (nonatomic) BOOL atBottom;
27 | @property (nonatomic, strong) IBOutlet NSPanel *aboutPanel;
28 | @property (nonatomic, strong) IBOutlet NSSegmentedControl *switchStreamLikesSegmentedControl;
29 | @property (nonatomic) NSInteger currentlySelectedStream;
30 |
31 | @property (nonatomic, strong) IBOutlet NSPanel *settingsPanel;
32 |
33 | @property (nonatomic, strong) IBOutlet NSMenuItem *trackNameDockMenuItem;
34 |
35 | @property (nonatomic, strong) IBOutlet NSTextField *loginTextField;
36 | @property (nonatomic, strong) IBOutlet NSButton *loginButton;
37 |
38 | - (IBAction)playButtonAction:(id)sender;
39 | - (IBAction)nextButtonAction:(id)sender;
40 | - (IBAction)previousButtonAction:(id)sender;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/AppleMediaKeyController.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppleMediaKeyController.h
3 | //
4 | // Modified by Gaurav Khanna on 8/17/10.
5 | // SOURCE: http://github.com/sweetfm/SweetFM/blob/master/Source/HMediaKeys.h
6 | //
7 | //
8 | // Permission is hereby granted, free of charge, to any person
9 | // obtaining a copy of this software and associated documentation
10 | // files (the "Software"), to deal in the Software without restriction,
11 | // including without limitation the rights to use, copy, modify,
12 | // merge, publish, distribute, sublicense, and/or sell copies of
13 | // the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be
17 | // included in all copies or substantial portions of the Software.
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22 | // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 | //
26 |
27 | #import "singleton.h"
28 | #import
29 |
30 | extern NSString * const MediaKeyPlayPauseNotification;
31 | extern NSString * const MediaKeyNextNotification;
32 | extern NSString * const MediaKeyPreviousNotification;
33 |
34 | @interface AppleMediaKeyController : NSObject {
35 | CFMachPortRef _eventPort;
36 | CFRunLoopSourceRef _runLoopSource;
37 | }
38 |
39 | @property(nonatomic, assign, readonly) CFMachPortRef eventPort;
40 |
41 | + (id)sharedController;
42 |
43 | @end
--------------------------------------------------------------------------------
/SoundcloudPlayer/AppleMediaKeyController.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppleMediaKeyController.m
3 | //
4 | // Modified by Gaurav Khanna on 8/17/10.
5 | // SOURCE: http://github.com/sweetfm/SweetFM/blob/master/Source/HMediaKeys.m
6 | // SOURCE: http://stackoverflow.com/questions/2969110/cgeventtapcreate-breaks-down-mysteriously-with-key-down-events
7 | //
8 | //
9 | // Permission is hereby granted, free of charge, to any person
10 | // obtaining a copy of this software and associated documentation
11 | // files (the "Software"), to deal in the Software without restriction,
12 | // including without limitation the rights to use, copy, modify,
13 | // merge, publish, distribute, sublicense, and/or sell copies of
14 | // the Software, and to permit persons to whom the Software is
15 | // furnished to do so, subject to the following conditions:
16 | //
17 | // The above copyright notice and this permission notice shall be
18 | // included in all copies or substantial portions of the Software.
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 | // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
23 | // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
24 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 | //
27 |
28 | #import "AppleMediaKeyController.h"
29 |
30 | NSString * const MediaKeyPlayPauseNotification = @"MediaKeyPlayPauseNotification";
31 | NSString * const MediaKeyNextNotification = @"MediaKeyNextNotification";
32 | NSString * const MediaKeyPreviousNotification = @"MediaKeyPreviousNotification";
33 |
34 | #define NX_KEYSTATE_UP 0x0A
35 | #define NX_KEYSTATE_DOWN 0x0B
36 |
37 | @implementation AppleMediaKeyController
38 |
39 | @synthesize eventPort = _eventPort;
40 |
41 | MAKE_SINGLETON(AppleMediaKeyController, sharedController)
42 |
43 | CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
44 | if(type == kCGEventTapDisabledByTimeout)
45 | CGEventTapEnable([[AppleMediaKeyController sharedController] eventPort], TRUE);
46 |
47 | if(type != NX_SYSDEFINED)
48 | return event;
49 |
50 | NSEvent *nsEvent = [NSEvent eventWithCGEvent:event];
51 |
52 | if([nsEvent subtype] != 8)
53 | return event;
54 |
55 | int data = (int)[nsEvent data1];
56 | int keyCode = (data & 0xFFFF0000) >> 16;
57 | int keyFlags = (data & 0xFFFF);
58 | int keyState = (keyFlags & 0xFF00) >> 8;
59 | BOOL keyIsRepeat = (keyFlags & 0x1) > 0;
60 |
61 | if(keyIsRepeat)
62 | return event;
63 |
64 | NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
65 | switch (keyCode) {
66 | case NX_KEYTYPE_PLAY:
67 | if(keyState == NX_KEYSTATE_DOWN)
68 | [center postNotificationName:MediaKeyPlayPauseNotification object:(AppleMediaKeyController *)refcon];
69 | if(keyState == NX_KEYSTATE_UP || keyState == NX_KEYSTATE_DOWN)
70 | return NULL;
71 | break;
72 | case NX_KEYTYPE_FAST:
73 | if(keyState == NX_KEYSTATE_DOWN)
74 | [center postNotificationName:MediaKeyNextNotification object:(AppleMediaKeyController *)refcon];
75 | if(keyState == NX_KEYSTATE_UP || keyState == NX_KEYSTATE_DOWN)
76 | return NULL;
77 | break;
78 | case NX_KEYTYPE_REWIND:
79 | if(keyState == NX_KEYSTATE_DOWN)
80 | [center postNotificationName:MediaKeyPreviousNotification object:(AppleMediaKeyController *)refcon];
81 | if(keyState == NX_KEYSTATE_UP || keyState == NX_KEYSTATE_DOWN)
82 | return NULL;
83 | break;
84 | }
85 | return event;
86 | }
87 |
88 | - (id)init {
89 | if(self = [super init]) {
90 | CFRunLoopRef runLoop;
91 |
92 | _eventPort = CGEventTapCreate(kCGSessionEventTap,
93 | kCGHeadInsertEventTap,
94 | kCGEventTapOptionDefault,
95 | CGEventMaskBit(NX_SYSDEFINED),
96 | tapEventCallback,
97 | self);
98 |
99 | if(_eventPort == NULL) {
100 | NSLog(@"Fatal Error: Event Tap could not be created");
101 | return self;
102 | }
103 |
104 | _runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0);
105 |
106 | if(_runLoopSource == NULL) {
107 | NSLog(@"Fatal Error: Run Loop Source could not be created");
108 | return self;
109 | }
110 |
111 | runLoop = CFRunLoopGetCurrent();
112 |
113 | if(runLoop == NULL) {
114 | NSLog(@"Fatal Error: Couldn't get current threads Run Loop");
115 | return self;
116 | }
117 |
118 | CFRunLoopAddSource(runLoop, _runLoopSource, kCFRunLoopCommonModes);
119 | }
120 | return self;
121 | }
122 |
123 | - (void)dealloc {
124 | CFRelease(_eventPort);
125 | CFRelease(_runLoopSource);
126 | [super dealloc];
127 | }
128 |
129 | @end
--------------------------------------------------------------------------------
/SoundcloudPlayer/ArtworkOverlayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ArtworkOverlayView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ArtworkOverlayView : NSView
12 |
13 | - (void)hideWithFadeOut;
14 | @end
15 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ArtworkOverlayView.m:
--------------------------------------------------------------------------------
1 |
2 | //
3 | // ArtworkOverlayView.m
4 | // SoundcloudPlayer
5 | //
6 | // Created by Philip Brechler on 19.01.15.
7 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
8 | //
9 |
10 | #import "ArtworkOverlayView.h"
11 | #import "StreamCloudStyles.h"
12 |
13 | @import QuartzCore;
14 |
15 | @implementation ArtworkOverlayView
16 |
17 | - (void)drawRect:(NSRect)dirtyRect {
18 | [[StreamCloudStyles orangeDark] setFill];
19 | NSRectFill(dirtyRect);
20 | }
21 |
22 | - (void)hideWithFadeOut {
23 | [[NSAnimationContext currentContext] setDuration:0.7];
24 | [self.animator setAlphaValue:0.0];
25 |
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ClickableTableView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ClickableTableView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 29.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ClickableTableView : NSTableView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ClickableTableView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ClickableTableView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 29.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ClickableTableView.h"
10 |
11 | @implementation ClickableTableView
12 |
13 | - (void)mouseDown:(NSEvent *)theEvent {
14 | [super mouseDown:theEvent];
15 | if ([theEvent clickCount] == 1 ) {
16 | NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
17 | NSInteger row = [self rowAtPoint:selfPoint];
18 | if (row>=0) [[self viewAtColumn:0 row:row makeIfNecessary:NO]
19 | mouseDown:theEvent];
20 | }
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ClickableTextField.h:
--------------------------------------------------------------------------------
1 | //
2 | // ClickableTextField.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 29.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ClickableTextField : NSTextField
12 |
13 | @property (nonatomic, strong) NSString *urlToOpen;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ClickableTextField.m:
--------------------------------------------------------------------------------
1 | //
2 | // ClickableTextField.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 29.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ClickableTextField.h"
10 |
11 | @interface ClickableTextField ()
12 |
13 | @property (nonatomic, strong) NSTrackingArea *trackingArea;
14 |
15 | @end
16 |
17 | @implementation ClickableTextField
18 |
19 | - (id)initWithCoder:(NSCoder *)aDecoder {
20 | self = [super initWithCoder:aDecoder];
21 | if (self){
22 | [self commonInit];
23 | }
24 | return self;
25 | }
26 |
27 | - (id)initWithFrame:(NSRect)frameRect {
28 | self = [super initWithFrame:frameRect];
29 | if (self){
30 | [self commonInit];
31 | }
32 | return self;
33 | }
34 |
35 | - (void)commonInit {
36 | [[NSCursor pointingHandCursor] set];
37 | }
38 |
39 | - (void)mouseDown:(NSEvent *)theEvent {
40 | if (self.urlToOpen){
41 | [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:_urlToOpen]];
42 | }
43 | }
44 |
45 | - (void)mouseEntered:(NSEvent *)theEvent {
46 | if (self.urlToOpen) {
47 | [[NSCursor pointingHandCursor] set];
48 | NSMutableAttributedString *str = [[self attributedStringValue] mutableCopy];
49 |
50 | [str addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInt:NSUnderlineStyleSingle] range:NSMakeRange(0, str.length)];
51 |
52 | [self setAttributedStringValue:str];
53 | }
54 | }
55 |
56 | - (void)mouseExited:(NSEvent *)theEvent {
57 | if (self.urlToOpen) {
58 | [[NSCursor arrowCursor] set];
59 | NSMutableAttributedString *str = [[self attributedStringValue] mutableCopy];
60 |
61 | [str removeAttribute:NSUnderlineStyleAttributeName range:NSMakeRange(0, str.length)];
62 |
63 | [self setAttributedStringValue:str];
64 | }
65 | }
66 |
67 | - (void)updateTrackingAreas {
68 | [super updateTrackingAreas];
69 | [self removeTrackingArea:_trackingArea];
70 | _trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options: (NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow) owner:self userInfo:nil];
71 | [self addTrackingArea:_trackingArea];
72 | }
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ConnectButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ConnectButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ConnectButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ConnectButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ConnectButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ConnectButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | @implementation ConnectButtonCell
12 |
13 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
14 | [StreamCloudStyles drawLoginButtonWithFrame:frame];
15 | }
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "beta-16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "beta-16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "beta-32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "beta-32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "beta-128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "beta-128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "beta-256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "beta-256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "beta-512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "beta-512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-128.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-128@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-16.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-16@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-256.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-256@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-32.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-32@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-512.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon Beta.appiconset/beta-512@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon128.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon128@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon16.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon16@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon256.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon256@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon32.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon32@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon512.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/AppIcon512@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "AppIcon16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "AppIcon16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "AppIcon32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "AppIcon32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "AppIcon128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "AppIcon128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "AppIcon256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "AppIcon256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "AppIcon512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "AppIcon512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/icon-lastfm.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "icon-lastfm.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "icon-lastfm@2x.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/icon-lastfm.imageset/icon-lastfm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/icon-lastfm.imageset/icon-lastfm.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/icon-lastfm.imageset/icon-lastfm@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/icon-lastfm.imageset/icon-lastfm@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "menuBarIcon.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "menuBarIcon@2x.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon.imageset/menuBarIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/menuBarIcon.imageset/menuBarIcon.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon.imageset/menuBarIcon@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/menuBarIcon.imageset/menuBarIcon@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon_active.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "menuBarIcon_active.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "menuBarIcon_active@2x.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon_active.imageset/menuBarIcon_active.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/menuBarIcon_active.imageset/menuBarIcon_active.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/menuBarIcon_active.imageset/menuBarIcon_active@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/menuBarIcon_active.imageset/menuBarIcon_active@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/plaetzchen.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "plaetzchen.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "plaetzchen@2x.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/plaetzchen.imageset/plaetzchen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/plaetzchen.imageset/plaetzchen.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/plaetzchen.imageset/plaetzchen@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/plaetzchen.imageset/plaetzchen@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/zutrinken.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x",
6 | "filename" : "zutrinken.png"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x",
11 | "filename" : "zutrinken@2x.png"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "scale" : "3x"
16 | }
17 | ],
18 | "info" : {
19 | "version" : 1,
20 | "author" : "xcode"
21 | }
22 | }
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/zutrinken.imageset/zutrinken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/zutrinken.imageset/zutrinken.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/Images.xcassets/zutrinken.imageset/zutrinken@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/Images.xcassets/zutrinken.imageset/zutrinken@2x.png
--------------------------------------------------------------------------------
/SoundcloudPlayer/IsRepostedLabelView.h:
--------------------------------------------------------------------------------
1 | //
2 | // IsRepostedLabelView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 16.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface IsRepostedLabelView : NSView
12 |
13 | @property (nonatomic, strong) NSString *reposterName;
14 | @end
15 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/IsRepostedLabelView.m:
--------------------------------------------------------------------------------
1 | //
2 | // IsRepostedLabelView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 16.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "IsRepostedLabelView.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @implementation IsRepostedLabelView
13 |
14 | - (void)drawRect:(NSRect)dirtyRect {
15 | [StreamCloudStyles drawTrackIsRepostWithFrame:NSMakeRect(0.5, 1.5, 9, 9)];
16 |
17 | NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
18 | [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
19 | [self.reposterName drawInRect:NSMakeRect(13, -0.5, CGRectGetWidth(self.frame)-CGRectGetHeight(self.frame)-4, 15) withAttributes:@{NSFontAttributeName:[NSFont fontWithName:@"HelveticaNeue" size:10],NSForegroundColorAttributeName:[StreamCloudStyles grayMediumLight],NSParagraphStyleAttributeName:paragraphStyle}];
20 |
21 | }
22 |
23 | - (void)setReposterName:(NSString *)reposterName {
24 | _reposterName = reposterName;
25 | [self setNeedsDisplay:YES];
26 | }
27 |
28 | @end
29 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/LoadSpeakerOverlayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LoadSpeakerOverlayView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 04.08.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface LoadSpeakerOverlayView : NSView
12 |
13 | @property (nonatomic) BOOL showLargeIcon;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/LoadSpeakerOverlayView.m:
--------------------------------------------------------------------------------
1 | //
2 | // LoadSpeakerOverlayView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 04.08.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "LoadSpeakerOverlayView.h"
10 | #import "StreamCloudStyles.h"
11 | @implementation LoadSpeakerOverlayView
12 |
13 | - (void)setShowLargeIcon:(BOOL)showLargeIcon {
14 | _showLargeIcon = showLargeIcon;
15 | [self setNeedsDisplay:YES];
16 | }
17 |
18 | - (void)drawRect:(NSRect)dirtyRect {
19 | [StreamCloudStyles drawPlayingOverlayWithFrame:self.frame];
20 | }
21 | @end
22 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/LowerShadowView.h:
--------------------------------------------------------------------------------
1 | //
2 | // LowerShadowView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface LowerShadowView : NSView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/LowerShadowView.m:
--------------------------------------------------------------------------------
1 | //
2 | // LowerShadowView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "LowerShadowView.h"
10 | #import "StreamCloudStyles.h"
11 | @implementation LowerShadowView
12 |
13 | - (void)drawRect:(NSRect)dirtyRect {
14 | [StreamCloudStyles drawPlaylistLowerShadowOverlayWithFrame:dirtyRect];
15 | }
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/MouseOverImageView.h:
--------------------------------------------------------------------------------
1 | //
2 | // MouseOverImageView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SoundCloudTrack.h"
11 | #import "SoundCloudPlaylist.h"
12 | #import "PlayPauseOverlayView.h"
13 | #import "SharedAudioPlayer.h"
14 | #import "LoadSpeakerOverlayView.h"
15 |
16 | @interface MouseOverImageView : NSImageView
17 |
18 | @property (nonatomic) NSInteger row;
19 | @property (nonatomic) id objectToPlay;
20 | @property (nonatomic) BOOL showLargePlayPauseView;
21 | @property (nonatomic) BOOL playing;
22 | @property (nonatomic, strong) PlayPauseOverlayView *playPauseOverlayView;
23 | @property (nonatomic, strong) LoadSpeakerOverlayView *loadSpeakerOverlayView;
24 |
25 | - (void)cursorEntered;
26 | - (void)cursorExited;
27 | - (void)loadArtworkImageWithURL:(NSURL *)artworkURL;
28 | @end
29 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/MouseOverImageView.m:
--------------------------------------------------------------------------------
1 | //
2 | // MouseOverImageView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "MouseOverImageView.h"
10 | #import "PlayPauseOverlayView.h"
11 | #import "SharedAudioPlayer.h"
12 | #import "LoadSpeakerOverlayView.h"
13 | #import "AFNetworking.h"
14 | #import "ArtworkOverlayView.h"
15 |
16 | @interface MouseOverImageView ()
17 |
18 | @property (nonatomic, strong) NSTrackingArea *trackingArea;
19 | @property (nonatomic) BOOL mouseOver;
20 |
21 | @property (nonatomic, strong) ArtworkOverlayView *artworkOverlayView;
22 |
23 | @end
24 |
25 | @implementation MouseOverImageView
26 |
27 | - (id)initWithFrame:(NSRect)frame
28 | {
29 | self = [super initWithFrame:frame];
30 | if (self) {
31 | [self commonInit];
32 | }
33 | return self;
34 | }
35 |
36 |
37 | - (id)initWithCoder:(NSCoder *)aDecoder {
38 | self = [super initWithCoder:aDecoder];
39 | if (self){
40 | [self commonInit];
41 | }
42 | return self;
43 | }
44 |
45 | - (void)commonInit {
46 |
47 | self.artworkOverlayView = [[ArtworkOverlayView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, self.frame.size.height)];
48 | [self addSubview:self.artworkOverlayView];
49 |
50 | self.playPauseOverlayView = [[PlayPauseOverlayView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, self.frame.size.height)];
51 | [self.playPauseOverlayView setHidden:YES];
52 | [self.playPauseOverlayView setRow:self.row];
53 | [self addSubview:self.playPauseOverlayView];
54 |
55 | self.loadSpeakerOverlayView = [[LoadSpeakerOverlayView alloc] initWithFrame:NSMakeRect(0, 0, self.frame.size.width, self.frame.size.height)];
56 | [self.loadSpeakerOverlayView setHidden:YES];
57 | [self addSubview:self.loadSpeakerOverlayView];
58 |
59 |
60 | [self setWantsLayer: YES];
61 | self.layer.cornerRadius = 2.0;
62 | self.layer.masksToBounds = YES;
63 | }
64 |
65 | - (void)drawRect:(NSRect)dirtyRect
66 | {
67 | [super drawRect:dirtyRect];
68 |
69 | }
70 |
71 | - (void)setShowLargePlayPauseView:(BOOL)showLargePlayPauseView {
72 | _showLargePlayPauseView = showLargePlayPauseView;
73 | [self.playPauseOverlayView setShowLargeIcons:showLargePlayPauseView];
74 | }
75 |
76 | - (void)dealloc {
77 | [[NSNotificationCenter defaultCenter] removeObserver:self];
78 | }
79 |
80 | # pragma mark - Setters
81 |
82 | - (void)setImage:(NSImage *)image {
83 | [super setImage:image];
84 | if (!image){
85 | [self.artworkOverlayView setHidden:NO];
86 | [self.artworkOverlayView setAlphaValue:1.0];
87 | }
88 | }
89 |
90 |
91 | - (void)setRow:(NSInteger)row {
92 | _row = row;
93 | [self.playPauseOverlayView setRow:row];
94 | }
95 |
96 | - (void)setObjectToPlay:(NSDictionary *)objectToPlay {
97 | _objectToPlay = objectToPlay;
98 | [self.playPauseOverlayView setObjectToShow:objectToPlay];
99 | }
100 |
101 | - (void)setPlaying:(BOOL)playing {
102 | _playing = playing;
103 | [self.loadSpeakerOverlayView setHidden:!playing];
104 | [self.playPauseOverlayView setHidden:YES];
105 | }
106 |
107 | # pragma mark - Loading Artwork
108 |
109 | - (void)loadArtworkImageWithURL:(NSURL *)artworkURL {
110 | if (artworkURL){
111 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
112 | manager.responseSerializer = [AFImageResponseSerializer serializer];
113 | [manager GET:artworkURL.absoluteString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
114 | [self setImage:responseObject];
115 | [self.artworkOverlayView hideWithFadeOut];
116 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
117 | NSLog(@"Failed to get image %@",error);
118 | }];
119 | }
120 | }
121 |
122 | # pragma mark - Mouse Handling
123 |
124 | - (void)cursorEntered {
125 | self.mouseOver = YES;
126 | [self.playPauseOverlayView setHidden:NO];
127 | [self.loadSpeakerOverlayView setHidden:YES];
128 | [self.playPauseOverlayView setNeedsDisplay:YES];
129 | }
130 |
131 | - (void)cursorExited {
132 | self.mouseOver = NO;
133 | [self.playPauseOverlayView setHidden:YES];
134 | [self setPlaying:_playing];
135 | }
136 |
137 | - (void)mouseDown:(NSEvent *)theEvent {
138 | if (self.objectToPlay == [[SharedAudioPlayer sharedPlayer] currentItem])
139 | [[SharedAudioPlayer sharedPlayer] togglePlayPause];
140 | else if ([[[SharedAudioPlayer sharedPlayer] streamItemsToShowInTableView]indexOfObject:[[[SharedAudioPlayer sharedPlayer]currentItem] playlistTrackIsFrom]] == self.row)
141 | [[SharedAudioPlayer sharedPlayer] togglePlayPause];
142 | else {
143 | if ([[SharedAudioPlayer sharedPlayer].streamItemsToShowInTableView containsObject:self.objectToPlay] && [SharedAudioPlayer sharedPlayer].sourceType != CurrentSourceTypeStream){
144 | [[SharedAudioPlayer sharedPlayer] switchToStream];
145 | } else if ([[SharedAudioPlayer sharedPlayer].favoriteItemsToShowInTableView containsObject:self.objectToPlay] && [SharedAudioPlayer sharedPlayer].sourceType != CurrentSourceTypeFavorites) {
146 | [[SharedAudioPlayer sharedPlayer] switchToFavorites];
147 | }
148 |
149 | NSInteger clickedRow = self.row;
150 | id clickedItem = self.objectToPlay;
151 | if ([SharedAudioPlayer sharedPlayer].sourceType == CurrentSourceTypeStream) {
152 | if ([clickedItem isKindOfClass:[SoundCloudPlaylist class]]){
153 | clickedItem = [[[SharedAudioPlayer sharedPlayer] streamItemsToShowInTableView] objectAtIndex:clickedRow+1];
154 | }
155 |
156 | NSInteger objectToPlay = [[[SharedAudioPlayer sharedPlayer] streamItemsToShowInTableView] indexOfObject:clickedItem];
157 | [[SharedAudioPlayer sharedPlayer] jumpToItemAtIndex:objectToPlay];
158 | } else if ([SharedAudioPlayer sharedPlayer].sourceType == CurrentSourceTypeFavorites) {
159 | if ([clickedItem isKindOfClass:[SoundCloudPlaylist class]]){
160 | clickedItem = [[[SharedAudioPlayer sharedPlayer] favoriteItemsToShowInTableView] objectAtIndex:clickedRow+1];
161 | }
162 |
163 | NSInteger objectToPlay = [[[SharedAudioPlayer sharedPlayer] favoriteItemsToShowInTableView] indexOfObject:clickedItem];
164 | [[SharedAudioPlayer sharedPlayer] jumpToItemAtIndex:objectToPlay];
165 |
166 | }
167 | [self.playPauseOverlayView setHidden:YES];
168 | }
169 | [self.playPauseOverlayView setNeedsDisplay:YES];
170 | }
171 |
172 |
173 | @end
174 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/NSImage+RoundedCorners.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSImage+RoundedCorners.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 04.08.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NSImage (RoundedCorners)
12 |
13 | - (NSImage *)roundCornersImageCornerRadius:(NSInteger)radius;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/NSImage+RoundedCorners.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSImage+RoundedCorners.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 04.08.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "NSImage+RoundedCorners.h"
10 |
11 | @implementation NSImage (RoundedCorners)
12 |
13 |
14 | void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
15 | {
16 | float fw, fh;
17 | if (ovalWidth == 0 || ovalHeight == 0) {
18 | CGContextAddRect(context, rect);
19 | return;
20 | }
21 | CGContextSaveGState(context);
22 | CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
23 | CGContextScaleCTM (context, ovalWidth, ovalHeight);
24 | fw = CGRectGetWidth (rect) / ovalWidth;
25 | fh = CGRectGetHeight (rect) / ovalHeight;
26 | CGContextMoveToPoint(context, fw, fh/2);
27 | CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
28 | CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
29 | CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
30 | CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
31 | CGContextClosePath(context);
32 | CGContextRestoreGState(context);
33 | }
34 |
35 | - (NSImage *)roundCornersImageCornerRadius:(NSInteger)radius {
36 | int w = (int) self.size.width;
37 | int h = (int) self.size.height;
38 |
39 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
40 | CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
41 |
42 | CGContextBeginPath(context);
43 | CGRect rect = CGRectMake(0, 0, w, h);
44 | addRoundedRectToPath(context, rect, radius, radius);
45 | CGContextClosePath(context);
46 | CGContextClip(context);
47 |
48 | CGImageRef cgImage = [[NSBitmapImageRep imageRepWithData:[self TIFFRepresentation]] CGImage];
49 |
50 | CGContextDrawImage(context, CGRectMake(0, 0, w, h), cgImage);
51 |
52 | CGImageRef imageMasked = CGBitmapContextCreateImage(context);
53 | CGContextRelease(context);
54 | CGColorSpaceRelease(colorSpace);
55 |
56 | NSImage *tmpImage = [[NSImage alloc] initWithCGImage:imageMasked size:self.size];
57 | NSData *imageData = [tmpImage TIFFRepresentation];
58 | NSImage *image = [[NSImage alloc] initWithData:imageData];
59 |
60 | return image;
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/NextButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // NextButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface NextButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/NextButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // NextButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "NextButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | @implementation NextButtonCell
12 |
13 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
14 | [StreamCloudStyles drawNextButtonWithFrame:frame];
15 | }
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/OAuth2Client:
--------------------------------------------------------------------------------
1 | Versions/Current/OAuth2Client
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NSData+NXOAuth2.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+NXOAuth2.h
3 | // OAuth2Client
4 | //
5 | // Created by Thomas Kollbach on 18.05.11
6 | //
7 | // Copyright 2011 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 |
17 | @interface NSData (NXOAuth2)
18 |
19 |
20 | #pragma mark Digest
21 |
22 | - (NSData *)nx_SHA1Digest;
23 | - (NSString *)nx_SHA1Hexdigest;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NSString+NXOAuth2.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSString+NXOAuth2.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 07.10.09.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 |
17 | @interface NSString (NXOAuth2)
18 |
19 | + (NSString *)nxoauth2_stringWithUUID;
20 |
21 | + (NSString *)nxoauth2_stringWithEncodedQueryParameters:(NSDictionary *)parameters;
22 | - (NSDictionary *)nxoauth2_parametersFromEncodedQueryString;
23 |
24 | - (NSString *)nxoauth2_URLEncodedString;
25 | - (NSString *)nxoauth2_URLDecodedString;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NSURL+NXOAuth2.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSURL+NXOAuth2.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 07.10.09.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | @interface NSURL (NXOAuth2)
17 |
18 | - (NSURL *)nxoauth2_URLByAddingParameters:(NSDictionary *)parameters;
19 |
20 | /*!
21 | * returns the value of the first parameter on the query string that matches the key
22 | * returns nil if key was not found
23 | */
24 | - (NSString *)nxoauth2_valueForQueryParameterKey:(NSString *)key;
25 |
26 | - (NSURL *)nxoauth2_URLWithoutQueryString;
27 | - (NSString *)nxoauth2_URLStringWithoutQueryString;
28 |
29 | @end
30 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 13.09.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import "NXOAuth2Client.h"
15 | #import "NXOAuth2ClientDelegate.h"
16 | #import "NXOAuth2AccessToken.h"
17 | #import "NXOAuth2Connection.h"
18 | #import "NXOAuth2ConnectionDelegate.h"
19 | #import "NXOAuth2TrustDelegate.h"
20 | #import "NXOAuth2Constants.h"
21 | #import "NXOAuth2FileStreamWrapper.h"
22 | #import "NXOAuth2PostBodyStream.h"
23 | #import "NXOAuth2AccountStore.h"
24 | #import "NXOAuth2Account.h"
25 | #import "NXOAuth2Request.h"
26 |
27 | #pragma mark Helpers
28 |
29 | #import "NSURL+NXOAuth2.h"
30 | #import "NSString+NXOAuth2.h"
31 | #import "NSData+NXOAuth2.h"
32 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2AccessToken.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2AccessToken.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 | #import
16 |
17 |
18 | @interface NXOAuth2AccessToken : NSObject {
19 | @private
20 | NSString *accessToken;
21 | NSString *refreshToken;
22 | NSString *tokenType;
23 | NSDate *expiresAt;
24 | NSSet *scope;
25 | NSString *responseBody;
26 | }
27 | @property (nonatomic, readonly) NSString *accessToken;
28 | @property (nonatomic, readonly) NSString *refreshToken;
29 | @property (nonatomic, readonly) NSString *tokenType;
30 | @property (nonatomic, readonly) NSDate *expiresAt;
31 | @property (nonatomic, readonly) BOOL doesExpire;
32 | @property (nonatomic, readonly) BOOL hasExpired;
33 | @property (nonatomic, readonly) NSSet *scope;
34 | @property (nonatomic, readonly) NSString *responseBody;
35 |
36 | + (id)tokenWithResponseBody:(NSString *)responseBody;
37 | + (id)tokenWithResponseBody:(NSString *)responseBody tokenType:(NSString *)tokenType;
38 |
39 | - (id)initWithAccessToken:(NSString *)accessToken;
40 | - (id)initWithAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken expiresAt:(NSDate *)expiryDate;
41 | - (id)initWithAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken expiresAt:(NSDate *)expiryDate scope:(NSSet *)scope;
42 | - (id)initWithAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken expiresAt:(NSDate *)expiryDate scope:(NSSet *)scope responseBody:(NSString *)responseBody;
43 | - (id)initWithAccessToken:(NSString *)accessToken refreshToken:(NSString *)refreshToken expiresAt:(NSDate *)expiryDate scope:(NSSet *)scope responseBody:(NSString *)responseBody tokenType:(NSString*)tokenType; // designated
44 |
45 | - (void)restoreWithOldToken:(NXOAuth2AccessToken *)oldToken;
46 |
47 | #pragma mark Keychain Support
48 |
49 | //TODO: Support alternate KeyChain Locations
50 |
51 | + (id)tokenFromDefaultKeychainWithServiceProviderName:(NSString *)provider;
52 | - (void)storeInDefaultKeychainWithServiceProviderName:(NSString *)provider;
53 | - (void)removeFromDefaultKeychainWithServiceProviderName:(NSString *)provider;
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2Account.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2Account.h
3 | // OAuth2Client
4 | //
5 | // Created by Tobias Kräntzer on 12.07.11.
6 | //
7 | // Copyright 2011 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | @class NXOAuth2Client;
17 | @class NXOAuth2AccessToken;
18 |
19 | #pragma mark Notifications
20 |
21 | extern NSString * const NXOAuth2AccountDidChangeUserDataNotification;
22 | extern NSString * const NXOAuth2AccountDidChangeAccessTokenNotification;
23 | extern NSString * const NXOAuth2AccountDidLoseAccessTokenNotification;
24 | extern NSString * const NXOAuth2AccountDidFailToGetAccessTokenNotification;
25 |
26 | #pragma mark -
27 |
28 | @interface NXOAuth2Account : NSObject {
29 | @private
30 | NSString *accountType;
31 | NSString *identifier;
32 | id userData;
33 | NXOAuth2Client *oauthClient;
34 | NXOAuth2AccessToken *accessToken;
35 | }
36 |
37 | #pragma mark Accessors
38 |
39 | @property (nonatomic, copy, readonly) NSString *accountType;
40 | @property (nonatomic, copy, readonly) NSString *identifier;
41 | @property (nonatomic, copy) id userData;
42 |
43 | @property (nonatomic, strong, readonly) NXOAuth2Client *oauthClient;
44 | @property (nonatomic, strong, readonly) NXOAuth2AccessToken *accessToken;
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2AccountStore.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2AccountStore.h
3 | // OAuth2Client
4 | //
5 | // Created by Tobias Kräntzer on 12.07.11.
6 | //
7 | // Copyright 2011 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | #import "NXOAuth2TrustDelegate.h"
17 |
18 | @class NXOAuth2Account;
19 | @class NXOAuth2Connection;
20 |
21 | #pragma mark Notifications
22 |
23 | extern NSString * const NXOAuth2AccountStoreDidFailToRequestAccessNotification;
24 | extern NSString * const NXOAuth2AccountStoreAccountsDidChangeNotification;
25 |
26 | extern NSString * const NXOAuth2AccountStoreNewAccountUserInfoKey;
27 |
28 | #pragma mark Configuration
29 |
30 | extern NSString * const kNXOAuth2AccountStoreConfigurationClientID;
31 | extern NSString * const kNXOAuth2AccountStoreConfigurationSecret;
32 | extern NSString * const kNXOAuth2AccountStoreConfigurationAuthorizeURL;
33 | extern NSString * const kNXOAuth2AccountStoreConfigurationTokenURL;
34 | extern NSString * const kNXOAuth2AccountStoreConfigurationRedirectURL;
35 | extern NSString * const kNXOAuth2AccountStoreConfigurationScope;
36 | extern NSString * const kNXOAuth2AccountStoreConfigurationTokenType;
37 | extern NSString * const kNXOAuth2AccountStoreConfigurationTokenRequestHTTPMethod;
38 |
39 |
40 | /*
41 | * Requires a NSDictionary as a value.
42 | * They are passed onto the authentication request as additional query parameters.
43 | * The dictionary may not contain the keys "grant_type", "client_id", "client_secret",
44 | * "username", "password", "redirect_uri", "code", "assertion_type" and "assertion" are not allowed.
45 | */
46 | extern NSString * const kNXOAuth2AccountStoreConfigurationAdditionalAuthenticationParameters;
47 |
48 |
49 | #pragma mark Account Type
50 |
51 | extern NSString * const kNXOAuth2AccountStoreAccountType;
52 |
53 |
54 | #pragma mark Handler
55 |
56 | typedef NXOAuth2TrustMode(^NXOAuth2TrustModeHandler)(NXOAuth2Connection *connection, NSString *hostname);
57 | typedef NSArray *(^NXOAuth2TrustedCertificatesHandler)(NSString *hostname);
58 | typedef void(^NXOAuth2PreparedAuthorizationURLHandler)(NSURL *preparedURL);
59 |
60 |
61 | #pragma mark -
62 |
63 | @interface NXOAuth2AccountStore : NSObject {
64 | @private
65 | NSMutableDictionary *pendingOAuthClients;
66 | NSMutableDictionary *accountsDict;
67 | NSMutableDictionary *configurations;
68 | NSMutableDictionary *trustModeHandler;
69 | NSMutableDictionary *trustedCertificatesHandler;
70 | }
71 |
72 | + (id)sharedStore;
73 |
74 | #pragma mark Accessors
75 |
76 | @property(nonatomic, strong, readonly) NSArray *accounts;
77 | - (NSArray *)accountsWithAccountType:(NSString *)accountType;
78 | - (NXOAuth2Account *)accountWithIdentifier:(NSString *)identifier;
79 |
80 |
81 | #pragma mark Configuration
82 |
83 | - (void)setClientID:(NSString *)aClientID
84 | secret:(NSString *)aSecret
85 | authorizationURL:(NSURL *)anAuthorizationURL
86 | tokenURL:(NSURL *)aTokenURL
87 | redirectURL:(NSURL *)aRedirectURL
88 | forAccountType:(NSString *)anAccountType;
89 |
90 | - (void)setClientID:(NSString *)aClientID
91 | secret:(NSString *)aSecret
92 | scope:(NSSet *)theScope
93 | authorizationURL:(NSURL *)anAuthorizationURL
94 | tokenURL:(NSURL *)aTokenURL
95 | redirectURL:(NSURL *)aRedirectURL
96 | keyChainGroup:(NSString *)aKeyChainGroup
97 | forAccountType:(NSString *)anAccountType;
98 |
99 | - (void)setClientID:(NSString *)aClientID
100 | secret:(NSString *)aSecret
101 | scope:(NSSet *)theScope
102 | authorizationURL:(NSURL *)anAuthorizationURL
103 | tokenURL:(NSURL *)aTokenURL
104 | redirectURL:(NSURL *)aRedirectURL
105 | keyChainGroup:(NSString *)aKeyChainGroup
106 | tokenType:(NSString *)aTokenType
107 | forAccountType:(NSString *)anAccountType;
108 |
109 | - (void)setConfiguration:(NSDictionary *)configuration forAccountType:(NSString *)accountType;
110 |
111 | - (NSDictionary *)configurationForAccountType:(NSString *)accountType;
112 |
113 |
114 | #pragma Trust Mode Handler
115 |
116 | - (void)setTrustModeHandlerForAccountType:(NSString *)accountType block:(NXOAuth2TrustModeHandler)handler;
117 | - (NXOAuth2TrustModeHandler)trustModeHandlerForAccountType:(NSString *)accountType;
118 |
119 | - (void)setTrustedCertificatesHandlerForAccountType:(NSString *)accountType block:(NXOAuth2TrustedCertificatesHandler)handler;
120 | - (NXOAuth2TrustedCertificatesHandler)trustedCertificatesHandlerForAccountType:(NSString *)accountType;
121 |
122 |
123 | #pragma mark Manage Accounts
124 |
125 | - (void)requestAccessToAccountWithType:(NSString *)accountType;
126 | - (void)requestAccessToAccountWithType:(NSString *)accountType withPreparedAuthorizationURLHandler:(NXOAuth2PreparedAuthorizationURLHandler)aPreparedAuthorizationURLHandler;
127 | - (void)requestAccessToAccountWithType:(NSString *)accountType username:(NSString *)username password:(NSString *)password;
128 | - (void)requestAccessToAccountWithType:(NSString *)accountType assertionType:(NSURL *)assertionType assertion:(NSString *)assertion;
129 | - (void)requestClientCredentialsAccessWithType:(NSString *)accountType;
130 | - (void)addAccount:(NXOAuth2Account *)account;
131 | - (void)removeAccount:(NXOAuth2Account *)account;
132 |
133 |
134 | #pragma mark Handle OAuth Redirects
135 |
136 | - (BOOL)handleRedirectURL:(NSURL *)URL;
137 |
138 | @end
139 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2Client.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2Client.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | #import "NXOAuth2ClientDelegate.h"
17 | #import "NXOAuth2ConnectionDelegate.h"
18 |
19 | extern NSString * const NXOAuth2ClientConnectionContextTokenRequest;
20 | extern NSString * const NXOAuth2ClientConnectionContextTokenRefresh;
21 |
22 | @class NXOAuth2Connection, NXOAuth2AccessToken;
23 |
24 | /*!
25 | * The OAuth 2.0 client
26 | * Only supports WebServer & Password flow at the moment
27 | *
28 | * - oauth2 draft 10 http://tools.ietf.org/html/draft-ietf-oauth-v2-10
29 | * - not thread save
30 | */
31 |
32 | //TODO: Link to documentation
33 |
34 | @interface NXOAuth2Client : NSObject {
35 | @protected
36 | BOOL authenticating;
37 | BOOL persistent;
38 |
39 | NSString *clientId;
40 | NSString *clientSecret;
41 |
42 | NSSet *desiredScope;
43 | NSString *userAgent;
44 | NSString *assertion;
45 | NSString *keyChainGroup;
46 |
47 | // server information
48 | NSURL *authorizeURL;
49 | NSURL *tokenURL;
50 | NSString *tokenType;
51 |
52 | // token exchange
53 | NXOAuth2Connection *authConnection;
54 | NXOAuth2AccessToken *accessToken;
55 | NSMutableArray *waitingConnections; //for connections that are waiting for successful authorisation
56 | NSInteger refreshConnectionDidRetryCount;
57 |
58 | // delegates
59 | NSObject* __unsafe_unretained delegate; // assigned
60 | }
61 |
62 | @property (nonatomic, readonly, getter = isAuthenticating) BOOL authenticating;
63 |
64 | @property (nonatomic, copy, readonly) NSString *clientId;
65 | @property (nonatomic, copy, readonly) NSString *clientSecret;
66 | @property (nonatomic, copy, readonly) NSString *tokenType;
67 | @property (nonatomic, strong, readwrite) NSDictionary *additionalAuthenticationParameters;
68 |
69 | @property (nonatomic, copy) NSSet *desiredScope;
70 | @property (nonatomic, copy) NSString *tokenRequestHTTPMethod; // defaults to POST
71 | @property (nonatomic, copy) NSString *userAgent;
72 | @property (nonatomic, copy) NSString *acceptType; // defaults to application/json
73 |
74 | @property (nonatomic, strong) NXOAuth2AccessToken *accessToken;
75 | @property (nonatomic, unsafe_unretained) NSObject* delegate;
76 |
77 |
78 | /*!
79 | * If set to NO, the access token is not stored any keychain, will be removed if it was.
80 | * Defaults to YES
81 | */
82 | @property (nonatomic, assign, readwrite, getter=isPersistent) BOOL persistent;
83 |
84 | /*!
85 | * Initializes the Client
86 | */
87 | - (id)initWithClientID:(NSString *)clientId
88 | clientSecret:(NSString *)clientSecret
89 | authorizeURL:(NSURL *)authorizeURL
90 | tokenURL:(NSURL *)tokenURL
91 | delegate:(NSObject *)delegate;
92 |
93 | - (id)initWithClientID:(NSString *)clientId
94 | clientSecret:(NSString *)clientSecret
95 | authorizeURL:(NSURL *)authorizeURL
96 | tokenURL:(NSURL *)tokenURL
97 | accessToken:(NXOAuth2AccessToken *)accessToken
98 | keyChainGroup:(NSString *)keyChainGroup
99 | persistent:(BOOL)shouldPersist
100 | delegate:(NSObject *)delegate;
101 |
102 | - (id)initWithClientID:(NSString *)clientId
103 | clientSecret:(NSString *)clientSecret
104 | authorizeURL:(NSURL *)authorizeURL
105 | tokenURL:(NSURL *)tokenURL
106 | accessToken:(NXOAuth2AccessToken *)accessToken
107 | tokenType:(NSString *)tokenType
108 | keyChainGroup:(NSString *)keyChainGroup
109 | persistent:(BOOL)shouldPersist
110 | delegate:(NSObject *)delegate;
111 |
112 | - (BOOL)openRedirectURL:(NSURL *)URL;
113 |
114 |
115 | #pragma mark Authorisation Methods
116 |
117 | /*---------------------------------*
118 | * Use ONE of the following flows: *
119 | *---------------------------------*/
120 |
121 | /*!
122 | * Authenticate usind a web URL (Web Server Flow)
123 | * returns the URL to be opened to get access grant
124 | */
125 | - (NSURL *)authorizationURLWithRedirectURL:(NSURL *)redirectURL;
126 |
127 | /*!
128 | * Authenticate with username & password (User Credentials Flow)
129 | */
130 | - (void)authenticateWithClientCredentials;
131 | - (void)authenticateWithUsername:(NSString *)username password:(NSString *)password;
132 |
133 | /*!
134 | * Authenticate with assertion (Assertion Flow)
135 | */
136 | - (void)authenticateWithAssertionType:(NSURL *)assertionType assertion:(NSString *)assertion;
137 |
138 |
139 | #pragma mark Public
140 |
141 | - (void)requestAccess;
142 |
143 | - (void)refreshAccessToken;
144 | - (void)refreshAccessTokenAndRetryConnection:(NXOAuth2Connection *)retryConnection;
145 |
146 | @end
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2ClientDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2ClientDelegate.h
3 | // OAuth2Client
4 | //
5 | // Created by Gernot Poetsch on 14.09.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import "NXOAuth2Constants.h"
15 | #import "NXOAuth2TrustDelegate.h"
16 |
17 | @class NXOAuth2Client;
18 |
19 | @protocol NXOAuth2ClientDelegate
20 |
21 | @required
22 | /*!
23 | * When this is called on the delegate, you are supposed to invoke the appropriate authentication method in the client.
24 | */
25 | - (void)oauthClientNeedsAuthentication:(NXOAuth2Client *)client;
26 |
27 | @optional
28 | - (void)oauthClientDidGetAccessToken:(NXOAuth2Client *)client;
29 | - (void)oauthClientDidLoseAccessToken:(NXOAuth2Client *)client;
30 | - (void)oauthClientDidRefreshAccessToken:(NXOAuth2Client *)client;
31 | - (void)oauthClient:(NXOAuth2Client *)client didFailToGetAccessTokenWithError:(NSError *)error;
32 |
33 | @end
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2Connection.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2Connection.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | #import "NXOAuth2Constants.h"
17 |
18 | @class NXOAuth2Client;
19 | @protocol NXOAuth2ConnectionDelegate;
20 |
21 |
22 | /*!
23 | * The connection
24 | *
25 | * NXOAuth2Connection is a wrapper around NXURLConnection.
26 | * It's main purpose is to simplify the delegates & to provide a context
27 | * ivar that can be used to put a connection object in a certain context.
28 | * The context may be compared to a tag.
29 | *
30 | * NXOAuth2Connection only provides asynchronous connections as synchronous
31 | * connections are strongly discouraged.
32 | *
33 | * The connection works together with the OAuth2 Client to sign a request
34 | * before sending it. If no client is passed in the connection will sent
35 | * unsigned requests.
36 | */
37 |
38 |
39 | #ifndef NXOAuth2ConnectionDebug
40 | #define NXOAuth2ConnectionDebug 0
41 | #endif
42 |
43 |
44 |
45 | extern NSString * const NXOAuth2ConnectionDidStartNotification;
46 | extern NSString * const NXOAuth2ConnectionDidEndNotification;
47 |
48 |
49 | typedef void(^NXOAuth2ConnectionResponseHandler)(NSURLResponse *response, NSData *responseData, NSError *error);
50 | typedef void(^NXOAuth2ConnectionSendingProgressHandler)(unsigned long long bytesSend, unsigned long long bytesTotal);
51 |
52 |
53 | @interface NXOAuth2Connection : NSObject {
54 | @private
55 | NSURLConnection *connection;
56 | NSMutableURLRequest *request;
57 | NSURLResponse *response;
58 | NSDictionary *requestParameters;
59 |
60 | NSMutableData *data;
61 | BOOL savesData;
62 |
63 | id context;
64 | NSDictionary *userInfo;
65 |
66 | NXOAuth2Client *client;
67 |
68 | NSObject *__unsafe_unretained delegate; // assigned
69 |
70 | NXOAuth2ConnectionResponseHandler responseHandler;
71 | NXOAuth2ConnectionSendingProgressHandler sendingProgressHandler;
72 |
73 | BOOL sendConnectionDidEndNotification;
74 |
75 | #if (NXOAuth2ConnectionDebug)
76 | NSDate *startDate;
77 | #endif
78 | }
79 |
80 | @property (nonatomic, unsafe_unretained) NSObject *delegate;
81 | @property (nonatomic, strong, readonly) NSData *data;
82 | @property (nonatomic, assign) BOOL savesData;
83 | @property (nonatomic, assign, readonly) long long expectedContentLength;
84 | @property (nonatomic, strong, readonly) NSURLResponse *response;
85 | @property (nonatomic, assign, readonly) NSInteger statusCode;
86 | @property (nonatomic, strong) id context;
87 | @property (nonatomic, strong) NSDictionary *userInfo;
88 | @property (nonatomic, strong, readonly) NXOAuth2Client *client;
89 |
90 | - (id) initWithRequest:(NSMutableURLRequest *)request
91 | requestParameters:(NSDictionary *)requestParameters
92 | oauthClient:(NXOAuth2Client *)client
93 | sendingProgressHandler:(NXOAuth2ConnectionSendingProgressHandler)sendingProgressHandler
94 | responseHandler:(NXOAuth2ConnectionResponseHandler)responseHandler;
95 |
96 | - (id)initWithRequest:(NSMutableURLRequest *)request
97 | requestParameters:(NSDictionary *)requestParameters
98 | oauthClient:(NXOAuth2Client *)client
99 | delegate:(NSObject *)delegate;
100 |
101 | - (void)cancel;
102 |
103 | - (void)retry;
104 |
105 | @end
106 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2ConnectionDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2ConnectionDelegate.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import "NXOAuth2Constants.h"
15 | #import "NXOAuth2TrustDelegate.h"
16 |
17 | @class NXOAuth2Connection;
18 |
19 |
20 | @protocol NXOAuth2ConnectionDelegate
21 | @optional
22 |
23 | /*!
24 | * The connection did receive a response.
25 | *
26 | * This method is not called if the response was a 401 with an expired token & a refresh token.
27 | * If so, then the token is refreshed & the connection will be automagically retried.
28 | */
29 | - (void)oauthConnection:(NXOAuth2Connection *)connection didReceiveResponse:(NSURLResponse *)response;
30 |
31 | /*!
32 | * The connection did finish and recieved the whole data.
33 | */
34 | - (void)oauthConnection:(NXOAuth2Connection *)connection didFinishWithData:(NSData *)data;
35 |
36 | /*!
37 | * The connection did fail with an error
38 | *
39 | * The domain of the error is NXOAuth2ErrorDomain.
40 | * Check the error code to see if it's been an HTTP error (NXOAuth2HTTPErrorCode). If so you can get the original error from the userInfo with the key NXOAuth2HTTPErrorKey
41 | */
42 | - (void)oauthConnection:(NXOAuth2Connection *)connection didFailWithError:(NSError *)error;
43 |
44 | /*!
45 | * The connection recieved a new chunk of bytes.
46 | *
47 | * Note: use connection.data.length and connection.expectedContentLength to get the overall progress
48 | */
49 | - (void)oauthConnection:(NXOAuth2Connection *)connection didReceiveData:(NSData *)data;
50 |
51 | /*!
52 | * The connection did send new data
53 | */
54 | - (void)oauthConnection:(NXOAuth2Connection *)connection didSendBytes:(unsigned long long)bytesSend ofTotal:(unsigned long long)bytesTotal;
55 |
56 | /*!
57 | * The connection received a redirect response
58 | */
59 | - (void)oauthConnection:(NXOAuth2Connection *)connection didReceiveRedirectToURL:(NSURL *)redirectURL;
60 |
61 |
62 | @end
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2Constants.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2Constants.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 |
17 | #pragma mark OAuth2 Errors
18 |
19 | extern NSString * const NXOAuth2ErrorDomain; // domain
20 |
21 | // Error Codes from http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-3.2.1
22 |
23 | /*
24 | * The request is missing a required parameter, includes an
25 | * unsupported parameter or parameter value, or is otherwise
26 | * malformed.
27 | */
28 | extern NSInteger const NXOAuth2InvalidRequestErrorCode; // -1001
29 |
30 | /*
31 | * The client identifier provided is invalid.
32 | */
33 | extern NSInteger const NXOAuth2InvalidClientErrorCode; // -1002
34 |
35 | /*
36 | * The client is not authorized to use the requested response
37 | * type.
38 | */
39 | extern NSInteger const NXOAuth2UnauthorizedClientErrorCode; // -1003
40 |
41 | /*
42 | * The redirection URI provided does not match a pre-registered
43 | * value.
44 | */
45 | extern NSInteger const NXOAuth2RedirectURIMismatchErrorCode; // -1004
46 |
47 | /*
48 | * The end-user or authorization server denied the request.
49 | */
50 | extern NSInteger const NXOAuth2AccessDeniedErrorCode; // -1005
51 |
52 | /*
53 | * The requested response type is not supported by the
54 | * authorization server.
55 | */
56 | extern NSInteger const NXOAuth2UnsupportedResponseTypeErrorCode;// -1006
57 |
58 | /*
59 | * The requested scope is invalid, unknown, or malformed.
60 | */
61 | extern NSInteger const NXOAuth2InvalidScopeErrorCode; // -1007
62 |
63 |
64 | // Custom Error codes
65 |
66 | /*
67 | * The connection failed because the token expired and could not be refreshed
68 | */
69 | extern NSInteger const NXOAuth2CouldNotRefreshTokenErrorCode; // -2001
70 |
71 |
72 | #pragma mark HTTP Errors
73 |
74 | extern NSString * const NXOAuth2HTTPErrorDomain; // domain
75 |
76 | // The error code represents the http status code
77 |
78 |
79 | #pragma mark TLS Trust Modes
80 |
81 | /*
82 | * Implement the connection:trustModeForHostname: method from the
83 | * NXOAuth2ConnectionDelegate protocol to specify how certificates provided by
84 | * TLS/SSL secured hosts should be trusted.
85 | * If connection:trustModeForHostname: is not implemented the default
86 | * NXOAuth2TrustModeSystem is assumed.
87 | *
88 | * Note that you can return multiple flags. If you to a match on any trust mode
89 | * will be interpreted as trusting the server (basically the are ORed)
90 | *
91 | * If you specify NXOAuth2TrustModeSpecificCertificate you need to also
92 | * implement connection:trustedCertificatesDERDataForHostname: and provide the
93 | * trusted certificate as DER-encoded NSData. NXOAuth2TrustModeSpecificCertificate
94 | * just ensures that any certificate in the chain is equal to the provided one.
95 | *
96 | * See SecCertificateCreateWithData and SecCertificateCopyData from the
97 | * Security Framework for further reference.
98 | */
99 |
100 | typedef enum {
101 | NXOAuth2TrustModeAnyCertificate = 1 << 0,
102 | NXOAuth2TrustModeSystem = 1 << 1,
103 | NXOAuth2TrustModeSpecificCertificate = 1 << 2
104 | } NXOAuth2TrustMode;
105 |
106 |
107 |
108 | extern NSString * const NXOAuth2AccountStoreErrorKey;
109 |
110 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2FileStreamWrapper.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2FileStreamWrapper.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 |
17 | @interface NXOAuth2FileStreamWrapper : NSObject {
18 | NSInputStream *stream;
19 | unsigned long long contentLength;
20 | NSString *fileName;
21 | NSString *contentType;
22 | }
23 | @property (nonatomic, strong, readonly) NSInputStream *stream;
24 | @property (nonatomic, assign, readonly) unsigned long long contentLength;
25 | @property (nonatomic, copy, readonly) NSString *fileName;
26 | @property (nonatomic, copy) NSString *contentType; // optional DEFAULT: "application/octettstream"
27 |
28 | + (id)wrapperWithStream:(NSInputStream *)stream contentLength:(unsigned long long)contentLength DEPRECATED_ATTRIBUTE;
29 | - (id)initWithStream:(NSInputStream *)stream contentLength:(unsigned long long)contentLength DEPRECATED_ATTRIBUTE;
30 |
31 | + (id)wrapperWithStream:(NSInputStream *)stream contentLength:(unsigned long long)contentLength fileName:(NSString *)fileName;
32 | - (id)initWithStream:(NSInputStream *)stream contentLength:(unsigned long long)contentLength fileName:(NSString *)fileName;
33 |
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2PostBodyStream.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2PostBodyStream.h
3 | // OAuth2Client
4 | //
5 | // Created by Ullrich Schäfer on 27.08.10.
6 | //
7 | // Copyright 2010 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 |
15 | #import
16 |
17 |
18 | @interface NXOAuth2PostBodyStream : NSInputStream {
19 | NSString *boundary;
20 |
21 | NSArray *contentStreams;
22 | NSInputStream *currentStream; // assigned (is retained by contentStreams)
23 | NSUInteger streamIndex;
24 |
25 | unsigned long long numBytesTotal;
26 | }
27 |
28 | - (id)initWithParameters:(NSDictionary *)postParameters;
29 |
30 | @property (readonly) NSString *boundary;
31 | @property (readonly) unsigned long long length;
32 |
33 | @end
34 |
35 |
36 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2Request.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2Request.h
3 | // OAuth2Client
4 | //
5 | // Created by Tobias Kräntzer on 13.07.11.
6 | //
7 | // Copyright 2011 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 |
16 | #import "NXOAuth2Connection.h"
17 |
18 | @class NXOAuth2Account;
19 |
20 | @interface NXOAuth2Request : NSObject {
21 | @private
22 | NSDictionary *parameters;
23 | NSURL *resource;
24 | NSString *requestMethod;
25 | NXOAuth2Account *account;
26 | NXOAuth2Connection *connection;
27 | NXOAuth2Request *me;
28 | }
29 |
30 |
31 | #pragma mark Class Methods
32 |
33 | + (void)performMethod:(NSString *)method
34 | onResource:(NSURL *)resource
35 | usingParameters:(NSDictionary *)parameters
36 | withAccount:(NXOAuth2Account *)account
37 | sendProgressHandler:(NXOAuth2ConnectionSendingProgressHandler)progressHandler
38 | responseHandler:(NXOAuth2ConnectionResponseHandler)responseHandler;
39 |
40 |
41 | #pragma mark Lifecycle
42 |
43 | - (id)initWithResource:(NSURL *)url method:(NSString *)method parameters:(NSDictionary *)parameter;
44 |
45 |
46 | #pragma mark Accessors
47 |
48 | @property (nonatomic, strong, readwrite) NXOAuth2Account *account;
49 |
50 | @property (nonatomic, strong, readwrite) NSString *requestMethod;
51 | @property (nonatomic, strong, readwrite) NSURL *resource;
52 | @property (nonatomic, strong, readwrite) NSDictionary *parameters;
53 |
54 |
55 | #pragma mark Signed NSURLRequest
56 |
57 | - (NSURLRequest *)signedURLRequest;
58 |
59 |
60 | #pragma mark Perform Request
61 |
62 | - (void)performRequestWithSendingProgressHandler:(NXOAuth2ConnectionSendingProgressHandler)progressHandler
63 | responseHandler:(NXOAuth2ConnectionResponseHandler)responseHandler;
64 |
65 |
66 | #pragma mark Cancel
67 |
68 | - (void)cancel;
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Headers/NXOAuth2TrustDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // NXOAuth2TrustDelegate.h
3 | // OAuth2Client
4 | //
5 | // Created by Thomas Kollbach on 24.05.11.
6 | //
7 | // Copyright 2011 nxtbgthng. All rights reserved.
8 | //
9 | // Licenced under the new BSD-licence.
10 | // See README.md in this repository for
11 | // the full licence.
12 | //
13 |
14 | #import
15 | #import "NXOAuth2Constants.h"
16 |
17 | @class NXOAuth2Connection;
18 |
19 | /*!
20 | * The delegate of the NXOAuth2Connection or the NXOAuth2Client can both
21 | * optionally implement this protocol to ensure specific trust modes.
22 | *
23 | * If a NXOAuth2Connection is created with a NXOAuth2Client set and both
24 | * delegates conform to the NXOAuth2TrustDelegate protocol, the NXOAuth2Client's
25 | * delegate is used.
26 | */
27 |
28 | @protocol NXOAuth2TrustDelegate
29 |
30 | @optional
31 |
32 | /*!
33 | * Specifies Trust mode for the specific hostname. See NXOAuth2Constants.h for constants
34 | */
35 | -(NXOAuth2TrustMode)connection:(NXOAuth2Connection *)connection trustModeForHostname:(NSString *)hostname;
36 |
37 | /*!
38 | * Array of NSData objects that contains the trusted certificates for the hostname.
39 | */
40 | -(NSArray *)connection:(NXOAuth2Connection *)connection trustedCertificatesForHostname:(NSString *)hostname;
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/OAuth2Client:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/OAuth2Client.framework/Versions/A/OAuth2Client
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 13D65
7 | CFBundleDevelopmentRegion
8 | English
9 | CFBundleExecutable
10 | OAuth2Client
11 | CFBundleIdentifier
12 | com.nxtbgthng.OAuth2Client
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.2.3
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | DTCompiler
24 | com.apple.compilers.llvm.clang.1_0
25 | DTPlatformBuild
26 | 5B1008
27 | DTPlatformVersion
28 | GM
29 | DTSDKBuild
30 | 13C64
31 | DTSDKName
32 | macosx10.9
33 | DTXcode
34 | 0511
35 | DTXcodeBuild
36 | 5B1008
37 |
38 |
39 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/OAuth2Client.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayPauseButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // CustomButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PlayPauseButtonCell : NSButtonCell
12 |
13 | @property (nonatomic) BOOL playing;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayPauseButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // CustomButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "PlayPauseButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 |
13 | @implementation PlayPauseButtonCell
14 |
15 | - (id)initWithCoder:(NSCoder *)aDecoder {
16 | self = [super initWithCoder:aDecoder];
17 | if (self){
18 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(markAsPlaying:) name:@"SharedAudioPlayerIsPlaying" object:nil];
19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(markAsPausing:) name:@"SharedAudioPlayerIsPausing" object:nil];
20 | }
21 | return self;
22 | }
23 |
24 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
25 | [StreamCloudStyles drawPlayPauseButtonWithFrame:frame playing:[SharedAudioPlayer sharedPlayer].audioPlayer.rate];
26 | }
27 |
28 | - (void)markAsPlaying:(NSNotification *)notification {
29 | [self setPlaying:YES];
30 | }
31 |
32 | - (void)markAsPausing:(NSNotification *)notification {
33 | [self setPlaying:NO];
34 | }
35 |
36 | - (void)setPlaying:(BOOL)playing {
37 | _playing = playing;
38 | [self setEnabled:NO];
39 | [self setEnabled:YES];
40 | }
41 |
42 | @end
43 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayPauseOverlayView.h:
--------------------------------------------------------------------------------
1 | //
2 | // PlayPauseOverlayView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PlayPauseOverlayView : NSView
12 |
13 | @property (nonatomic) NSInteger row;
14 | @property (nonatomic) id objectToShow;
15 | @property (nonatomic) BOOL showLargeIcons;
16 | @end
17 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayPauseOverlayView.m:
--------------------------------------------------------------------------------
1 | //
2 | // PlayPauseOverlayView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "PlayPauseOverlayView.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 | #import "SoundCloudPlaylist.h"
13 | #import "SoundCloudTrack.h"
14 |
15 | @implementation PlayPauseOverlayView
16 |
17 | - (id)initWithFrame:(NSRect)frame
18 | {
19 | self = [super initWithFrame:frame];
20 | if (self) {
21 | // Initialization code here.
22 | }
23 | return self;
24 | }
25 |
26 | - (void)setShowLargeIcons:(BOOL)showLargeIcons {
27 | _showLargeIcons = showLargeIcons;
28 | [self setNeedsDisplay:YES];
29 | }
30 |
31 | - (void)drawRect:(NSRect)dirtyRect
32 | {
33 | [super drawRect:dirtyRect];
34 | BOOL playing = NO;
35 | if ([[SharedAudioPlayer sharedPlayer] currentItem] == self.objectToShow && [SharedAudioPlayer sharedPlayer].audioPlayer.rate) {
36 | playing = YES;
37 | } else if ([[[SharedAudioPlayer sharedPlayer] streamItemsToShowInTableView]indexOfObject:[[[SharedAudioPlayer sharedPlayer]currentItem] playlistTrackIsFrom]] == self.row && [SharedAudioPlayer sharedPlayer].audioPlayer.rate ) {
38 | playing = YES;
39 | }
40 | if (self.showLargeIcons){
41 | [StreamCloudStyles drawLargePlayPauseOverlayWithFrame:self.frame playing:playing];
42 | } else {
43 | [StreamCloudStyles drawPlayPauseOverlayWithFrame:self.frame playing:playing];
44 | }
45 | }
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayingIndicatorView.h:
--------------------------------------------------------------------------------
1 | //
2 | // PlayingIndicatorView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PlayingIndicatorView : NSView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PlayingIndicatorView.m:
--------------------------------------------------------------------------------
1 | //
2 | // PlayingIndicatorView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "PlayingIndicatorView.h"
10 | #import "StreamCloudStyles.h"
11 | @implementation PlayingIndicatorView
12 |
13 | - (id)initWithCoder:(NSCoder *)aDecoder {
14 | self = [super initWithCoder:aDecoder];
15 | if (self){
16 | }
17 | return self;
18 | }
19 |
20 | - (void)drawRect:(NSRect)dirtyRect {
21 | [StreamCloudStyles drawPlayingIndicatorWithFrame:NSMakeRect(0, 0, self.frame.size.width, self.frame.size.height)];
22 | }
23 |
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PreviousButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // PreviousButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface PreviousButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/PreviousButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // PreviousButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 23.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "PreviousButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @implementation PreviousButtonCell
13 |
14 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
15 | [StreamCloudStyles drawPreviousButtonWithFrame:frame];
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressIndicatorView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressIndicatorView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ProgressIndicatorView : NSView
12 |
13 | @property (nonatomic) float progress;
14 | @end
15 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressIndicatorView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressIndicatorView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ProgressIndicatorView.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 |
13 | @implementation ProgressIndicatorView
14 |
15 | - (id)initWithFrame:(NSRect)frame
16 | {
17 | self = [super initWithFrame:frame];
18 | if (self) {
19 | [self commonInit];
20 | }
21 | return self;
22 | }
23 |
24 | - (id)initWithCoder:(NSCoder *)aDecoder {
25 | self = [super initWithCoder:aDecoder];
26 | if (self){
27 | [self commonInit];
28 | }
29 | return self;
30 | }
31 |
32 | - (void)commonInit {
33 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateProgress) name:@"SharedAudioPlayerUpdatedTimePlayed" object:nil];
34 | }
35 |
36 | - (void)drawRect:(NSRect)dirtyRect
37 | {
38 | [super drawRect:dirtyRect];
39 |
40 | [StreamCloudStyles drawProgressIndicatorViewWithPercentShown:floorf(self.progress)];
41 | }
42 |
43 | - (void)updateProgress {
44 | float timeGone = CMTimeGetSeconds([SharedAudioPlayer sharedPlayer].audioPlayer.currentTime);
45 | float durationOfItem = CMTimeGetSeconds([SharedAudioPlayer sharedPlayer].audioPlayer.currentItem.duration);
46 | //float timeToGo = durationOfItem - timeGone;
47 | float progress = (timeGone/durationOfItem)*100;
48 | if (!isnan(progress)){
49 | self.progress = progress;
50 | [self setNeedsDisplay:YES];
51 | }
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressSliderCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressSliderCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ProgressSliderCell : NSSliderCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressSliderCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressSliderCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ProgressSliderCell.h"
10 | #import "ProgressSliderView.h"
11 | #import "StreamCloudStyles.h"
12 | @implementation ProgressSliderCell
13 |
14 | - (void)drawKnob:(NSRect)knobRect {
15 | [StreamCloudStyles drawProgressSliderKnobWithFrame:knobRect];
16 | }
17 |
18 | - (void)drawBarInside:(NSRect)aRect flipped:(BOOL)flipped {
19 | [StreamCloudStyles drawProgressSliderTrackWithFrame:aRect];
20 |
21 | }
22 |
23 | - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView {
24 | [super drawInteriorWithFrame:cellFrame inView:controlView];
25 | NSRect trackRect = NSMakeRect(3, 6, controlView.frame.size.width-6,7);
26 | [StreamCloudStyles drawProgressSliderTrackWithFrame:trackRect];
27 | if (self.doubleValue > 0) {
28 | NSRect leftRect = NSMakeRect(3.5, -0.5, ((controlView.frame.size.width-7)*(self.doubleValue/100)), 20);
29 | [StreamCloudStyles drawProgressSliderProgressWithFrame:NSIntegralRect(leftRect)];
30 | } else {
31 | NSRect leftRect = NSMakeRect(3.5, -0.5, 2, 20);
32 | [StreamCloudStyles drawProgressSliderProgressWithFrame:NSIntegralRect(leftRect)];
33 | }
34 | [self drawKnob];
35 | }
36 |
37 | - (void)stopTracking:(NSPoint)lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag {
38 | [super stopTracking:lastPoint at:stopPoint inView:controlView mouseIsUp:flag];
39 | ProgressSliderView *parentView = (ProgressSliderView *)controlView;
40 | [parentView setClicked:NO];
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressSliderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressSliderView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ProgressSliderView : NSSlider
12 |
13 | @property (nonatomic) BOOL clicked;
14 | @end
15 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ProgressSliderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ProgressSliderView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 26.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ProgressSliderView.h"
10 |
11 | @implementation ProgressSliderView
12 |
13 | - (id)initWithFrame:(NSRect)frame
14 | {
15 | self = [super initWithFrame:frame];
16 | if (self) {
17 | self.clicked = NO;
18 | }
19 | return self;
20 | }
21 |
22 | - (void)drawRect:(NSRect)dirtyRect
23 | {
24 | [super drawRect:dirtyRect];
25 |
26 | // Drawing code here.
27 | }
28 |
29 | - (void)mouseDown:(NSEvent *)theEvent {
30 | self.clicked = YES;
31 | [super mouseDown:theEvent];
32 | }
33 |
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/RepeatButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // RepeatButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface RepeatButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/RepeatButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // RepeatButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "RepeatButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 |
13 | @implementation RepeatButtonCell
14 |
15 | - (id)initWithCoder:(NSCoder *)aDecoder {
16 | self = [super initWithCoder:aDecoder];
17 | if (self){
18 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(repeatModeChanged) name:@"SharedAudioPlayerChangedRepeatMode" object:nil];
19 | }
20 | return self;
21 | }
22 |
23 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
24 | RepeatMode repeatMode = [[SharedAudioPlayer sharedPlayer] repeatMode];
25 | switch (repeatMode) {
26 | case RepeatModeNone:
27 | [StreamCloudStyles drawRepeatButtonWithFrame:frame repeatMode:1];
28 | break;
29 | case RepeatModeAll:
30 | [StreamCloudStyles drawRepeatButtonWithFrame:frame repeatMode:2];
31 | break;
32 | case RepeatModeTrack:
33 | [StreamCloudStyles drawRepeatButtonWithFrame:frame repeatMode:3];
34 | break;
35 | }
36 | }
37 |
38 | - (void)repeatModeChanged {
39 | [self setEnabled:NO];
40 | [self setEnabled:YES];
41 | }
42 |
43 | @end
44 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SeperatorView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SeperatorView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SeperatorView : NSView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SeperatorView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SeperatorView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SeperatorView.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @implementation SeperatorView
13 |
14 | - (void)drawRect:(NSRect)dirtyRect {
15 | [StreamCloudStyles drawSeperatorViewWithFrame:dirtyRect];
16 | }
17 | @end
18 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SettingsViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // SettingsViewController.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 22.05.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MASShortcutView.h"
11 |
12 | @interface SettingsViewController : NSViewController
13 |
14 | @property (nonatomic, strong) IBOutlet NSTextField *lastFMUserNameField;
15 | @property (nonatomic, strong) IBOutlet NSTextField *lastFMPasswordField;
16 | @property (nonatomic, strong) IBOutlet NSButton *useLastFMButton;
17 | @property (nonatomic, strong) IBOutlet NSTextField *lastFMConnectionStateField;
18 | @property (nonatomic, strong) IBOutlet MASShortcutView *playPauseShortcutView;
19 | @property (nonatomic, strong) IBOutlet MASShortcutView *prevShortcutView;
20 | @property (nonatomic, strong) IBOutlet MASShortcutView *nextShortcutView;
21 |
22 | @end
23 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SettingsViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // SettingsViewController.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 22.05.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SettingsViewController.h"
10 | #import "LastFm.h"
11 | #import "MASShortcutView.h"
12 | #import "MASShortcutView+UserDefaults.h"
13 | #import "MASShortcut+UserDefaults.h"
14 | #import "MASShortcut+Monitoring.h"
15 | #import "AppDelegate.h"
16 |
17 |
18 |
19 | @implementation SettingsViewController
20 |
21 | - (instancetype)initWithCoder:(NSCoder *)coder {
22 | self = [super initWithCoder:coder];
23 | if (self){
24 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewWillAppear) name:@"MainWindowOpenSettings" object:nil];
25 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidDisappear) name:@"MainWindowCloseSettings" object:nil];
26 | }
27 | return self;
28 | }
29 |
30 | - (void)viewWillAppear {
31 | [super viewWillAppear];
32 | [self.useLastFMButton setState:[[NSUserDefaults standardUserDefaults] integerForKey:@"useLastFM"]];
33 | if ([[NSUserDefaults standardUserDefaults] stringForKey:@"lastFMUserName"])
34 | [self.lastFMUserNameField setStringValue:[[NSUserDefaults standardUserDefaults] stringForKey:@"lastFMUserName"]];
35 | if ([[NSUserDefaults standardUserDefaults] stringForKey:@"lastFMPassword"])
36 | [self.lastFMPasswordField setStringValue:[[NSUserDefaults standardUserDefaults] stringForKey:@"lastFMPassword"]];
37 | if (self.useLastFMButton.state > 0){
38 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Scrobbling", nil)];
39 | } else {
40 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Not Scrobbling", nil)];
41 | }
42 | if ([[NSUserDefaults standardUserDefaults] stringForKey:@"lastFMSessionKey"]){
43 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Connected", nil)];
44 | } else {
45 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Not connected", nil)];
46 | }
47 |
48 | self.playPauseShortcutView.associatedUserDefaultsKey = @"PlayPauseShortcut";
49 |
50 | self.nextShortcutView.associatedUserDefaultsKey = @"NextShortcut";
51 |
52 | self.prevShortcutView.associatedUserDefaultsKey = @"PreviousShortcut";
53 |
54 | }
55 |
56 | - (void)viewDidDisappear {
57 | [super viewDidDisappear];
58 | [[NSUserDefaults standardUserDefaults] setInteger:self.useLastFMButton.state forKey:@"useLastFM"];
59 | [[NSUserDefaults standardUserDefaults] setObject:self.lastFMUserNameField.stringValue forKey:@"lastFMUserName"];
60 | [[NSUserDefaults standardUserDefaults] setObject:self.lastFMPasswordField.stringValue forKey:@"lastFMPassword"];
61 | [[NSUserDefaults standardUserDefaults] synchronize];
62 | }
63 |
64 | - (IBAction)scrobbleStateSwitchAction:(id)sender {
65 | if (self.useLastFMButton.state == 0) {
66 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Not connected", nil)];
67 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Not Scrobbling", nil)];
68 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"lastFMSessionKey"];
69 | } else {
70 | [[LastFm sharedInstance] getSessionForUser:self.lastFMUserNameField.stringValue password:self.lastFMPasswordField.stringValue successHandler:^(NSDictionary *result) {
71 | NSLog(@"Got LastFM Session");
72 | NSString *lastFMSessionKey = [result objectForKey:@"key"];
73 | if (lastFMSessionKey){
74 | [[NSUserDefaults standardUserDefaults] setObject:lastFMSessionKey forKey:@"lastFMSessionKey"];
75 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Connected", nil)];
76 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Scrobbling", nil)];
77 | } else {
78 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Not connected", nil)];
79 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Not Scrobbling", nil)];
80 | [self showAlertForLastFMFailure];
81 | }
82 | } failureHandler:^(NSError *error) {
83 | NSLog(@"No LastFM Session");
84 | [self.lastFMConnectionStateField setStringValue:NSLocalizedString(@"Not connected", nil)];
85 | [self.useLastFMButton.cell setTitle:NSLocalizedString(@"Not Scrobbling", nil)];
86 | [self showAlertForLastFMFailure];
87 | }];
88 | }
89 | }
90 |
91 | - (IBAction)lastFMUserPasswordFieldAction:(id)sender {
92 |
93 | }
94 |
95 | - (void)showAlertForLastFMFailure {
96 | NSAlert *lastFMAlert = [NSAlert alertWithMessageText:NSLocalizedString(@"Could not get access to Last.FM!", nil) defaultButton:NSLocalizedString(@"Damn!", nil) alternateButton:nil otherButton:nil informativeTextWithFormat:@"Maybe you entered a wrong username or password?"];
97 | [lastFMAlert runModal];
98 | }
99 |
100 | @end
101 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SharedAudioPlayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // SharedAudioPlayer.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 21.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SoundCloudItem.h"
11 | #import "SoundCloudTrack.h"
12 | #import "SoundCloudPlaylist.h"
13 | #import "SoundCloudUser.h"
14 |
15 | typedef enum : NSUInteger {
16 | RepeatModeNone,
17 | RepeatModeAll,
18 | RepeatModeTrack,
19 | } RepeatMode;
20 |
21 | typedef enum : NSUInteger {
22 | CurrentSourceTypeStream,
23 | CurrentSourceTypeFavorites,
24 | } CurrentSourceType;
25 |
26 | @import AVFoundation;
27 |
28 | @interface SharedAudioPlayer : NSObject
29 |
30 | @property (nonatomic, strong) AVQueuePlayer *audioPlayer;
31 | @property (nonatomic, strong) NSMutableArray *itemsToPlay;
32 | @property (nonatomic, strong) NSMutableArray *streamItemsToShowInTableView;
33 | @property (nonatomic, strong) NSMutableArray *favoriteItemsToShowInTableView;
34 | @property (nonatomic, strong) NSMutableArray *shuffledItemsToPlay;
35 | @property (nonatomic) BOOL shuffleEnabled;
36 | @property (nonatomic) NSInteger positionInPlaylist;
37 | @property (nonatomic, strong) NSURL *nextStreamPartURL;
38 | @property (nonatomic, strong) NSURL *nextFavoritesPartURL;
39 | @property (nonatomic) RepeatMode repeatMode;
40 | @property (nonatomic) CurrentSourceType sourceType;
41 | @property (nonatomic ,strong) NSMutableArray *scrobbledItems;
42 |
43 | + (SharedAudioPlayer *)sharedPlayer;
44 | - (void)insertStreamItems:(NSArray *)items;
45 | - (void)insertFavoriteItems:(NSArray *)items;
46 | - (void)togglePlayPause;
47 | - (void)previousItem;
48 | - (void)nextItem;
49 | - (void)jumpToItemAtIndex:(NSInteger)item;
50 | - (void)advanceToTime:(float)timeToGo;
51 | - (SoundCloudTrack *)currentItem;
52 | - (void)getNextSongs;
53 | - (void)toggleRepeatMode;
54 | - (void)reset;
55 | - (void)switchToFavorites;
56 | - (void)switchToStream;
57 | @end
58 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ShuffleButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ShuffleButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ShuffleButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/ShuffleButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ShuffleButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "ShuffleButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 |
13 | @interface ShuffleButtonCell ()
14 |
15 | @property (nonatomic) BOOL shuffeling;
16 |
17 | @end
18 |
19 | @implementation ShuffleButtonCell
20 |
21 | - (id)initWithCoder:(NSCoder *)aDecoder {
22 | self = [super initWithCoder:aDecoder];
23 | if (self){
24 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shuffleStarted) name:@"SharedAudioPlayShuffleStarted" object:nil];
25 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shuffleEnded) name:@"SharedAudioPlayShuffleEnded" object:nil];
26 | }
27 | return self;
28 | }
29 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
30 | [StreamCloudStyles drawShuffleButtonWithFrame:frame active:[SharedAudioPlayer sharedPlayer].shuffleEnabled];
31 | }
32 |
33 | - (void)shuffleStarted {
34 | self.shuffeling = YES;
35 | [self setEnabled:NO];
36 | [self setEnabled:YES];
37 | }
38 |
39 | - (void)shuffleEnded {
40 | self.shuffeling = NO;
41 | [self setEnabled:NO];
42 | [self setEnabled:YES];
43 | }
44 | @end
45 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/SoundCloudAPI:
--------------------------------------------------------------------------------
1 | Versions/Current/SoundCloudAPI
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCAPI.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import "SCConstants.h"
22 | #import "SCSoundCloud.h"
23 | #import "SCAccount.h"
24 | #import "SCRequest.h"
25 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCAccount+Private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import
22 |
23 | #import "SCAccount.h"
24 |
25 | #pragma mark Notifications
26 |
27 | extern NSString * const SCAccountDidChangeUserInfoNotification;
28 |
29 | #pragma mark -
30 |
31 | @interface SCAccount (Private)
32 |
33 | @property (nonatomic, readonly) NXOAuth2Account *oauthAccount;
34 | @property (nonatomic, copy) NSDictionary *userInfo;
35 | - (id)initWithOAuthAccount:(NXOAuth2Account *)account;
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCAccount.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import
22 |
23 | #pragma mark Notifications
24 |
25 | extern NSString * const SCAccountDidFailToGetAccessToken;
26 |
27 | @class NXOAuth2Account;
28 |
29 | @interface SCAccount : NSObject {
30 | @private
31 | NXOAuth2Account *oauthAccount;
32 | }
33 |
34 | #pragma mark Accessors
35 |
36 | @property (nonatomic, readonly) NSString *identifier;
37 |
38 | @end
39 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCConstants.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import
22 |
23 |
24 | #pragma mark OAuth2 Configuration
25 |
26 | extern NSString * const kSCAccountType;
27 |
28 | extern NSString * const kSCConfigurationClientID;
29 | extern NSString * const kSCConfigurationSecret;
30 | extern NSString * const kSCConfigurationRedirectURL;
31 | extern NSString * const kSCConfigurationSandbox;
32 | extern NSString * const kSCConfigurationAPIURL;
33 | extern NSString * const kSCConfigurationAuthorizeURL;
34 |
35 | extern NSString * const kSCSoundCloudAPIURL;
36 | extern NSString * const kSCSoundCloudAccessTokenURL;
37 | extern NSString * const kSCSoundCloudAuthURL;
38 |
39 | extern NSString * const kSCSoundCloudSandboxAPIURL;
40 | extern NSString * const kSCSoundCloudSandboxAccessTokenURL;
41 | extern NSString * const kSCSoundCloudSandboxAuthURL;
42 |
43 | extern NSString * const kTermsOfServiceURL;
44 | extern NSString * const kPrivacyPolicyURL;
45 |
46 | extern float const kSCBorderRadius;
47 |
48 | extern NSUInteger const kSCUsernameTextFieldTag;
49 | extern NSUInteger const kSCPasswordTextFieldTag;
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCRequest.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import
22 |
23 | typedef void(^SCRequestResponseHandler)(NSURLResponse *response, NSData *responseData, NSError *error);
24 | typedef void(^SCRequestSendingProgressHandler)(unsigned long long bytesSend, unsigned long long bytesTotal);
25 |
26 | enum SCRequestMethod {
27 | SCRequestMethodGET = 0,
28 | SCRequestMethodPOST,
29 | SCRequestMethodPUT,
30 | SCRequestMethodDELETE,
31 | SCRequestMethodHEAD
32 | };
33 | typedef enum SCRequestMethod SCRequestMethod;
34 |
35 | @class NXOAuth2Request;
36 | @class SCAccount;
37 |
38 | @interface SCRequest : NSObject {
39 | @private
40 | NXOAuth2Request *oauthRequest;
41 | }
42 |
43 |
44 | #pragma mark Class Methods
45 |
46 | + (id) performMethod:(SCRequestMethod)aMethod
47 | onResource:(NSURL *)resource
48 | usingParameters:(NSDictionary *)parameters
49 | withAccount:(SCAccount *)account
50 | sendingProgressHandler:(SCRequestSendingProgressHandler)progressHandler
51 | responseHandler:(SCRequestResponseHandler)responseHandler;
52 |
53 | + (void)cancelRequest:(id)request;
54 |
55 |
56 | #pragma mark Initializer
57 |
58 | - (id)initWithMethod:(SCRequestMethod)aMethod resource:(NSURL *)aResource;
59 |
60 | #pragma mark Accessors
61 |
62 | @property (nonatomic, readwrite, retain) SCAccount *account;
63 |
64 | @property (nonatomic, assign) SCRequestMethod requestMethod;
65 | @property (nonatomic, readwrite, retain) NSURL *resource;
66 | @property (nonatomic, readwrite, retain) NSDictionary *parameters;
67 |
68 |
69 | #pragma mark Signed NSURLRequest
70 |
71 | - (NSURLRequest *)signedURLRequest;
72 |
73 | #pragma mark Perform Request
74 |
75 | //TODO Consider this
76 | // - Why not to -performRequestWithSendingHandler:responseHandler: ?
77 | // - Why Resource instead of URL ?
78 | // - Need documentation in why there is no –addMultiPartData:withName:type:
79 |
80 | - (void)performRequestWithSendingProgressHandler:(SCRequestSendingProgressHandler)progressHandler
81 | responseHandler:(SCRequestResponseHandler)responseHandler;
82 |
83 | #pragma Cancel Request
84 |
85 | - (void)cancel;
86 |
87 | @end
88 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCSoundCloud+Private.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import "SCSoundCloud.h"
22 |
23 | @interface SCSoundCloud (Private)
24 |
25 | + (SCSoundCloud *)shared;
26 |
27 | #pragma mark Configuration
28 |
29 | + (NSDictionary *)configuration;
30 |
31 | #pragma mark Manage Accounts
32 |
33 | - (void)requestAccessWithUsername:(NSString *)username password:(NSString *)password;
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Headers/SCSoundCloud.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2010, 2011 nxtbgthng for SoundCloud Ltd.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 | * use this file except in compliance with the License. You may obtain a copy of
6 | * the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 | * License for the specific language governing permissions and limitations under
14 | * the License.
15 | *
16 | * For more information and documentation refer to
17 | * http://soundcloud.com/api
18 | *
19 | */
20 |
21 | #import
22 |
23 | #pragma mark Notifications
24 |
25 | extern NSString * const SCSoundCloudAccountDidChangeNotification;
26 | extern NSString * const SCSoundCloudDidFailToRequestAccessNotification;
27 |
28 |
29 | #pragma mark Handler
30 |
31 | typedef void(^SCPreparedAuthorizationURLHandler)(NSURL *preparedURL);
32 |
33 |
34 | #pragma mark -
35 |
36 | @class SCAccount;
37 |
38 | @interface SCSoundCloud : NSObject
39 |
40 | #pragma mark Accessors
41 |
42 | + (SCAccount *)account;
43 |
44 |
45 | #pragma mark Manage Accounts
46 |
47 | + (void)requestAccessWithPreparedAuthorizationURLHandler:(SCPreparedAuthorizationURLHandler)aPreparedAuthorizationURLHandler;
48 | + (void)removeAccess;
49 |
50 |
51 | #pragma mark Configuration
52 |
53 | + (void)setClientID:(NSString *)aClientID
54 | secret:(NSString *)aSecret
55 | redirectURL:(NSURL *)aRedirectURL;
56 |
57 | #pragma mark OAuth2 Flow
58 |
59 | + (BOOL)handleRedirectURL:(NSURL *)URL;
60 |
61 | @end
62 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 13D65
7 | CFBundleDevelopmentRegion
8 | English
9 | CFBundleExecutable
10 | SoundCloudAPI
11 | CFBundleIdentifier
12 | com.yourcompany.SoundCloudAPI
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.0b6
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 2.0b6
23 | DTCompiler
24 | com.apple.compilers.llvm.clang.1_0
25 | DTPlatformBuild
26 | 5B1008
27 | DTPlatformVersion
28 | GM
29 | DTSDKBuild
30 | 13C64
31 | DTSDKName
32 | macosx10.9
33 | DTXcode
34 | 0511
35 | DTXcodeBuild
36 | 5B1008
37 |
38 |
39 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/SoundCloudAPI:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/SoundcloudPlayer/SoundCloudAPI.framework/Versions/A/SoundCloudAPI
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPI.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPIClient.h:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudAPIClient.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SoundCloudAPIClient : NSObject
12 |
13 | + (SoundCloudAPIClient *)sharedClient;
14 | - (void)login;
15 | - (void)logout;
16 | - (BOOL)isLoggedIn;
17 | - (void)getInitialStreamSongs;
18 | - (void)getStreamSongsWithURL:(NSString *)url;
19 | - (void)getInitialFavoriteSongs;
20 | - (void)getFavoriteSongsWithURL:(NSString *)url;
21 | - (void)reloadStream;
22 | @end
23 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudAPIClient.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudAPIClient.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SoundCloudAPIClient.h"
10 | #import
11 | #import "SharedAudioPlayer.h"
12 | #import "SoundCloudItem.h"
13 |
14 | @implementation SoundCloudAPIClient
15 |
16 | - (id)init {
17 | self = [super init];
18 | if (self){
19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadStream) name:SCSoundCloudAccountDidChangeNotification object:nil];
20 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFailToAuthenticate) name:SCSoundCloudDidFailToRequestAccessNotification object:nil];
21 | }
22 | return self;
23 | }
24 |
25 | + (SoundCloudAPIClient *)sharedClient {
26 | static dispatch_once_t once;
27 | static SoundCloudAPIClient* sharedClient;
28 | dispatch_once(&once, ^{
29 | sharedClient = [[self alloc] init];
30 | });
31 | return sharedClient;
32 | }
33 |
34 | - (void)login {
35 | [SCSoundCloud requestAccessWithPreparedAuthorizationURLHandler:^(NSURL *preparedURL){
36 | // Load the URL in a web view or open it in an external browser
37 | [[NSWorkspace sharedWorkspace] openURL:preparedURL];
38 | }];
39 | }
40 |
41 |
42 | - (void)logout {
43 | [[NSURLCache sharedURLCache] removeAllCachedResponses];
44 | [SCSoundCloud removeAccess];
45 | [self didFailToAuthenticate];
46 | }
47 |
48 | - (void)didFailToAuthenticate {
49 | [[NSNotificationCenter defaultCenter] postNotificationName:@"SoundCloudAPIClientDidFailToAuthenticate" object:nil];
50 | [[SharedAudioPlayer sharedPlayer] reset];
51 | }
52 | - (BOOL)isLoggedIn {
53 | SCAccount *account = [SCSoundCloud account];
54 | if (!account.identifier) {
55 | return NO;
56 | } else {
57 | return YES;
58 | }
59 | }
60 |
61 | - (void)reloadStream {
62 | [[NSURLCache sharedURLCache] removeAllCachedResponses];
63 | [[SharedAudioPlayer sharedPlayer] reset];
64 | [self getInitialStreamSongs];
65 | [self getInitialFavoriteSongs];
66 | }
67 |
68 | - (void)getInitialStreamSongs {
69 | SCAccount *account = [SCSoundCloud account];
70 |
71 | [SCRequest performMethod:SCRequestMethodGET
72 | onResource:[NSURL URLWithString:@"https://api-v2.soundcloud.com/stream?limit=25"]
73 | usingParameters:nil
74 | withAccount:account
75 | sendingProgressHandler:nil
76 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
77 | // Handle the response
78 | if (error) {
79 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
80 | } else {
81 | NSLog(@"Got data, yeah");
82 | NSError *error;
83 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
84 | if (!error){
85 | NSArray *itemsFromResponse = [SoundCloudItem soundCloudItemsFromResponse:objectFromData];
86 | [[SharedAudioPlayer sharedPlayer] insertStreamItems:itemsFromResponse];
87 | }
88 | }
89 | }];
90 |
91 | [SCRequest performMethod:SCRequestMethodGET
92 | onResource:[NSURL URLWithString:@"https://api.soundcloud.com/me"]
93 | usingParameters:nil
94 | withAccount:account
95 | sendingProgressHandler:nil
96 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
97 | // Handle the response
98 | if (error) {
99 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
100 | } else {
101 | NSLog(@"Got data, yeah");
102 | NSError *error;
103 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
104 | if (!error){
105 | if ([objectFromData isKindOfClass:[NSDictionary class]]){
106 | NSNumber *userId = [objectFromData objectForKey:@"id"];
107 | [[NSUserDefaults standardUserDefaults] setObject:userId forKey:@"scUserId"];
108 | [[NSUserDefaults standardUserDefaults] synchronize];
109 | }
110 | }
111 | }
112 | }];
113 |
114 | }
115 |
116 |
117 | - (void)getStreamSongsWithURL:(NSString *)url {
118 | SCAccount *account = [SCSoundCloud account];
119 |
120 | [SCRequest performMethod:SCRequestMethodGET
121 | onResource:[NSURL URLWithString:url]
122 | usingParameters:nil
123 | withAccount:account
124 | sendingProgressHandler:nil
125 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
126 | // Handle the response
127 | if (error) {
128 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
129 | } else {
130 | NSLog(@"Got data, yeah");
131 | NSError *error;
132 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
133 | if (!error){
134 | if ([objectFromData isKindOfClass:[NSDictionary class]]) {
135 | NSArray *itemsToInsert = [SoundCloudItem soundCloudItemsFromResponse:objectFromData];
136 | [[SharedAudioPlayer sharedPlayer]insertStreamItems:itemsToInsert];
137 | }
138 | }
139 | }
140 | }];
141 |
142 | }
143 |
144 | - (void)getInitialFavoriteSongs {
145 | SCAccount *account = [SCSoundCloud account];
146 |
147 | [SCRequest performMethod:SCRequestMethodGET
148 | onResource:[NSURL URLWithString:[NSString stringWithFormat:@"https://api-v2.soundcloud.com/users/%@/track_likes?limit=12&offset=0&linked_partitioning=1",[[NSUserDefaults standardUserDefaults] objectForKey:@"scUserId"]]]
149 | usingParameters:nil
150 | withAccount:account
151 | sendingProgressHandler:nil
152 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
153 | // Handle the response
154 | if (error) {
155 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
156 | } else {
157 | NSLog(@"Got data, yeah");
158 | NSError *error;
159 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
160 | if (!error){
161 | if ([objectFromData isKindOfClass:[NSDictionary class]]) {
162 | NSArray *itemsToInsert = [SoundCloudItem soundCloudItemsFromResponse:objectFromData];
163 | [[SharedAudioPlayer sharedPlayer]insertFavoriteItems:itemsToInsert];
164 |
165 | }
166 | }
167 | }
168 | }];
169 |
170 | }
171 |
172 | - (void)getFavoriteSongsWithURL:(NSString *)url {
173 | SCAccount *account = [SCSoundCloud account];
174 |
175 | [SCRequest performMethod:SCRequestMethodGET
176 | onResource:[NSURL URLWithString:url]
177 | usingParameters:nil
178 | withAccount:account
179 | sendingProgressHandler:nil
180 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
181 | // Handle the response
182 | if (error) {
183 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
184 | } else {
185 | NSLog(@"Got data, yeah");
186 | NSError *error;
187 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
188 | if (!error){
189 | if ([objectFromData isKindOfClass:[NSDictionary class]]) {
190 | NSArray *itemsToInsert = [SoundCloudItem soundCloudItemsFromResponse:objectFromData];
191 | [[SharedAudioPlayer sharedPlayer]insertFavoriteItems:itemsToInsert];
192 | }
193 | }
194 | }
195 | }];
196 | }
197 |
198 | @end
199 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudItem.h:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudItem.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef enum : NSUInteger {
12 | SoundCloudItemTypeUnknown,
13 | SoundCloudItemTypeTrack,
14 | SoundCloudItemTypePlaylist,
15 | SoundCloudItemTypeTrackRepost,
16 | SoundCloudItemTypePlaylistRepost
17 | } SoundCloudItemType;
18 |
19 | @class SoundCloudUser;
20 | @interface SoundCloudItem : NSObject
21 |
22 | @property (nonatomic, strong) NSDate *createdAt;
23 | @property (nonatomic) SoundCloudItemType type;
24 | @property (nonatomic, strong) NSString *uuid;
25 | @property (nonatomic) id item;
26 | @property (nonatomic, strong) SoundCloudUser *user;
27 | @property (nonatomic, strong) NSURL *nextHref;
28 |
29 | + (NSArray *)soundCloudItemsFromResponse:(id)response;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudItem.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudItem.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SoundCloudItem.h"
10 | #import "SoundCloudUser.h"
11 | #import "SoundCloudTrack.h"
12 | #import "SoundCloudPlaylist.h"
13 |
14 | @implementation SoundCloudItem
15 |
16 | - (instancetype)initWithCollectionDict:(NSDictionary *)dict {
17 | self = [super init];
18 | if (self){
19 | self.createdAt = [NSDate date];
20 | self.type = SoundCloudItemTypeUnknown;
21 | NSString *typeString = [dict objectForKey:@"type"];
22 | NSString *kindString = [dict objectForKey:@"kind"];
23 | self.user = [SoundCloudUser userForDict:[dict objectForKey:@"user"]];
24 |
25 | if (kindString && [kindString isEqualToString:@"like"]){
26 | if ([dict objectForKey:@"track"] && [[dict objectForKey:@"track"] isKindOfClass:[NSDictionary class]]){
27 | self.type = SoundCloudItemTypeTrack;
28 | self.item = [SoundCloudTrack trackForDict:[dict objectForKey:@"track"] withPlaylist:nil repostedBy:nil];
29 | } else if ([dict objectForKey:@"playlist"] && [[dict objectForKey:@"playlist"] isKindOfClass:[NSDictionary class]]){
30 | self.type = SoundCloudItemTypePlaylist;
31 | self.item = [SoundCloudPlaylist playlistForDict:[dict objectForKey:@"playlist"] repostedBy:nil];
32 | }
33 | } else {
34 | if ([typeString isEqualToString:@"track"]) {
35 | self.type = SoundCloudItemTypeTrack;
36 | self.item = [SoundCloudTrack trackForDict:[dict objectForKey:@"track"] withPlaylist:nil repostedBy:nil];
37 | } else if ([typeString isEqualToString:@"track-repost"]) {
38 | self.type = SoundCloudItemTypeTrackRepost;
39 | self.item = [SoundCloudTrack trackForDict:[dict objectForKey:@"track"] withPlaylist:nil repostedBy:self.user];
40 | } else if ([typeString isEqualToString:@"playlist"]){
41 | self.type = SoundCloudItemTypePlaylist;
42 | self.item = [SoundCloudPlaylist playlistForDict:[dict objectForKey:@"playlist"] repostedBy:nil];
43 | } else if ([typeString isEqualToString:@"playlist-repost"]) {
44 | self.type = SoundCloudItemTypePlaylistRepost;
45 | self.item = [SoundCloudPlaylist playlistForDict:[dict objectForKey:@"playlist"] repostedBy:self.user];
46 | }
47 | self.uuid = [dict objectForKey:@"uuid"];
48 | }
49 | }
50 | return self;
51 | }
52 |
53 | + (NSArray *)soundCloudItemsFromResponse:(id)response {
54 | if ([response isKindOfClass:[NSDictionary class]]){
55 | NSMutableArray *arrayToReturn = [NSMutableArray array];
56 | NSArray *collectionArray = [response objectForKey:@"collection"];
57 | if (collectionArray && [collectionArray isKindOfClass:[NSArray class]]) {
58 | for (NSDictionary *collectionItem in collectionArray){
59 | SoundCloudItem *itemFromCollectionItem = [[SoundCloudItem alloc]initWithCollectionDict:collectionItem];
60 | if ([[response objectForKey:@"next_href"] isKindOfClass:[NSString class]])
61 | itemFromCollectionItem.nextHref = [NSURL URLWithString:[response objectForKey:@"next_href"]];
62 | [arrayToReturn addObject:itemFromCollectionItem];
63 | }
64 | }
65 | return [NSArray arrayWithArray:arrayToReturn];
66 | } else {
67 | return nil;
68 | }
69 | }
70 | @end
71 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudPlaylist.h:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudPlaylist.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @class SoundCloudUser;
12 | @interface SoundCloudPlaylist : NSObject
13 |
14 | @property (nonatomic, strong) NSURL *artworkUrl;
15 | @property (nonatomic, strong) NSDate *createdAt;
16 | @property (nonatomic, strong) NSString *descriptionText;
17 | @property (nonatomic) NSTimeInterval duration;
18 | @property (nonatomic, strong) NSString *genre;
19 | @property (nonatomic, strong) NSDate *lastModified;
20 | @property (nonatomic, strong) NSString *license;
21 | @property (nonatomic, strong) NSNumber *likesCount;
22 | @property (nonatomic, strong) NSURL *permalinkUrl;
23 | @property (nonatomic, strong) NSNumber *repostsCount;
24 | @property (nonatomic) BOOL streamable;
25 | @property (nonatomic, strong) NSString *tagList;
26 | @property (nonatomic, strong) NSString *title;
27 | @property (nonatomic, strong) NSNumber *trackCount;
28 | @property (nonatomic, strong) NSArray *tracks;
29 | @property (nonatomic, strong) NSNumber *identifier;
30 | @property (nonatomic, strong) SoundCloudUser *user;
31 | @property (nonatomic, strong) SoundCloudUser *repostBy;
32 |
33 | + (SoundCloudPlaylist *)playlistForDict:(NSDictionary *)dict repostedBy:(SoundCloudUser *)repostedBy;
34 | @end
35 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudPlaylist.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudPlaylist.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SoundCloudPlaylist.h"
10 | #import "SoundCloudUser.h"
11 | #import "SoundCloudTrack.h"
12 | #import
13 |
14 | @implementation SoundCloudPlaylist
15 |
16 | - (instancetype)initWithDict:(NSDictionary *)dict {
17 | self = [super init];
18 | if (self){
19 | if ([[dict objectForKey:@"artwork_url"] isKindOfClass:[NSString class]])
20 | self.artworkUrl = [NSURL URLWithString:[dict objectForKey:@"artwork_url"]];
21 | self.createdAt = [NSDate date];
22 | self.descriptionText = [dict objectForKey:@"description"];
23 | self.duration = [[dict objectForKey:@"duration"] doubleValue]/1000;
24 | self.genre = [dict objectForKey:@"genre"];
25 | self.lastModified = [NSDate date];
26 | self.license = [dict objectForKey:@"license"];
27 | self.likesCount = [dict objectForKey:@"likes_count"];
28 | if ([[dict objectForKey:@"permalink_url"] isKindOfClass:[NSString class]])
29 | self.permalinkUrl = [NSURL URLWithString:[dict objectForKey:@"permalink_url"]];
30 | self.repostsCount = [dict objectForKey:@"reposts_count"];
31 | self.streamable = YES;
32 | self.tagList = [dict objectForKey:@"tag_list"];
33 | self.title = [dict objectForKey:@"title"];
34 | self.trackCount = [dict objectForKey:@"track_count"];
35 | self.identifier = [dict objectForKey:@"id"];
36 | self.user = [SoundCloudUser userForDict:[dict objectForKey:@"user"]];
37 | }
38 | return self;
39 | }
40 |
41 | + (SoundCloudPlaylist *)playlistForDict:(NSDictionary *)dict repostedBy:(SoundCloudUser *)repostedBy {
42 | SoundCloudPlaylist *playlistToReturn = [[SoundCloudPlaylist alloc]initWithDict:dict];
43 | [[NSNotificationCenter defaultCenter] postNotificationName:@"SoundCloudPlaylistTracksWillLoad" object:playlistToReturn];
44 | [playlistToReturn loadTracksForPlaylist];
45 | if (repostedBy)
46 | playlistToReturn.repostBy = repostedBy;
47 | return playlistToReturn;
48 | }
49 |
50 | - (void)loadTracksForPlaylist {
51 | SCAccount *account = [SCSoundCloud account];
52 |
53 | [SCRequest performMethod:SCRequestMethodGET
54 | onResource:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.soundcloud.com/playlists/%@",self.identifier]]
55 | usingParameters:nil
56 | withAccount:account
57 | sendingProgressHandler:nil
58 | responseHandler:^(NSURLResponse *response, NSData *data, NSError *error){
59 | // Handle the response
60 | if (error) {
61 | NSLog(@"Ooops, something went wrong: %@", [error localizedDescription]);
62 | } else {
63 | NSLog(@"Got data, yeah");
64 | NSError *error;
65 | id objectFromData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
66 | if (!error){
67 | if ([objectFromData isKindOfClass:[NSDictionary class]]){
68 | if ([objectFromData objectForKey:@"tracks"]){
69 | NSMutableArray *tracksCache = [NSMutableArray array];
70 | for (NSDictionary *track in [objectFromData objectForKey:@"tracks"]) {
71 | [tracksCache addObject:[SoundCloudTrack trackForDict:track withPlaylist:self repostedBy:nil]];
72 | }
73 | self.tracks = [NSArray arrayWithArray:tracksCache];
74 | [[NSNotificationCenter defaultCenter] postNotificationName:@"SoundCloudPlaylistTracksLoaded" object:self];
75 | }
76 | }
77 | } else {
78 | [[NSNotificationCenter defaultCenter] postNotificationName:@"SoundCloudPlaylistFailedToLoadTracks" object:self];
79 | }
80 | }
81 | }];
82 | }
83 | @end
84 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudTrack.h:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudTrack.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @import AVFoundation;
12 | @class SoundCloudPlaylist;
13 | @class SoundCloudUser;
14 |
15 | @interface SoundCloudTrack : NSObject
16 |
17 | @property (nonatomic, readonly) AVPlayerItem *playerItem;
18 | @property (nonatomic, strong) NSURL *artworkUrl;
19 | @property (nonatomic, strong) NSNumber *commentCount;
20 | @property (nonatomic, strong) NSDate *createdAt;
21 | @property (nonatomic, strong) NSString *descriptionText;
22 | @property (nonatomic, strong) NSNumber *downloadCount;
23 | @property (nonatomic, strong) NSURL *downloadUrl;
24 | @property (nonatomic) BOOL downloadable;
25 | @property (nonatomic) NSTimeInterval duration;
26 | @property (nonatomic, strong) NSString *genre;
27 | @property (nonatomic, strong) NSString *labelName;
28 | @property (nonatomic, strong) NSDate *lastModified;
29 | @property (nonatomic, strong) NSString *license;
30 | @property (nonatomic, strong) NSNumber *likesCount;
31 | @property (nonatomic, strong) NSURL *permalinkUrl;
32 | @property (nonatomic, strong) NSNumber *playbackCount;
33 | @property (nonatomic, strong) NSNumber *repostsCount;
34 | @property (nonatomic, strong) NSURL *streamingUrl;
35 | @property (nonatomic) BOOL streamable;
36 | @property (nonatomic, strong) NSString *tagList;
37 | @property (nonatomic, strong) NSString *title;
38 | @property (nonatomic, strong) NSDate *updatedAt;
39 | @property (nonatomic, strong) NSURL *uri;
40 | @property (nonatomic, strong) SoundCloudUser *user;
41 | @property (nonatomic ,strong) NSURL *waveformUrl;
42 | @property (nonatomic, strong) SoundCloudUser *repostedBy;
43 |
44 | @property (nonatomic, strong) SoundCloudPlaylist *playlistTrackIsFrom;
45 |
46 | + (SoundCloudTrack *)trackForDict:(NSDictionary *)dict withPlaylist:(SoundCloudPlaylist *)playlist repostedBy:(SoundCloudUser *)repostedBy;
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudTrack.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudTrack.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SoundCloudTrack.h"
10 | #import "SoundCloudUser.h"
11 | #define CLIENT_ID @"909c2edcdbd7b312b48a04a3f1e6b40c"
12 |
13 | @interface SoundCloudTrack ()
14 |
15 | @property (nonatomic, readwrite) AVPlayerItem *playerItem;
16 |
17 | @end
18 |
19 | @implementation SoundCloudTrack
20 |
21 | - (instancetype)initWithDict:(NSDictionary *)dict {
22 | self = [super init];
23 | if (self){
24 | if ([[dict objectForKey:@"artwork_url"] isKindOfClass:[NSString class]])
25 | self.artworkUrl = [NSURL URLWithString:[dict objectForKey:@"artwork_url"]];
26 | self.commentCount = [dict objectForKey:@"comment_count"];
27 | self.createdAt = [NSDate date];
28 | self.descriptionText = [dict objectForKey:@"description"];
29 | self.downloadCount = [dict objectForKey:@"download_count"];
30 | if ([[dict objectForKey:@"download_url"] isKindOfClass:[NSString class]])
31 | self.downloadUrl = [NSURL URLWithString:[dict objectForKey:@"download_url"]];
32 | self.downloadable = [[dict objectForKey:@"downloadable"] boolValue];
33 | self.duration = [[dict objectForKey:@"duration"] doubleValue]/1000;
34 | self.genre = [dict objectForKey:@"genre"];
35 | self.labelName = [dict objectForKey:@"label_name"];
36 | self.lastModified = [NSDate date];
37 | self.license = [dict objectForKey:@"license"];
38 | self.likesCount = [dict objectForKey:@"likes_count"];
39 | if ([[dict objectForKey:@"permalink_url"] isKindOfClass:[NSString class]])
40 | self.permalinkUrl = [NSURL URLWithString:[dict objectForKey:@"permalink_url"]];
41 | self.playbackCount = [dict objectForKey:@"playback_count"];
42 | self.repostsCount = [dict objectForKey:@"reposts_count"];
43 | if ([[dict objectForKey:@"stream_url"] isKindOfClass:[NSString class]])
44 | self.streamingUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@?client_id=%@&allow_redirects=False",[dict objectForKey:@"stream_url"],CLIENT_ID]];
45 | self.streamable = [[dict objectForKey:@"streamable"] boolValue];
46 | if (self.streamable && !self.streamingUrl) {
47 | self.streamingUrl = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.soundcloud.com/tracks/%@/stream?client_id=%@",[dict objectForKey:@"id"],CLIENT_ID]];
48 | }
49 | self.tagList = [dict objectForKey:@"tag_list"];
50 | if ([dict objectForKey:@"title"])
51 | self.title = [dict objectForKey:@"title"];
52 | else
53 | self.title = @"";
54 | self.updatedAt = [NSDate date];
55 | if ([[dict objectForKey:@"uri"] isKindOfClass:[NSString class]])
56 | self.uri = [NSURL URLWithString:[dict objectForKey:@"uri"]];
57 | self.user = [SoundCloudUser userForDict:[dict objectForKey:@"user"]];
58 | if ([[dict objectForKey:@"waveform_url"] isKindOfClass:[NSString class]])
59 | self.waveformUrl = [NSURL URLWithString:[dict objectForKey:@"waveform_url"]];
60 | if (self.streamable)
61 | self.playerItem = [AVPlayerItem playerItemWithURL:self.streamingUrl];
62 | }
63 | return self;
64 | }
65 |
66 | + (SoundCloudTrack *)trackForDict:(NSDictionary *)dict withPlaylist:(SoundCloudPlaylist *)playlist repostedBy:(SoundCloudUser *)repostedBy {
67 | SoundCloudTrack *trackToReturn = [[SoundCloudTrack alloc]initWithDict:dict];
68 | trackToReturn.playlistTrackIsFrom = playlist;
69 | trackToReturn.repostedBy = repostedBy;
70 | return trackToReturn;
71 | }
72 |
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudUser.h:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudUser.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SoundCloudUser : NSObject
12 |
13 | @property (nonatomic, strong) NSURL *avatarUrl;
14 | @property (nonatomic, strong) NSNumber *identifier;
15 | @property (nonatomic, strong) NSString *kind;
16 | @property (nonatomic, strong) NSDate *lastModified;
17 | @property (nonatomic, strong) NSString *permalink;
18 | @property (nonatomic, strong) NSURL *permalinkUrl;
19 | @property (nonatomic ,strong) NSURL *userUri;
20 | @property (nonatomic, strong) NSString *username;
21 |
22 | + (SoundCloudUser *)userForDict:(NSDictionary *)dict;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundCloudUser.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundCloudUser.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 14.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "SoundCloudUser.h"
10 |
11 | @implementation SoundCloudUser
12 |
13 | - (instancetype)initWithDict:(NSDictionary *)dict {
14 | self = [super init];
15 | if (self){
16 | if ([[dict objectForKey:@"avatar_url"] isKindOfClass:[NSString class]])
17 | self.avatarUrl = [NSURL URLWithString:[dict objectForKey:@"avatar_url"]];
18 | self.identifier = [dict objectForKey:@"id"];
19 | self.kind = [dict objectForKey:@"kind"];
20 | self.lastModified = [NSDate date];
21 | self.permalink = [dict objectForKey:@"permalink"];
22 | if ([[dict objectForKey:@"permalink_url"] isKindOfClass:[NSString class]])
23 | self.permalinkUrl = [NSURL URLWithString:[dict objectForKey:@"permalink_url"]];
24 | if ([[dict objectForKey:@"uri"] isKindOfClass:[NSString class]])
25 | self.userUri = [NSURL URLWithString:[dict objectForKey:@"uri"]];
26 | self.username = [dict objectForKey:@"username"];
27 | }
28 | return self;
29 | }
30 |
31 |
32 | + (SoundCloudUser *)userForDict:(NSDictionary *)dict {
33 | SoundCloudUser *userToReturn = [[SoundCloudUser alloc]initWithDict:dict];
34 | return userToReturn;
35 | }
36 | @end
37 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundcloudPlayer-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | de.call-a-nerd.${PRODUCT_NAME:rfc1034identifier}
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.4.2
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLName
29 | de.call-a-nerd.StreamCloud
30 | CFBundleURLSchemes
31 |
32 | streamcloud
33 |
34 |
35 |
36 | CFBundleVersion
37 | 443
38 | LSApplicationCategoryType
39 | public.app-category.music
40 | LSMinimumSystemVersion
41 | ${MACOSX_DEPLOYMENT_TARGET}
42 | NSHumanReadableCopyright
43 | Copyright © 2014 Call a Nerd. All rights reserved.
44 | NSMainNibFile
45 | MainMenu
46 | NSPrincipalClass
47 | StreamCloudApplication
48 |
49 |
50 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundcloudPlayer-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header
3 | //
4 | // The contents of this file are implicitly included at the beginning of every source file.
5 | //
6 |
7 | #ifdef __OBJC__
8 | #import
9 | #endif
10 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/SoundcloudPlayer.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StatusBarPlayerViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // StatusBarPlayerViewController.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface StatusBarPlayerViewController : NSViewController
12 |
13 | @property (nonatomic ,strong) IBOutlet NSImageView *coverArtImageView;
14 | @property (nonatomic, strong) IBOutlet NSTextField *artistLabel;
15 | @property (nonatomic, strong) IBOutlet NSTextField *trackLabel;
16 | @property (nonatomic, strong) IBOutlet NSImageView *overlayImageView;
17 | - (IBAction)playPauseButtonAction:(id)sender;
18 | - (IBAction)nextButtonAction:(id)sender;
19 | - (IBAction)previousButtonAction:(id)sender;
20 | - (IBAction)shuffleButtonAction:(id)sender;
21 | - (IBAction)repeatButtonAction:(id)sender;
22 | - (void)reloadImage;
23 | @end
24 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StatusBarPlayerViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // StatusBarPlayerViewController.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "StatusBarPlayerViewController.h"
10 | #import "SharedAudioPlayer.h"
11 | #import "AFNetworking.h"
12 | #import "NSImage+RoundedCorners.h"
13 | #import "StreamCloudStyles.h"
14 | #import "SoundCloudTrack.h"
15 | #import "SoundCloudUser.h"
16 |
17 | @implementation StatusBarPlayerViewController
18 |
19 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
20 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
21 | if (self){
22 |
23 | }
24 | return self;
25 | }
26 |
27 | - (void)awakeFromNib {
28 | [self.coverArtImageView setImage:[StreamCloudStyles imageOfSoundCloudLogoWithFrame:NSMakeRect(0, 0, 320, 320)]];
29 | [self.overlayImageView setImage:[StreamCloudStyles imageOfImageOverlayGradientViewWithFrame:NSMakeRect(0, 0, 320, 320)]];
30 |
31 | [self reloadImage];
32 | }
33 |
34 | - (void)reloadImage {
35 | SoundCloudTrack *currentObject = [SharedAudioPlayer sharedPlayer].currentItem;
36 | if (currentObject) {
37 | [self.trackLabel setStringValue:currentObject.title];
38 | BOOL useAvatar = YES;
39 | if (currentObject.artworkUrl){
40 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
41 | manager.responseSerializer = [AFImageResponseSerializer serializer];
42 | useAvatar = NO;
43 | NSString *artworkURL = currentObject.artworkUrl.absoluteString;
44 | artworkURL = [artworkURL stringByReplacingOccurrencesOfString:@"large" withString:@"t500x500"];
45 | [manager GET:artworkURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
46 | [self.coverArtImageView setImage:[responseObject roundCornersImageCornerRadius:4]];
47 |
48 |
49 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
50 | NSLog(@"Failed to get image %@",error);
51 | }];
52 |
53 | }
54 | [self.artistLabel setStringValue:currentObject.user.username];
55 | if (useAvatar && currentObject.user.avatarUrl){
56 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
57 | manager.responseSerializer = [AFImageResponseSerializer serializer];
58 | NSString *avatarURL = currentObject.user.avatarUrl.absoluteString;
59 | avatarURL = [avatarURL stringByReplacingOccurrencesOfString:@"large" withString:@"t500x500"];
60 | [manager GET:avatarURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
61 | [self.coverArtImageView setImage:[responseObject roundCornersImageCornerRadius:4]];
62 |
63 |
64 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
65 | NSLog(@"Failed to get image %@",error);
66 | }];
67 | }
68 | }
69 |
70 | }
71 |
72 | # pragma mark - IBActions
73 |
74 | - (IBAction)playPauseButtonAction:(id)sender {
75 | [[SharedAudioPlayer sharedPlayer] togglePlayPause];
76 | }
77 | - (IBAction)nextButtonAction:(id)sender {
78 | [[SharedAudioPlayer sharedPlayer] nextItem];
79 | }
80 | - (IBAction)previousButtonAction:(id)sender {
81 | [[SharedAudioPlayer sharedPlayer] previousItem];
82 | }
83 | - (IBAction)shuffleButtonAction:(id)sender {
84 | [[SharedAudioPlayer sharedPlayer] setShuffleEnabled:![SharedAudioPlayer sharedPlayer].shuffleEnabled];
85 | }
86 | - (IBAction)repeatButtonAction:(id)sender {
87 | [[SharedAudioPlayer sharedPlayer] toggleRepeatMode];
88 | }
89 |
90 | @end
91 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StatusBarPlayerViewController.xib:
--------------------------------------------------------------------------------
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 |
39 |
51 |
63 |
75 |
87 |
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 |
128 |
129 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StreamCloudApplication.h:
--------------------------------------------------------------------------------
1 | //
2 | // StreamCloudApplication.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 16.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | @interface StreamCloudApplication : NSApplication
13 |
14 |
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StreamCloudApplication.m:
--------------------------------------------------------------------------------
1 | //
2 | // StreamCloudApplication.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 16.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "StreamCloudApplication.h"
10 | #define SPSystemDefinedEventMediaKeys 8
11 | #define NX_KEYTYPE_PLAY 16
12 | #define NX_KEYTYPE_NEXT 17
13 | #define NX_KEYTYPE_PREVIOUS 18
14 | #define NX_KEYTYPE_FAST 19
15 | #define NX_KEYTYPE_REWIND 20
16 |
17 | @implementation StreamCloudApplication
18 |
19 | - (void)sendEvent:(NSEvent *)event
20 | {
21 | #pragma clang diagnostic push
22 | #pragma clang diagnostic ignored "-Wundeclared-selector"
23 | if ([event type] == NSKeyDown)
24 | {
25 |
26 | NSString *str = [event characters];
27 | if([str characterAtIndex:0] == 0x20) // spacebar
28 | {
29 | [super sendAction:@selector(spaceBarPressed:) to:nil from:self];
30 | }
31 | else if ([str characterAtIndex:0] == 0xF703) // right Arrow
32 | {
33 |
34 | [super sendAction:@selector(rightKeyPressed:) to:nil from:self];
35 | } else if ([str characterAtIndex:0] == 0xF702) // left Arrow
36 | {
37 | [super sendAction:@selector(leftKeyPressed:) to:nil from:self];
38 | }
39 | else // added this
40 | [super sendEvent:event]; //
41 |
42 | } else if ([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys) {
43 | int keyCode = (([event data1] & 0xFFFF0000) >> 16);
44 | int keyFlags = ([event data1] & 0x0000FFFF);
45 | BOOL keyIsPressed = (((keyFlags & 0xFF00) >> 8)) == 0xA;
46 | int keyRepeat = (keyFlags & 0x1);
47 | if (keyIsPressed && keyRepeat == 0) {
48 | switch (keyCode) {
49 | case NX_KEYTYPE_PLAY:
50 | [super sendAction:@selector(spaceBarPressed:) to:nil from:self];
51 | break;
52 | case NX_KEYTYPE_NEXT:
53 | case NX_KEYTYPE_FAST:
54 | [super sendAction:@selector(rightKeyPressed:) to:nil from:self];
55 | break;
56 | case NX_KEYTYPE_PREVIOUS:
57 | case NX_KEYTYPE_REWIND:
58 | [super sendAction:@selector(leftKeyPressed:) to:nil from:self];
59 | break;
60 | default:
61 | break;
62 | }
63 | }
64 | }
65 | else // and this
66 | [super sendEvent:event];
67 | # pragma clang diagnostic pop
68 | }
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/StreamCloudStyles.h:
--------------------------------------------------------------------------------
1 | //
2 | // StreamCloudStyles.h
3 | // StreamCloud
4 | //
5 | // Created by Peter Amende on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 | // Generated by PaintCode (www.paintcodeapp.com)
9 | //
10 |
11 | #import
12 | #import
13 |
14 |
15 | @interface StreamCloudStyles : NSObject
16 |
17 | // Colors
18 | + (NSColor*)orangeLight;
19 | + (NSColor*)orangeDark;
20 | + (NSColor*)grayMedium;
21 | + (NSColor*)grayDark;
22 | + (NSColor*)grayMediumLight;
23 | + (NSColor*)grayLight;
24 | + (NSColor*)seperatorColor;
25 | + (NSColor*)artistLabelColor;
26 | + (NSColor*)durationLabelColor;
27 |
28 | // Gradients
29 | + (NSGradient*)orangeGradient;
30 |
31 | // Drawing Methods
32 | + (void)drawPlayPauseButtonWithFrame: (NSRect)frame playing: (BOOL)playing;
33 | + (void)drawNextButtonWithFrame: (NSRect)frame;
34 | + (void)drawPreviousButtonWithFrame: (NSRect)frame;
35 | + (void)drawShuffleButtonWithFrame: (NSRect)frame active: (BOOL)active;
36 | + (void)drawRepeatButtonWithFrame: (NSRect)frame repeatMode: (CGFloat)repeatMode;
37 | + (void)drawVolumeSettingsWithFrame: (NSRect)frame volumeToShow: (CGFloat)volumeToShow;
38 | + (void)drawPlayingIndicatorWithFrame: (NSRect)frame;
39 | + (void)drawPlayPauseOverlayWithFrame: (NSRect)frame playing: (BOOL)playing;
40 | + (void)drawTrackDownloadWithFrame: (NSRect)frame;
41 | + (void)drawTrackRepostWithFrame: (NSRect)frame;
42 | + (void)drawTrackLikeWithFrame: (NSRect)frame;
43 | + (void)drawSeperatorViewWithFrame: (NSRect)frame;
44 | + (void)drawPlayingOverlayWithFrame: (NSRect)frame;
45 | + (void)drawLargePlayPauseOverlayWithFrame: (NSRect)frame playing: (BOOL)playing;
46 | + (void)drawSetListOpenClose;
47 | + (void)drawTrackDetailWithFrame: (NSRect)frame;
48 | + (void)drawTrackIsRepostWithFrame: (NSRect)frame;
49 | + (void)drawPlaylistUpperShadowOverlayWithFrame: (NSRect)frame;
50 | + (void)drawPlaylistLowerShadowOverlayWithFrame: (NSRect)frame;
51 | + (void)drawLoginButtonWithFrame: (NSRect)frame;
52 | + (void)drawSoundCloudLogoWithFrame: (NSRect)frame;
53 | + (void)drawProgressSliderTrackWithFrame: (NSRect)frame;
54 | + (void)drawProgressSliderProgressWithFrame: (NSRect)frame;
55 | + (void)drawProgressIndicatorViewWithPercentShown: (CGFloat)percentShown;
56 | + (void)drawProgressSliderKnobWithFrame: (NSRect)frame;
57 | + (void)drawIconFollowerWithFrame: (NSRect)frame;
58 | + (void)drawIconTracksWithFrame: (NSRect)frame active: (BOOL)active;
59 | + (void)drawTabTracksWithFrame: (NSRect)frame;
60 | + (void)drawTabProfileWithFrame: (NSRect)frame;
61 | + (void)drawIconFavoritesWithFrame: (NSRect)frame active: (BOOL)active;
62 |
63 | // Generated Images
64 | + (NSImage*)imageOfPlayPauseButtonWithFrame: (NSRect)frame playing: (BOOL)playing;
65 | + (NSImage*)imageOfNextButtonWithFrame: (NSRect)frame;
66 | + (NSImage*)imageOfPreviousButtonWithFrame: (NSRect)frame;
67 | + (NSImage*)imageOfShuffleButtonWithFrame: (NSRect)frame active: (BOOL)active;
68 | + (NSImage*)imageOfRepeatButtonWithFrame: (NSRect)frame repeatMode: (CGFloat)repeatMode;
69 | + (NSImage*)imageOfPlayingIndicatorWithFrame: (NSRect)frame;
70 | + (NSImage*)imageOfImageOverlayGradientViewWithFrame: (NSRect)frame;
71 | + (NSImage*)imageOfSoundCloudLogoWithFrame: (NSRect)frame;
72 | + (NSImage*)imageOfMenuBarIconWithActive: (BOOL)active;
73 | + (NSImage*)imageOfIconTracksWithFrame: (NSRect)frame active: (BOOL)active;
74 | + (NSImage*)imageOfIconFavoritesWithFrame: (NSRect)frame active: (BOOL)active;
75 |
76 | @end
77 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/TrackCellForPlaylistItemView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TrackCellForPlaylistItemView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 28.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "TrackCellView.h"
11 | #import "SeperatorView.h"
12 | #import "UpperShadowView.h"
13 | #import "LowerShadowView.h"
14 |
15 | @interface TrackCellForPlaylistItemView : TrackCellView
16 |
17 | @property (nonatomic, strong) IBOutlet SeperatorView *seperatorView;
18 | @property (nonatomic, strong) IBOutlet UpperShadowView *upperShadowView;
19 | @property (nonatomic, strong) IBOutlet LowerShadowView *lowerShadowView;
20 |
21 | @end
22 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/TrackCellForPlaylistItemView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TrackCellForPlaylistItemView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 28.07.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "TrackCellForPlaylistItemView.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @implementation TrackCellForPlaylistItemView
13 |
14 | - (void)awakeFromNib {
15 | [super awakeFromNib];
16 | [self.artworkView setShowLargePlayPauseView:YES];
17 | }
18 |
19 | - (void)drawRect:(NSRect)dirtyRect
20 | {
21 | NSRect bounds = [self bounds];
22 |
23 | if (super.mouseInside){
24 | [[NSColor colorWithWhite:0.92 alpha:1.000]set];
25 | } else {
26 | [[NSColor colorWithWhite:0.97 alpha:1.000]set];
27 | }
28 |
29 | NSRectFill(bounds);
30 |
31 | }
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/TrackCellView.h:
--------------------------------------------------------------------------------
1 | //
2 | // TrackCellView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "MouseOverImageView.h"
11 | #import "ClickableTextField.h"
12 | @interface TrackCellView : NSTableCellView
13 |
14 | @property (nonatomic, strong) IBOutlet ClickableTextField *titleLabel;
15 | @property (nonatomic, strong) IBOutlet MouseOverImageView *artworkView;
16 | @property (nonatomic, strong) IBOutlet ClickableTextField *artistLabel;
17 | @property (nonatomic, strong) IBOutlet NSTextField *durationLabel;
18 | @property (nonatomic ,strong) IBOutlet NSButton *pausePlayButton;
19 | @property (nonatomic, strong) IBOutlet NSView *playingIndicatiorView;
20 | @property (nonatomic, strong) IBOutlet NSView *seperatorView;
21 | @property (nonatomic) NSInteger row;
22 | @property (nonatomic) BOOL mouseInside;
23 |
24 | - (void)markAsPlaying:(BOOL)playing;
25 | @end
26 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/TrackCellView.m:
--------------------------------------------------------------------------------
1 | //
2 | // TrackCellView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 24.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "TrackCellView.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @interface TrackCellView ()
13 |
14 | @property (nonatomic, strong) NSTrackingArea *trackingArea;
15 |
16 | @property (nonatomic) BOOL markedAsPlaying;
17 |
18 | @end
19 |
20 | @implementation TrackCellView
21 |
22 | - (void)awakeFromNib {
23 | [self.artistLabel setTextColor:[StreamCloudStyles artistLabelColor]];
24 | [self markAsPlaying:NO];
25 | [self.durationLabel setTextColor:[StreamCloudStyles durationLabelColor]];
26 | }
27 |
28 | - (id)initWithCoder:(NSCoder *)aDecoder {
29 | self = [super initWithCoder:aDecoder];
30 | if (self){
31 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateTrackingAreas) name:@"SongTableViewDidScroll" object:nil];
32 | }
33 | return self;
34 | }
35 |
36 | - (BOOL)canDrawSubviewsIntoLayer {
37 | return YES;
38 | }
39 |
40 | - (void)dealloc {
41 | [[NSNotificationCenter defaultCenter] removeObserver:self];
42 | }
43 |
44 | - (void)setRow:(NSInteger)row {
45 | _row = row;
46 | [self.artworkView setRow:row];
47 | }
48 |
49 | - (void)setMouseInside:(BOOL)mouseInside {
50 | _mouseInside = mouseInside;
51 | [self setNeedsDisplay:YES];
52 | }
53 |
54 | - (void)markAsPlaying:(BOOL)playing {
55 | if (playing){
56 | [self.playingIndicatiorView setHidden:NO];
57 | [self.playingIndicatiorView setNeedsDisplay:YES];
58 | [self.titleLabel setTextColor:[StreamCloudStyles orangeDark]];
59 | } else {
60 | [self.playingIndicatiorView setHidden:YES];
61 | [self.titleLabel setTextColor:[NSColor blackColor]];
62 |
63 | }
64 | [self.artworkView setPlaying:playing];
65 | [self setMarkedAsPlaying:playing];
66 | }
67 |
68 | - (void)setMarkedAsPlaying:(BOOL)markedAsPlaying {
69 | _markedAsPlaying = markedAsPlaying;
70 | self.mouseInside = _mouseInside;
71 | [self setNeedsDisplay:YES];
72 | }
73 |
74 |
75 | # pragma mark - Drawing
76 |
77 | - (void)drawRect:(NSRect)dirtyRect
78 | {
79 | NSRect bounds = [self bounds];
80 |
81 | if (_mouseInside){
82 | [[NSColor colorWithRed:0.98 green:0.98 blue:0.98 alpha:1] set];
83 | } else {
84 | [[NSColor colorWithRed:1 green:1 blue:1 alpha:1] set];
85 | }
86 |
87 | NSRectFill(bounds);
88 |
89 | }
90 |
91 | # pragma mark - MouseDown
92 |
93 | - (void)mouseDown:(NSEvent *)theEvent {
94 | NSPoint selfPoint = [self convertPoint:theEvent.locationInWindow fromView:nil];
95 | if (CGRectContainsPoint(self.artistLabel.frame, selfPoint)) {
96 | [self.artistLabel mouseDown:theEvent];
97 | }
98 | if (CGRectContainsPoint(self.titleLabel.frame, selfPoint)) {
99 | [self.titleLabel mouseDown:theEvent];
100 | }
101 | }
102 |
103 | # pragma mark - Mouse Over Managment
104 |
105 | - (void) createTrackingArea {
106 | int opts = (NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways);
107 | _trackingArea = [ [NSTrackingArea alloc] initWithRect:[self bounds]
108 | options:opts
109 | owner:self
110 | userInfo:nil];
111 | [self addTrackingArea:_trackingArea];
112 |
113 | NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
114 | mouseLocation = [self convertPoint: mouseLocation fromView: nil];
115 |
116 | if (NSPointInRect(mouseLocation, self.bounds)){
117 | [self mouseEntered:nil];
118 | } else {
119 | [self mouseExited:nil];
120 | }
121 |
122 | }
123 |
124 |
125 | - (void)updateTrackingAreas {
126 | [self removeTrackingArea:_trackingArea];
127 | [self createTrackingArea];
128 | [super updateTrackingAreas];
129 | }
130 |
131 | - (void)mouseEntered:(NSEvent *)theEvent {
132 | [self setMouseInside:YES];
133 | [self setNeedsDisplay:YES];
134 | [self.artworkView cursorEntered];
135 | }
136 |
137 | - (void)mouseExited:(NSEvent *)theEvent {
138 | [self setMouseInside:NO];
139 | [self setNeedsDisplay:YES];
140 | [self.artworkView cursorExited];
141 | }
142 |
143 |
144 | @end
145 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/UpperShadowView.h:
--------------------------------------------------------------------------------
1 | //
2 | // UpperShadowView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UpperShadowView : NSView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/UpperShadowView.m:
--------------------------------------------------------------------------------
1 | //
2 | // UpperShadowView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 19.01.15.
6 | // Copyright (c) 2015 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "UpperShadowView.h"
10 | #import "StreamCloudStyles.h"
11 |
12 | @implementation UpperShadowView
13 |
14 | - (void)drawRect:(NSRect)dirtyRect {
15 | [StreamCloudStyles drawPlaylistUpperShadowOverlayWithFrame:dirtyRect];
16 | }
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/VolumeButtonCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // VolumeButtonCell.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface VolumeButtonCell : NSButtonCell
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/VolumeButtonCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // VolumeButtonCell.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "VolumeButtonCell.h"
10 | #import "StreamCloudStyles.h"
11 | #import "SharedAudioPlayer.h"
12 | @implementation VolumeButtonCell
13 |
14 | - (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
15 | float volumeToUse =[SharedAudioPlayer sharedPlayer].audioPlayer.volume*100;
16 | if ([SharedAudioPlayer sharedPlayer].audioPlayer){
17 | [StreamCloudStyles drawVolumeSettingsWithFrame:frame volumeToShow:volumeToUse];
18 | } else {
19 | [StreamCloudStyles drawVolumeSettingsWithFrame:frame volumeToShow:100];
20 | }
21 | }
22 |
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/WhiteBackgroundView.h:
--------------------------------------------------------------------------------
1 | //
2 | // WhiteBackgroundView.h
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface WhiteBackgroundView : NSView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/WhiteBackgroundView.m:
--------------------------------------------------------------------------------
1 | //
2 | // WhiteBackgroundView.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 25.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import "WhiteBackgroundView.h"
10 |
11 | @implementation WhiteBackgroundView
12 |
13 | - (id)initWithFrame:(NSRect)frame
14 | {
15 | self = [super initWithFrame:frame];
16 | if (self) {
17 | // Initialization code here.
18 | }
19 | return self;
20 | }
21 |
22 | - (void)drawRect:(NSRect)dirtyRect
23 | {
24 | [super drawRect:dirtyRect];
25 |
26 | [[NSColor whiteColor] setFill];
27 | NSRectFill(dirtyRect);
28 | [super drawRect:dirtyRect];
29 | }
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/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 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // SoundcloudPlayer
4 | //
5 | // Created by Philip Brechler on 20.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, const char * argv[])
12 | {
13 | return NSApplicationMain(argc, argv);
14 | }
15 |
--------------------------------------------------------------------------------
/SoundcloudPlayer/singleton.h:
--------------------------------------------------------------------------------
1 | #define MAKE_SINGLETON(class_name, shared_method_name) \
2 | + (id)shared_method_name { \
3 | static dispatch_once_t pred; \
4 | static class_name * z ## class_name ## _ = nil; \
5 | dispatch_once(&pred, ^{ \
6 | z ## class_name ## _ = [[self alloc] init]; \
7 | }); \
8 | return z ## class_name ## _; \
9 | } \
10 | - (id)copy { \
11 | return self; \
12 | }/*
13 | - (id)retain { \
14 | return self; \
15 | } \
16 | - (NSUInteger)retainCount { \
17 | return UINT_MAX; \
18 | } \
19 | - (void)release { \
20 | } \
21 | - (id)autorelease { \
22 | return self; \
23 | }
24 | */
--------------------------------------------------------------------------------
/SoundcloudPlayerTests/SoundcloudPlayerTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | de.call-a-nerd.${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 |
--------------------------------------------------------------------------------
/SoundcloudPlayerTests/SoundcloudPlayerTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // SoundcloudPlayerTests.m
3 | // SoundcloudPlayerTests
4 | //
5 | // Created by Philip Brechler on 20.06.14.
6 | // Copyright (c) 2014 Call a Nerd. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface SoundcloudPlayerTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation SoundcloudPlayerTests
16 |
17 | - (void)setUp
18 | {
19 | [super setUp];
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 | }
22 |
23 | - (void)tearDown
24 | {
25 | // Put teardown code here. This method is called after the invocation of each test method in the class.
26 | [super tearDown];
27 | }
28 |
29 | - (void)testExample
30 | {
31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/SoundcloudPlayerTests/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/StreamCloud copy-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | de.call-a-nerd.$(PRODUCT_NAME:rfc1034identifier)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | ${PRODUCT_NAME}
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.4.2
21 | CFBundleSignature
22 | ????
23 | CFBundleURLTypes
24 |
25 |
26 | CFBundleTypeRole
27 | Editor
28 | CFBundleURLName
29 | de.call-a-nerd.StreamCloud
30 | CFBundleURLSchemes
31 |
32 | streamcloudbeta
33 |
34 |
35 |
36 | CFBundleVersion
37 | 450
38 | LSApplicationCategoryType
39 | public.app-category.music
40 | LSMinimumSystemVersion
41 | ${MACOSX_DEPLOYMENT_TARGET}
42 | NSHumanReadableCopyright
43 | Copyright © 2014 Call a Nerd. All rights reserved.
44 | NSMainNibFile
45 | MainMenu
46 | NSPrincipalClass
47 | StreamCloudApplication
48 |
49 |
50 |
--------------------------------------------------------------------------------
/streamcloud-icons.pcvd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/streamcloudapp/StreamCloud/c2c96fb98653790d1159f23f3b8667723f9faad8/streamcloud-icons.pcvd
--------------------------------------------------------------------------------
/streamcloud_beta.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | beta_over
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------