PCBとキースイッチを染めている話

adventar.org

この記事は キーボード #2 Advent Calendar 2019 の5日目の記事です。

 

こんばんは。染め太郎もといもぎら (@mogira_jubeat)です。

簡単に自己紹介をしておくと、主にキースイッチやPCBを染色している人です。

天下一キーボードわいわい会 Vol.3では、染色したキースイッチとPCBのカラーサンプル、この2つを組み合わせてGenesis2.5をカラフルにしたGenesis2.5(染)、あとは素 – Shiroをいい感じに染めたものなんかを展示していました。

(写真撮り忘れたのでぜりさんのツイート借りました)

染色に至った経緯と、染色のやり方、今まで得た知見なんかを書いてみようかと思います。

 

染色に至った経緯

ちょうどOutemuスイッチパーツ(10個) | 遊舎工房が販売開始になった頃で、Ice Blueを遊舎工房で見て「すごい綺麗だなー、こんなの使って組んでみたいなー」と思っていました。
そこに店員さんが来て「キースイッチはバネだけじゃなくて、軸やハウジングも交換して楽しめるんですよ~」と、とんでもない沼に引きずり込んでくれました。
おかげさまで、『キースイッチはそのままの組み合わせで使わなきゃ!』という意識が消えてなくなりました。

また、ちょうどこの頃キースイッチ染色やPCB染色にトライした先人がいました。私はそのうちの一人のキーボードで沼にハマったので「へー基板もスイッチも好きな色に染められるんだー」と、染色をかなりハードルの低い行為として捉えていました。

こういった沼人先人たちの洗脳知見の共有によって、「キースイッチもPCBも気に入った色がなければ好きに染めて作ればいいし、好きなように組み合わせて作ればいい」と思えるようになりました。

この後Genesis2.5というキーボードに出会って「この綺麗なキーボードを虹色に染めなくては!」という衝動に駆られ、カラーサンプルの作成など、色々研究がスタートした感じです。

 

染色のやり方

とても 簡単です。

  1. 樹脂用染料SDNという染料を、水と1:20の割合で混ぜる
  2. 温めて70±10℃の温度に保ちつつ、物を投入する
  3. 色ムラにならないように、時々引き上げて色を見ながらぐるぐる混ぜ続ける
  4. 良き色になったら引き上げて、水で流す→中性洗剤で洗う→水で流す→よく乾かす

以上です。ケミカルな臭いが結構すごいので要換気です。廃液の処理も必要ですし、変なところに付着すると厄介です。詳しくはこの辺のページを参考にしてください。

染色をやるに当たって私は器具を一切持っていなかったので、そのときまとめて揃えたものを以下に置いておきます。

※別にビーカーである必要はないですし、アルコールランプを使う必要もないです。趣味です。
※ビーカーはたくさんあると、色を混ぜたりするときにストックできて嬉しいです。
※5mlくらい計れる小型の注射器があると、染料をダバァすることなくきっちり計れて嬉しいです。

私は、キースイッチ数個程度なら染料2.5ml:水50mlくらいで作ってます。

染色が難しいということは特にないと思います。手間がかかるだけです。

 

染色の注意事項

  • やってる最中と成果物のケミカルな臭いがやばいです。
    成果物は扇風機に当てるか、風通しのいい場所に一日くらい放置しておくと多少マシになります。
  • 染色キースイッチは、ピンが抜けやすくなります。
    • ソケットに挿そうとすると、ピンが抜けてしまうことが多いです。
      ソケットに挿す場合はピンセットでピンを押し込む必要があります(地獄)。
      一度ソケットから抜いたらまた押し込み直す必要があります(無間地獄)。
    • 普通にはんだ付けする場合は、限界まで引き出した状態ではんだ付けしましょう。
  • 染色PCBは熱に弱い?っぽいです。
    • フラックスが沸騰するのに巻き込まれたりすると色がハゲます。表面実装の部品周りは要注意です。
    • フラックスクリーナーを使うと色が落ちますが、こっちはフラックス沸騰ほど目に見えて色が落ちるわけではなく、周囲に色が移るから注意してねという程度です。
  • 染色による品質への影響は未知数です。
    一応素 – Shiroの組み立て時に動作確認はしているのですが、品質に影響はないのか?長期的に見てどうか?と言われると、何も分からんというのが正直なところです。


