]> cgit.babelmonkeys.de Git - mpdbot.git/blob - PEPThread.m
Reconnect to MPD using BEP on failure
[mpdbot.git] / PEPThread.m
1 #import <ObjFW/ObjFW.h>
2 #import <ObjXMPP/ObjXMPP.h>
3
4 #import "PEPThread.h"
5
6 #define NS_PUBSUB @"http://jabber.org/protocol/pubsub"
7 #define NS_TUNE @"http://jabber.org/protocol/tune"
8
9 @implementation PEPThread: OFThread
10 - (void)dealloc
11 {
12         [sock release];
13
14         [super dealloc];
15 }
16
17 - (void)MPD_connect
18 {
19         int64_t pause = 1;
20         while(1) {
21                 @try {
22                         [sock release];
23                         sock = [[OFTCPSocket alloc] init];
24                         [sock connectToHost: @"localhost"
25                                        port: 6600];
26                         return;
27                 } @catch (id e) {
28                         of_log(@"Connection failed, retrying in %" PRIi64
29                                         " seconds", pause);
30                         [OFThread sleepForTimeInterval: pause];
31                         if (pause < 120)
32                                 pause *= 2;
33                         [e release];
34                 }
35         }
36 }
37
38 - (OFMutableDictionary*)MPD_responseFromSocket: (OFTCPSocket*)sock
39 {
40         OFString *answer;
41         OFMutableDictionary *response = [OFMutableDictionary dictionary];
42         while ((answer = [sock readLine]) && ![answer hasPrefix: @"OK"]) {
43                 size_t index;
44                 index = [answer indexOfFirstOccurrenceOfString: @":"];
45                 if (index == OF_INVALID_INDEX)
46                         continue;
47                 [response setObject: [answer substringFromIndex: index + 2
48                                                         toIndex: answer.length]
49                              forKey: [answer substringFromIndex: 0
50                                                         toIndex: index]];
51         }
52
53         return response;
54 }
55
56 - (id)main
57 {
58         [self MPD_connect];
59         [self MPD_responseFromSocket: sock];
60         while (1) {
61                 OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
62                 @try {
63                         OFMutableDictionary *response;
64                         OFString *answer;
65                         XMPPIQ *tuneIQ;
66                         OFXMLElement *pubsub, *publish, *item, *tune;
67
68                         tuneIQ = [XMPPIQ IQWithType: @"set"
69                                                  ID: [object generateStanzaID]];
70                         pubsub = [OFXMLElement elementWithName: @"pubsub"
71                                                      namespace: NS_PUBSUB];
72                         [tuneIQ addChild: pubsub];
73                         publish = [OFXMLElement elementWithName: @"publish"
74                                                       namespace: NS_PUBSUB];
75                         [publish addAttributeWithName: @"node"
76                                           stringValue: NS_TUNE];
77                         [pubsub addChild: publish];
78                         item = [OFXMLElement elementWithName: @"item"
79                                                    namespace: NS_PUBSUB];
80                         [publish addChild: item];
81                         tune = [OFXMLElement elementWithName: @"tune"
82                                                    namespace: NS_TUNE];
83                         [item addChild: tune];
84                         [sock writeLine: @"status"];
85                         response = [self MPD_responseFromSocket: sock];
86                         if ([[response objectForKey: @"state"]
87                             isEqual: @"play"]) {
88                                 [sock writeLine: @"currentsong"];
89                                 response = [self MPD_responseFromSocket: sock];
90                                 if ((answer =
91                                     [response objectForKey: @"Artist"]))
92                                         [tune addChild: [OFXMLElement
93                                             elementWithName: @"artist"
94                                                   namespace: NS_TUNE
95                                                 stringValue: answer]];
96                                 if ((answer = [response objectForKey: @"Time"]))
97                                         [tune addChild: [OFXMLElement
98                                             elementWithName: @"length"
99                                                   namespace: NS_TUNE
100                                                 stringValue: answer]];
101                                 if ((answer =
102                                     [response objectForKey: @"Album"]))
103                                         [tune addChild: [OFXMLElement
104                                             elementWithName: @"source"
105                                                   namespace: NS_TUNE
106                                                 stringValue: answer]];
107                                 if ((answer =
108                                     [response objectForKey: @"Title"]))
109                                         [tune addChild: [OFXMLElement
110                                             elementWithName: @"title"
111                                                   namespace: NS_TUNE
112                                                 stringValue: answer]];
113                                 if ((answer =
114                                     [response objectForKey: @"Track"]))
115                                         [tune addChild: [OFXMLElement
116                                             elementWithName: @"track"
117                                                   namespace: NS_TUNE
118                                                 stringValue: answer]];
119                         }
120                         [object sendStanza: tuneIQ];
121                         [sock writeLine: @"idle player"];
122                         [self MPD_responseFromSocket: sock];
123                 } @catch (id e) {
124                         [self MPD_connect];
125                         [self MPD_responseFromSocket: sock];
126                         [e release];
127                 }
128                 [pool release];
129         }
130
131         return nil;
132 }
133 @end