染色について

f:id:mogira_jubeat:20191205011845j:plain

  • 染めた後に異なる色で染めると、先に染めた色が結構落ちます。これを利用することで、良い色が作れることがあります。
    • 薄い色→濃い色とすると、薄い色が落ちつつ濃い色が入ってしまうので、濃い色単色とあまり変化がないです。(例:空→緑)
    • 濃い色→薄い色とすることで、濃い色が少し落ちた状態で薄い色が新たに入るので、いい感じに色が加算できます(例:紫→空or桃)
  • 事前に混ぜた染色液で染めるのと、濃い色→薄い色は同じような色になります。(例:空+緑と緑→空)
  • 同じ色で二度染めても、濃くなったりはしない?(これは試行回数が少ないので不確かな情報です)
    一度橙色で2度染め実験してみたのですが同じ色のままでした。機会があればまたやってみます。
  • シルクは染まりません。
    マット黒シルクで全体に模様を書いた基板だと、マット黒シルクの質感に引きずられて全体がマットな印象になります。冒頭の素の画像がまさにそれなのですが、個人的にとても気に入った染色の仕方です。
  • キースイッチはものによって、染まり方が異なります(素材が違う?)。
    私が確認した限りだと、Outemuのトップ(Clear)とベース?(Ice Blue)はほとんど色が入らない、Blue Zilent v2とR2 KBDfans T1は染まりやすい、Kailh Box(Crystal)は染まるがZilentより色が薄めになる、みたいな傾向が見られました。
  • キースイッチとPCBは当然ですが染まるまでの時間が異なります。
    キースイッチは数十秒~2-3分程度で十分ですが、PCBは数分~十分くらい煮ます。一緒に染める場合は、キースイッチから目を離さない方が良いです。

 

画像とか

以下のモーメントにまとめています!最近更新していないので新しい色とかは載っていないですが、後ほど追加します!

twitter.com

twitter.com

 

終わりに

ちょっと駆け足でしたがいかがだったでしょうか?染色やってみたくなりましたか?

個人的に「そういえば誰かやってたしやってみるか」みたいに心理的なハードルを引き下げるのってすごい重要なことだと思っているので、今回私がその役割を果たせたらいいなと思って天キーやらアドベントカレンダーやら参加してみました。

また、天キーでは色んな人に実物を見てもらえたので、可能性を感じた誰かの背中を押して沼に落としてあげられたらいいなと思います。

ただ、注意事項で書いたように、染色による品質への影響が未知数なので、私個人としては染色したものをboothなどで売ったりする気は今のところないです。そういうことをきちんと説明することができる場(フリマとか)での譲渡や売買、個人的に依頼されるのはありかなとは思っています。というか自分で染めてください。

あとはモーメントの更新だけなのでとりあえず記事は公開します!ダッシュで追加します!

以来スイッチはそのまま使わなくてはいけないみたいな意識がどこかに行ってしまいました。また、何人かキースイッチ染色にトライした人がいたので9672892315197440?s=20https://twitter.com/mogira_jubeat/status/1129672892315197440?s=20https://twitter.com/mogira_jubeat/status/1129672892315197440?s=20

MPMusicPlayerControllerに現在セットされている再生リストを取得する

はじめに
現在再生中の楽曲リストを知りたいことってあると思います。setQueueした後ならqueueAsQueryから取得できますが、新しく取得し直した MPMusicPlayerControllerからはqueueAsQueryでは取得できません。
というわけでこれを取得しようというのが今回のお話です。


発見までのお話
https://developer.apple.com/reference/mediaplayer/mpmusicplayercontroller
こちらがApple公式リファレンスのMPMusicPlayerControllerのページです。
再生中の楽曲の情報を取得するのはnowPlayingItem、とそのインデックスを取得するのはindexOfNowPlayingItemでできますが、再生中のリストを取得するようなメソッドが一切見当たりません。
「本当にないのかなー、何か使えそうなメソッドないかなー」とMPMusicPlayerControllerをdirしていたら「nowPlayingItemAtIndex」というメソッドを見つけました。ネーミングがわかりづらすぎて一回スルーしてしまいました。
Appleの公式リファレンスに載っていないメソッドも見つけることができます。そうPythonistaならね。


というか既にやってた
そんな経緯で発見したのですが、実はstackoverflowに同じようなことやってる人がいました。
http://stackoverflow.com/questions/10092589/ios-get-programatically-queue-of-items-currently-playing
あとからnowPlayingItemAtIndexでググったら見つけました。まぁこれのPythonista版だと思ってください。


本編

def getPlayer(): 
	return ObjCClass('MPMusicPlayerController').systemMusicPlayer() 

def getNowPlayingList(): 
	p = getPlayer() 
	q = [] 
	for i in range(p.numberOfItems()): 
		q.append(p.nowPlayingItemAtIndex(i)) 
	return q 

該当箇所のみです。全ソースコード欲しい人はgitから拾ってください。ハッシュは0e80a13c7b127a3a232e06e7deba985d6f01b474で、MPUtils.pyに入ってます。
今回はnowPlayingItemAtIndexを使ってリストを作るだけなので特に解説要らないと思います。
numberOfItemsで再生リストの曲数がわかるので、for文で回しながらnowPlayingItemAtIndexに渡せば、該当インデックスの曲が貰えます。
地味にnumberOfItemsもリファレンスには載ってません。注意してください。


おわりに
こんな感じで現在の再生リストが取得できます。Apple公式リファレンスに載ってないものでも覗いてみると案外有用なものがあったりするので暇な時に覗いてみるといいかもしれません。iOSのバージョンアップでメソッド追加されてたりとかもあるかもしれません。
というか公式のリファレンスに載ってないってどうなんでしょうね。APIなのに使わせる気がないんですか。誰のためのAPIなんですか。そもそもリストを直接くれればいいのに、インデックス指定してそこの曲だけ欲しい場面ってそんなにあるんですかね。リスト全部くれるなら曲ごとの情報とかこっちで勝手にやりますし余計なことしないでほしいです。大体内部でリストで持ってるであろうものをばらばらにして返してこっちでリストにまとめるって非効率的すぎます。リストで管理していないんだったらもっとアホでしょう。このAPIユースケース考えた人どうかしてるんじゃないですか。
以上です(ニッコリ)。

MPMediaPropertyPredicateでは文字列型プロパティの不一致検索ができない

はじめに
Pythonista for iOSで音楽再生その1 - MPMusicPlayer+MPMediaQuery+MPMediaPropertyPredicate - - 雑魚グラマの妄言

MPMediaPropertyPredicateにはcomparisonTypeプロパティがあるので、完全一致だけじゃなく「〜〜という文字列を含む」という検索もできます*3。equalToは0で、containsは1です*4。一応createFilter関数にも対応させてあります(デフォルトはequalTo)。

ちなみに「〜〜という文字列を含まない」とか「〜〜という文字列と完全一致したものは除外」とかはできません。これに関しては後日恨みと共に解決策を書きます。

と書いたので少しまとめて書いてみようと思います。


事の発端


ミュージックライブラリにアルバムを複数入れてると思いますが、サントラとか一緒くたに再生キューに入れて聞かなくていいアルバムってあると思います。
そういったアルバムをフィルタで除外したかったんですが、結局そんな手法は用意されていませんでした。comparisonTypeもequalToとcontainsの2つしかないですし*1、フィルタを否定の意味で使うようなメソッドもありません。
というわけで、対象のリストからアルバム/曲名で完全一致/部分一致した楽曲のリストを弾くことで実現します。
このときはよく調べてなかったのですが、再生キューにはMPMediaQueryではなくMPMediaItemCollectionを使います。


本編
上で書いた通り、一度対象にするリストを取得した上で、除外する曲リストを新たに取得して、これを対象のリストから弾きます。

# -*- coding: utf-8 -*-

from __future__ import print_function, unicode_literals
from objc_util import NSBundle, ObjCClass

def createFilter(property, value, is_contains=0):
	mpp = ObjCClass('MPMediaPropertyPredicate').alloc()
	mpp.setProperty(property)
	mpp.setValue(value)
	mpp.setComparisonType(is_contains)
	return mpp

def extractMediaQueryItems(tgt):
	return tgt.items().mutableCopy()

if __name__ == '__main__':
	NSBundle.bundleWithPath_('/System/Library/Frameworks/MediaPlayer.framework').load()
	
	player = ObjCClass('MPMusicPlayerController').systemMusicPlayer()
	mq = ObjCClass('MPMediaQuery').albumsQuery()
	
	f0 = createFilter('isCloudItem', False)
	mq.addFilterPredicate(f0)
	all = extractMediaQueryItems(mq)

	f1 = createFilter('albumTitle', 'SOUNDTRACK', 1)
	mq.addFilterPredicate(f1)
	exc = extractMediaQueryItems(mq)

	tgt = all.mutableCopy()
	tgt.removeObjectsInArray(exc)
	
	pl = ObjCClass('MPMediaItemCollection').alloc()
	pl.initWithItems(tgt)

	player.setQueueWithItemCollection(pl)
	player.prepareToPlay()

紹介用なのでデバッグ用のコードは省いてます。では説明していきます。

def extractMediaQueryItems(tgt):
	return tgt.items().mutableCopy()
	f0 = createFilter('isCloudItem', False)
	mq.addFilterPredicate(f0)
	all = extractMediaQueryItems(mq)

この辺はあまり変わりませんが、allにメディアアイテムの可変長リストを抽出しています。
MPMediaQuery.items()が返すのはMPMediaEntityResultSetArrayというクラスで、この中にMPConcreteMediaItem(MPMediaItemの具象クラスっぽい)が詰まっています。
後で出てきますが私が使いたいのはNSMutableArrayクラスのremoveObjectsInArrayメソッドなので、mutableCopyメソッドでNSMutableArrayにコピー&変換してもらいます。というのをやってくれているのがextractMediaQueryItemsです。
NSMutableArrayはNSArrayの可変長版みたいなものらしいです。

	f1 = createFilter('albumTitle', 'SOUNDTRACK', 1)
	mq.addFilterPredicate(f1)
	exc = extractMediaQueryItems(mq)

今回は除外するアルバムとして、ごちうさのサントラを使います。(すまぬ……)
サントラはDisk1, 2とあるので共通する部分を使って部分一致検索でフィルタします。
そして除外リストのexcにさっきと同じようにNSMutableArrayを抽出します。

	tgt = all.mutableCopy()
	tgt.removeObjectsInArray(exc)

allそのまま使うのは気持ち悪いので「対象」リストの意味も込めてtgtにコピーしてます。
あとは対象リストからexcのリストの要素を消し飛ばすだけです。

	pl = ObjCClass('MPMediaItemCollection').alloc()
	pl.initWithItems(tgt)

	player.setQueueWithItemCollection(pl)
	player.prepareToPlay()

tgtはNSMutableArrayで、そのままだと再生キューとして使えないのでMPMediaItemCollectionというクラスに変換します。
SwiftやObjective-Cのネイティブならコンストラクタに渡すんでしょうが、Pythonistaでコンストラクタにどうやって渡すのかわからないので別のイニシャライザを使います。
dirしてみたらちょうど良さげなinitWithItemsというメソッドがあったので、これにメディアアイテムを詰め込んだNSMutableArrayのtgtを渡してあげると無事に再生キューとして使えるいい感じのMPMediaItemCollectionが出来上がります。
あとはもうsetQueueするだけです。前回はWithQueryでしたが、MPMediaQueryとMPMediaItemCollectionは全然別物らしいので、ちゃんとWithItemCollectionを使いましょう。
これで完成です。


おわりに
いかかでしょうか。フィルタを否定の意味で使おうと思うとかなり面倒なことになるのがわかっていただけたと思います。
MPMediaFilterPredicateに否定用のフラグ一つ足しておいてくれるだけで良かったと思いますが、これがAppleAPI実装らしいです(憤怒)。
このクソさは次回も多分愚痴と共に語ることになると思います。では。

MP4Pythonistaとしてgithubにリポジトリ作成

MP4Pythonistaというプロジェクト名でgithubリポジトリ作ってみました。
Pythonista上でもStaShからcloneできますし、httpsですが一応pushもできたのでこれで開発環境は整った感じです……(git初心者)
これから毎日commitしようと思います(大嘘)。
https://github.com/mogira/MP4Pythonista
サイドバーにリンク集も追加したのでそっちにも置いときます。

Pythonista for iOSで音楽再生その1 - MPMusicPlayer+MPMediaQuery+MPMediaPropertyPredicate -

はじめに
手始めに、ミュージックライブラリから取得した全楽曲を再生してみることにします。ただしクラウド上のアイテムだけは省くようにしてみます。
今のところPythonista向けの解説記事みたいなものはまだあまりないと思います。名前が紛らわしいので引っかからないだけかもしれません。
まぁObjective-CPythonでラップしてるだけなので複数言語使える人ならどうにかできると思いますが、自分向けのメモという意味でも残しておこうと思います。


参考ページ一覧
1. Pythonista for iOS で Nowplaying する
そもそもPythonistaでObjective-Cのオブジェクトを扱う方法がわからなかったので、こちらの記事を参考にしました。
サンプルではMPMusicPlayerController.iPodMusicPlayerを使っていますが、2017年2月現在、まだiPodMusicPlayerは使えますが一応deprecatedなのでsystemMusicPlayerを使うようにしましょう*1 *2
2. [iOS][Swift]ミュージックライブラリにアクセスして音楽を再生する(MPMusicPlayerController使用)
プレイヤーごとの違いも丁寧に書いてくださっていて非常にわかりやすいです。
再生や一時停止などの基本操作も載っているので言語はSwiftですが一読してみると良いと思います。
3. [iOS][Swift]MPMediaQueryを使って曲を絞り込む
2と同サイト様の記事です。2ではMPMediaPickerControllerで曲を選択していましたが、とりあえず全曲一括で欲しいのでMPMediaQueryというものを使います。
Queryと書いてありますしプロパティ設定してデータベースに問い合わせて楽曲リストを受け取るみたいなイメージでしょうか。まぁ詳しいことは参考ページを読んで下さい。


nackpan様のサイト http://nackpan.net/blog/ は今回の目的にはかなり合致しているので、度々紹介することになると思います。気になる方は色々読んでみると勉強になるかと思います。


本編
いきなりですが全体のコードです。

# -*- coding: utf-8 -*-

from __future__ import print_function, unicode_literals
from objc_util import NSBundle, ObjCClass
import inspect

def dp(o):
	print(o.__class__.__name__)
	if hasattr(o, '__call__'):
		print(inspect.getargspec(o))
	else:
		print(dir(o))

def printItems(ls, verbose=False):
	for item in ls:
		print(item.title())
		if verbose:
			print('- artist: %s' % item.artist())
			print('- albumTitle: %s' % item.albumTitle())
			print('- persistentID: %d' % item.persistentID())
			print('- isCloudItem: %r' % item.isCloudItem())
	print()

def createFilter(property, value, is_contains=0):
	mpp = ObjCClass('MPMediaPropertyPredicate').alloc()
	mpp.setProperty(property)
	mpp.setValue(value)
	mpp.setComparisonType(is_contains)
	return mpp
	
if __name__ == '__main__':
	NSBundle.bundleWithPath_('/System/Library/Frameworks/MediaPlayer.framework').load()
	MPMusicPlayerController = ObjCClass('MPMusicPlayerController')
	MPMediaQuery = ObjCClass('MPMediaQuery')
	
	player = MPMusicPlayerController.systemMusicPlayer()
	mq = MPMediaQuery.songsQuery()
	
	f0 = createFilter('isCloudItem', False)
	mq.addFilterPredicate(f0)
	
	player.setQueueWithQuery(mq)
	player.prepareToPlay()
	#player.play()
	
	printItems(mq.items())

(はてなダイアリープログラミング言語ハイライトとかそんな機能あったの知らなかった……)
それでは説明していきます。

from __future__ import print_function, unicode_literals

Pythonista3では2系と3系両方使えるのでできれば書いておきましょう。2系でも3系と同様にprintが関数形式で使えるのとプリフィックスなしの文字列がunicode扱いになるとかなんとかだったと思います。詳しくはググってください。

from objc_util import NSBundle, ObjCClass

これが肝です。Objective-Cのクラスを扱えるようにしてくれるobjc_utilを作った方は偉大です。↓
http://omz-software.com/pythonista/docs/ios/objc_util.html

import inspect

def dp(o):
	print(o.__class__.__name__)
	if hasattr(o, '__call__'):
		print(inspect.getargspec(o))
	else:
		print(dir(o))

def printItems(ls, verbose=False):
	for item in ls:
		print(item.title())
		if verbose:
			print('- artist: %s' % item.artist())
			print('- albumTitle: %s' % item.albumTitle())
			print('- persistentID: %d' % item.persistentID())
			print('- isCloudItem: %r' % item.isCloudItem())
	print()

この辺は私が作ったデバッグ用の関数です。
一つ目の参考ページだとvalueForProperty_を使ってプロパティを取得していますが、printItemsでやっているように直接メソッドを呼び出しても取れます。どっちでもいいと思います。
あとメソッド名の後ろにアンダーバーもつけなくても大丈夫っぽいです。
ちなみにdp内で、メソッドだけは引数の数とか見たくてargspec取ってますが意味ないです。メソッド本体もただのプロキシになってるのでselfしか引数取らないように見えますが、実際には渡せば送ってくれるっぽいです。
つまりAppleのリファレンスに載ってないメソッドだったら試行錯誤するしかないです。仮引数名くらいはどうにかすれば見れる気がします(白目)。

def createFilter(property, value, is_contains=0):
	mpp = ObjCClass('MPMediaPropertyPredicate').alloc()
	mpp.setProperty(property)
	mpp.setValue(value)
	mpp.setComparisonType(is_contains)
	return mpp

ここ、中身はフィルタ用のオブジェクトを生成して返すだけですが、PythonistaでのiOSアプリのコーディングに重要な要素が含まれてます。
MPMediaPropertyPredicateクラスがフィルター用のクラスなんですが、ObjCClassで取得できるのは「クラスオブジェクト」なのでallocでインスタンス化する必要があります
取得したクラスオブジェクトをdpで覗いてみればわかりますが、クラスメソッドかスタティックメソッドしか呼び出せないと思います。
私はPythonオブジェクト指向もド素人なので、この程度の説明しかできませんが、とりあえずインスタンス化する必要がある場合はallocを忘れないでください。

if __name__ == '__main__':
	NSBundle.bundleWithPath_('/System/Library/Frameworks/MediaPlayer.framework').load()

入れる場所がここで正しいのかわかりませんが、まぁ呼び出す側の最初に呼べばいいと思います。

	MPMusicPlayerController = ObjCClass('MPMusicPlayerController')
	MPMediaQuery = ObjCClass('MPMediaQuery')
	
	player = MPMusicPlayerController.systemMusicPlayer()
	mq = MPMediaQuery.songsQuery()

クラスオブジェクトをそのクラス名をつけた変数に入れといてあとで使い回す感じです。後でクラスオブジェクトを使う予定がなければ直接呼んでも構いません。今回の分に関しては直接呼んでも構いませんね。
ちなみにsystemMusicPlayerとsongsQueryの取得はインスタンス化する必要がないのでそのまま呼べます。
あとsongsQueryは全曲を曲名でソートして返してくれます。albumsQuery()とかだとアルバム名順にソートしてくれたりします。いくつか試してみると良いです。

	f0 = createFilter('isCloudItem', False)
	mq.addFilterPredicate(f0)
	
	player.setQueueWithQuery(mq)
	player.prepareToPlay()
	#player.play()
	
	printItems(mq.items())

あとは特に変わったところはないですね。
songsQueryが返してくれたクエリーに、生成したisCloudItem=Falseなフィルターをaddしてあげて、playerにセットします。
playじゃなくてprepareToPlayを使うと再生せずにキューのセットだけして待機してくれます。
フィルタに使うプロパティはhttps://developer.apple.com/reference/mediaplayer/mpmediaitemを参照してください。
MPMediaPropertyPredicateにはcomparisonTypeプロパティがあるので、完全一致だけじゃなく「〜〜という文字列を含む」という検索もできます*3。equalToは0で、containsは1です*4。一応createFilter関数にも対応させてあります(デフォルトはequalTo)。
ちなみに「〜〜という文字列を含まない」とか「〜〜という文字列と完全一致したものは除外」とかはできません。これに関しては後日恨みと共に解決策を書きます。


終わり
こんなところです。とりあえずこれでミュージックライブラリから取得した(クラウド上の曲を除く)全曲を曲名ソートした再生キューがセット+再生できます。
systemMusicPlayerを使っているのでBluetoothやイヤホン付属のリモコン、コントロールセンターからも操作できると思います。(リモコンは試してない)
systemMusicPlayerはプリインストールアプリの「ミュージック」を「終了する」という動作(再生キューセット後に開く→終了でも同様)に反応して再生が停止されるので注意です。
PythonistaはMac無しでいいところまでiOSアプリ開発ができそうな予感がしてるので、ユーザーが増えてくれるといいと思います。
実行後にコマンドインターフェイスも使えるのでぜひ色々試してみてください。大丈夫です、iOSならちょっとやそっとじゃ壊れないはずです。
長くなりましたが以上です。

PythonistaでiOS向けの音楽アプリを作りたい

というわけで第1弾です。
まずPythonista*1というのはAppStore上で買えるiOS向けのPythonの開発環境?のことです。
https://itunes.apple.com/us/app/pythonista-3/id1085978097?ls=1&mt=8
色々便利な機能があるのですが、Objective-C向けのクラスをラップするProxyクラスのようなもの?が用意されており、Pythonistaアプリ上からネイティブアプリケーションのコードを書くことができるそうです。*2
作りたいものはiOS上で動く音楽プレイヤーです。理由はいつか長々語ることになると思うのでとりあえず全部省いて機能要件だけ書きます。

  • ミュージックライブラリへのフルアクセス
  • イヤホン等に付いてるリモコンも含めてコントロールセンターからの操作
  • アルバムやアーティストはもちろん、ニコ○コ動画ライクなユーザー定義タグによる検索機能
  • 論理演算子などを用いた高度な検索機能
  • 検索結果を用いたプレイリストの作成・編集機能

検索に関してはニコニコ動画の検索とWiresharkのパケットフィルタリングをかけ合わせたくらいの自由度を想定していますが、検索結果を更に検索に使うスクリプト言語のような使い方ができたらいいなとも思っています。この辺はまだ具体的には決めていません。ただの妄言です。
とりあえずしばらくはこんな感じのものを作りたいなということで進めていきます。

作り直しました

jubeat系の開発のお話をしようかと思って立ち上げたんですが、色々ありまして頓挫しましたので新しいテーマでやっていこうと思います。
主題はプログラムやハードのお話になるかと思いますが、どちらも私自身そこまで詳しくないです。ツッコミや言いたいことがあれば匿名でバンバン送ってくれて構いません。構いませんが返事や記事の修正はあまり期待しないでください。