├── .gitignore ├── .project ├── README.org ├── cassiel.zeroconf ├── externals │ └── .empty ├── help │ ├── zeroconf.browser.maxhelp │ ├── zeroconf.maxhelp │ ├── zeroconf.resolve.maxhelp │ └── zeroconf.service.maxhelp └── patchers │ └── zeroconf_example.maxpat ├── deploy_os-x.sh ├── source ├── Info.plist └── zeroconf │ ├── common │ ├── CriticalSection.cpp │ ├── CriticalSection.h │ ├── NetService.cpp │ ├── NetService.h │ ├── NetServiceBrowser.cpp │ ├── NetServiceBrowser.h │ ├── NetServiceThread.cpp │ ├── NetServiceThread.h │ ├── Thread.cpp │ ├── Thread.h │ └── VERSION.h │ ├── zeroconf_browser │ ├── zeroconf.browser.cpp │ ├── zeroconf.browser.def │ ├── zeroconf.browser.sln │ ├── zeroconf.browser.vcproj │ └── zeroconf.browser.xcodeproj │ │ └── project.pbxproj │ ├── zeroconf_resolve │ ├── zeroconf.resolve.cpp │ ├── zeroconf.resolve.def │ ├── zeroconf.resolve.sln │ ├── zeroconf.resolve.vcproj │ └── zeroconf.resolve.xcodeproj │ │ └── project.pbxproj │ └── zeroconf_service │ ├── zeroconf.service.cpp │ ├── zeroconf.service.def │ ├── zeroconf.service.sln │ ├── zeroconf.service.vcproj │ └── zeroconf.service.xcodeproj │ └── project.pbxproj └── zipped-externals ├── osx └── zeroconf_20110520_osx_universal.zip └── win32 ├── vcredist_x86.exe └── zeroconf_20110226_win32.zip /.gitignore: -------------------------------------------------------------------------------- 1 | maxmspsdk.xcconfig 2 | c74support 3 | externals 4 | sdk-build 5 | build 6 | ext_win_* 7 | *.ncb 8 | *.suo 9 | cassiel.zeroconf/externals/*.mxe 10 | cassiel.zeroconf/externals/*.mxo 11 | project.xcworkspace 12 | xcuserdata 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | zeroconf 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | =-*- mode: org; mode: visual-line; -*-= 2 | #+STARTUP: indent 3 | 4 | * =zeroconf= 5 | 6 | This is a release of Rémy Muller's zeroconf objects for MaxMSP. The sources are here, including projects for OS X (Xcode 3.2) and Windows (Visual Studio Express 2008). 7 | 8 | Both builds are now current. The Xcode build creates Max externals as universal binaries, compatible with OS X 10.4 (Tiger) onwards. 9 | 10 | ** Usage 11 | 12 | - The directory =cassiel.zeroconf= is laid out as a Max 7 package and contains everything *except* the native binaries, since those (at least on OS X) are bundles, and are rather untidy to check into Git directly. The zipped bundles are in folder =zipped-externals=. Unpack the OS X or Windows file as required, and copy all =.mxe= or =.mxo= files into =cassiel.zeroconf/externals=. 13 | 14 | ** Build 15 | 16 | ** Windows Issues 17 | 18 | - You need to install Apple's Bonjour for Windows (known as Bonjour Print Services). Download link [[http://support.apple.com/kb/dl999][here]]. 19 | 20 | - The Zeroconf objects need a Visual C++ runtime library in order to work. Download link [[http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9b2da534-3e03-4391-8a4d-074b9f2bc1bf&displaylang=en&pf=true][here]]. 21 | 22 | We've also taken the liberty of including the installer package here (since it is, after all, "redistributable"). 23 | 24 | ** OS X Issues 25 | 26 | - I've made some slight mods to maxmspsdk.xcconfig - I plant `sdk-build' at the same level as `zeroconf' (rather than one level up). Also, there's an Info.plist for each project, rather than the common Cycling '74 one (with Cycling '74's copyright notice and other boilerplate). 27 | 28 | - For both builds, put the `c74support' directory from the SDK into the same directory as `zeroconf' - I didn't want to put this into Github since it's big and rather untidy. 29 | 30 | ** Revision History 31 | 32 | - 2015-11-xx :: Revisit to prepare =zeroconf= for Max 7's Package Manager 33 | - 2011-05-20 :: Original maintenance port 34 | 35 | ** Credits 36 | 37 | - Original code by Rémy Muller 38 | - This maintenance port by Nick Rothwell, =nick@cassiel.com= 39 | -------------------------------------------------------------------------------- /cassiel.zeroconf/externals/.empty: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cassiel/zeroconf/be9cd4ab180528e99df1a5593f8a47b0817a7084/cassiel.zeroconf/externals/.empty -------------------------------------------------------------------------------- /cassiel.zeroconf/help/zeroconf.browser.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 917.0, 571.0, 640.0, 506.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 917.0, 571.0, 640.0, 506.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 10.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Verdana", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 5.0, 5.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "boxes" : [ { 19 | "box" : { 20 | "maxclass" : "message", 21 | "text" : "browse _afpovertcp._tcp", 22 | "outlettype" : [ "" ], 23 | "fontsize" : 10.0, 24 | "patching_rect" : [ 51.0, 42.0, 135.0, 17.0 ], 25 | "id" : "obj-8", 26 | "numinlets" : 2, 27 | "fontname" : "Verdana", 28 | "numoutlets" : 1 29 | } 30 | 31 | } 32 | , { 33 | "box" : { 34 | "maxclass" : "message", 35 | "text" : "browse _smb._tcp", 36 | "outlettype" : [ "" ], 37 | "fontsize" : 10.0, 38 | "patching_rect" : [ 82.0, 67.0, 103.0, 17.0 ], 39 | "id" : "obj-7", 40 | "numinlets" : 2, 41 | "fontname" : "Verdana", 42 | "numoutlets" : 1 43 | } 44 | 45 | } 46 | , { 47 | "box" : { 48 | "maxclass" : "newobj", 49 | "text" : "zeroconf.service @name \"Open Sound Control UDP Service\" @port 4321 @type _osc._udp", 50 | "fontsize" : 10.0, 51 | "patching_rect" : [ 130.0, 318.0, 465.0, 19.0 ], 52 | "id" : "obj-5", 53 | "numinlets" : 1, 54 | "fontname" : "Verdana", 55 | "numoutlets" : 0 56 | } 57 | 58 | } 59 | , { 60 | "box" : { 61 | "maxclass" : "newobj", 62 | "text" : "zeroconf.service @name \"Un autre service\" @port 6666 @type _osc._udp", 63 | "fontsize" : 10.0, 64 | "patching_rect" : [ 130.0, 344.0, 380.0, 19.0 ], 65 | "id" : "obj-6", 66 | "numinlets" : 1, 67 | "fontname" : "Verdana", 68 | "numoutlets" : 0 69 | } 70 | 71 | } 72 | , { 73 | "box" : { 74 | "maxclass" : "newobj", 75 | "text" : "zeroconf.service @name \"Open Sound Control UDP Service\" @port 12345 @type _osc._udp", 76 | "fontsize" : 10.0, 77 | "patching_rect" : [ 130.0, 284.0, 471.0, 19.0 ], 78 | "id" : "obj-4", 79 | "numinlets" : 1, 80 | "fontname" : "Verdana", 81 | "numoutlets" : 0 82 | } 83 | 84 | } 85 | , { 86 | "box" : { 87 | "maxclass" : "message", 88 | "text" : "browse _osc._udp", 89 | "outlettype" : [ "" ], 90 | "fontsize" : 10.0, 91 | "patching_rect" : [ 105.0, 99.0, 103.0, 17.0 ], 92 | "id" : "obj-3", 93 | "numinlets" : 2, 94 | "fontname" : "Verdana", 95 | "numoutlets" : 1 96 | } 97 | 98 | } 99 | , { 100 | "box" : { 101 | "maxclass" : "newobj", 102 | "text" : "print browser", 103 | "fontsize" : 10.0, 104 | "patching_rect" : [ 105.0, 178.0, 78.0, 19.0 ], 105 | "id" : "obj-2", 106 | "numinlets" : 1, 107 | "fontname" : "Verdana", 108 | "numoutlets" : 0 109 | } 110 | 111 | } 112 | , { 113 | "box" : { 114 | "maxclass" : "newobj", 115 | "text" : "zeroconf.browser @type _smb._tcp @domain local.", 116 | "outlettype" : [ "" ], 117 | "fontsize" : 10.0, 118 | "patching_rect" : [ 105.0, 125.0, 268.0, 19.0 ], 119 | "id" : "obj-1", 120 | "numinlets" : 1, 121 | "fontname" : "Verdana", 122 | "numoutlets" : 1 123 | } 124 | 125 | } 126 | ], 127 | "lines" : [ { 128 | "patchline" : { 129 | "source" : [ "obj-8", 0 ], 130 | "destination" : [ "obj-1", 0 ], 131 | "hidden" : 0, 132 | "midpoints" : [ ] 133 | } 134 | 135 | } 136 | , { 137 | "patchline" : { 138 | "source" : [ "obj-7", 0 ], 139 | "destination" : [ "obj-1", 0 ], 140 | "hidden" : 0, 141 | "midpoints" : [ ] 142 | } 143 | 144 | } 145 | , { 146 | "patchline" : { 147 | "source" : [ "obj-3", 0 ], 148 | "destination" : [ "obj-1", 0 ], 149 | "hidden" : 0, 150 | "midpoints" : [ ] 151 | } 152 | 153 | } 154 | , { 155 | "patchline" : { 156 | "source" : [ "obj-1", 0 ], 157 | "destination" : [ "obj-2", 0 ], 158 | "hidden" : 0, 159 | "midpoints" : [ ] 160 | } 161 | 162 | } 163 | ] 164 | } 165 | 166 | } 167 | -------------------------------------------------------------------------------- /cassiel.zeroconf/help/zeroconf.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 504.0, 44.0, 640.0, 506.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 504.0, 44.0, 640.0, 506.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 12.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Arial", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 15.0, 15.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "boxes" : [ { 19 | "box" : { 20 | "maxclass" : "newobj", 21 | "text" : "udpsend localhost 9000", 22 | "fontsize" : 10.0, 23 | "patching_rect" : [ 79.0, 292.0, 130.0, 19.0 ], 24 | "id" : "obj-17", 25 | "numinlets" : 1, 26 | "fontname" : "Verdana", 27 | "numoutlets" : 0 28 | } 29 | 30 | } 31 | , { 32 | "box" : { 33 | "maxclass" : "button", 34 | "outlettype" : [ "bang" ], 35 | "patching_rect" : [ 78.0, 222.0, 20.0, 20.0 ], 36 | "id" : "obj-16", 37 | "numinlets" : 1, 38 | "numoutlets" : 1 39 | } 40 | 41 | } 42 | , { 43 | "box" : { 44 | "maxclass" : "newobj", 45 | "text" : "prepend name", 46 | "outlettype" : [ "" ], 47 | "fontsize" : 12.0, 48 | "patching_rect" : [ 119.0, 224.0, 100.0, 20.0 ], 49 | "id" : "obj-14", 50 | "numinlets" : 1, 51 | "fontname" : "Arial", 52 | "numoutlets" : 1 53 | } 54 | 55 | } 56 | , { 57 | "box" : { 58 | "maxclass" : "newobj", 59 | "text" : "print _RESOLVE_", 60 | "fontsize" : 10.0, 61 | "patching_rect" : [ 222.0, 292.0, 97.0, 19.0 ], 62 | "id" : "obj-10", 63 | "numinlets" : 1, 64 | "fontname" : "Verdana", 65 | "numoutlets" : 0 66 | } 67 | 68 | } 69 | , { 70 | "box" : { 71 | "maxclass" : "newobj", 72 | "text" : "zeroconf.resolve @name \"Un autre service\" @type _osc._udp @domain local.", 73 | "outlettype" : [ "" ], 74 | "fontsize" : 10.0, 75 | "patching_rect" : [ 78.0, 255.0, 399.0, 19.0 ], 76 | "id" : "obj-11", 77 | "numinlets" : 1, 78 | "fontname" : "Verdana", 79 | "numoutlets" : 1 80 | } 81 | 82 | } 83 | , { 84 | "box" : { 85 | "maxclass" : "newobj", 86 | "text" : "zeroconf.service @name \"Open Sound Control UDP Service\" @port 4321 @type _osc._udp", 87 | "fontsize" : 10.0, 88 | "patching_rect" : [ 72.0, 400.0, 465.0, 19.0 ], 89 | "id" : "obj-5", 90 | "numinlets" : 1, 91 | "fontname" : "Verdana", 92 | "numoutlets" : 0 93 | } 94 | 95 | } 96 | , { 97 | "box" : { 98 | "maxclass" : "newobj", 99 | "text" : "zeroconf.service @name \"Un autre service\" @port 6666 @type _osc._udp", 100 | "fontsize" : 10.0, 101 | "patching_rect" : [ 72.0, 423.0, 380.0, 19.0 ], 102 | "id" : "obj-6", 103 | "numinlets" : 1, 104 | "fontname" : "Verdana", 105 | "numoutlets" : 0 106 | } 107 | 108 | } 109 | , { 110 | "box" : { 111 | "maxclass" : "newobj", 112 | "text" : "zeroconf.service @name \"Open Sound Control UDP Service\" @port 12345 @type _osc._udp", 113 | "fontsize" : 10.0, 114 | "patching_rect" : [ 72.0, 377.0, 471.0, 19.0 ], 115 | "id" : "obj-4", 116 | "numinlets" : 1, 117 | "fontname" : "Verdana", 118 | "numoutlets" : 0 119 | } 120 | 121 | } 122 | , { 123 | "box" : { 124 | "maxclass" : "button", 125 | "outlettype" : [ "bang" ], 126 | "patching_rect" : [ 191.0, 135.0, 20.0, 20.0 ], 127 | "id" : "obj-9", 128 | "numinlets" : 1, 129 | "numoutlets" : 1 130 | } 131 | 132 | } 133 | , { 134 | "box" : { 135 | "maxclass" : "umenu", 136 | "outlettype" : [ "int", "", "" ], 137 | "items" : [ "Open Sound Control UDP Service", ",", "Open Sound Control UDP Service (2)", ",", "Un autre service" ], 138 | "fontsize" : 12.0, 139 | "patching_rect" : [ 78.0, 190.0, 266.0, 20.0 ], 140 | "id" : "obj-7", 141 | "types" : [ ], 142 | "numinlets" : 1, 143 | "fontname" : "Arial", 144 | "numoutlets" : 3 145 | } 146 | 147 | } 148 | , { 149 | "box" : { 150 | "maxclass" : "newobj", 151 | "text" : "zeroconf.browser @type _smb._tcp @domain local.", 152 | "outlettype" : [ "" ], 153 | "fontsize" : 10.0, 154 | "patching_rect" : [ 78.0, 163.0, 268.0, 19.0 ], 155 | "id" : "obj-3", 156 | "numinlets" : 1, 157 | "fontname" : "Verdana", 158 | "numoutlets" : 1 159 | } 160 | 161 | } 162 | , { 163 | "box" : { 164 | "maxclass" : "newobj", 165 | "text" : "prepend browse", 166 | "outlettype" : [ "" ], 167 | "fontsize" : 12.0, 168 | "patching_rect" : [ 78.0, 134.0, 100.0, 20.0 ], 169 | "id" : "obj-2", 170 | "numinlets" : 1, 171 | "fontname" : "Arial", 172 | "numoutlets" : 1 173 | } 174 | 175 | } 176 | , { 177 | "box" : { 178 | "maxclass" : "umenu", 179 | "outlettype" : [ "int", "", "" ], 180 | "items" : [ "_osc._udp", ",", "_afpovertcp._tcp", ",", "_smb._tcp" ], 181 | "fontsize" : 12.0, 182 | "patching_rect" : [ 78.0, 105.0, 148.0, 20.0 ], 183 | "id" : "obj-1", 184 | "types" : [ ], 185 | "numinlets" : 1, 186 | "fontname" : "Arial", 187 | "numoutlets" : 3 188 | } 189 | 190 | } 191 | ], 192 | "lines" : [ { 193 | "patchline" : { 194 | "source" : [ "obj-9", 0 ], 195 | "destination" : [ "obj-3", 0 ], 196 | "hidden" : 0, 197 | "midpoints" : [ 200.5, 158.5, 87.5, 158.5 ] 198 | } 199 | 200 | } 201 | , { 202 | "patchline" : { 203 | "source" : [ "obj-7", 0 ], 204 | "destination" : [ "obj-16", 0 ], 205 | "hidden" : 0, 206 | "midpoints" : [ ] 207 | } 208 | 209 | } 210 | , { 211 | "patchline" : { 212 | "source" : [ "obj-7", 1 ], 213 | "destination" : [ "obj-14", 0 ], 214 | "hidden" : 0, 215 | "midpoints" : [ 211.0, 216.5, 128.5, 216.5 ] 216 | } 217 | 218 | } 219 | , { 220 | "patchline" : { 221 | "source" : [ "obj-3", 0 ], 222 | "destination" : [ "obj-7", 0 ], 223 | "hidden" : 0, 224 | "midpoints" : [ ] 225 | } 226 | 227 | } 228 | , { 229 | "patchline" : { 230 | "source" : [ "obj-2", 0 ], 231 | "destination" : [ "obj-3", 0 ], 232 | "hidden" : 0, 233 | "midpoints" : [ ] 234 | } 235 | 236 | } 237 | , { 238 | "patchline" : { 239 | "source" : [ "obj-16", 0 ], 240 | "destination" : [ "obj-11", 0 ], 241 | "hidden" : 0, 242 | "midpoints" : [ ] 243 | } 244 | 245 | } 246 | , { 247 | "patchline" : { 248 | "source" : [ "obj-14", 0 ], 249 | "destination" : [ "obj-11", 0 ], 250 | "hidden" : 0, 251 | "midpoints" : [ 128.5, 249.0, 87.5, 249.0 ] 252 | } 253 | 254 | } 255 | , { 256 | "patchline" : { 257 | "source" : [ "obj-11", 0 ], 258 | "destination" : [ "obj-17", 0 ], 259 | "hidden" : 0, 260 | "midpoints" : [ ] 261 | } 262 | 263 | } 264 | , { 265 | "patchline" : { 266 | "source" : [ "obj-11", 0 ], 267 | "destination" : [ "obj-10", 0 ], 268 | "hidden" : 0, 269 | "midpoints" : [ 87.5, 281.5, 231.5, 281.5 ] 270 | } 271 | 272 | } 273 | , { 274 | "patchline" : { 275 | "source" : [ "obj-1", 1 ], 276 | "destination" : [ "obj-2", 0 ], 277 | "hidden" : 0, 278 | "midpoints" : [ 152.0, 129.0, 87.5, 129.0 ] 279 | } 280 | 281 | } 282 | ] 283 | } 284 | 285 | } 286 | -------------------------------------------------------------------------------- /cassiel.zeroconf/help/zeroconf.resolve.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 1163.0, 383.0, 640.0, 506.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 1163.0, 383.0, 640.0, 506.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 10.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Verdana", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 5.0, 5.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "boxes" : [ { 19 | "box" : { 20 | "maxclass" : "newobj", 21 | "text" : "zeroconf.service @name \"Un autre service\" @port 6666 @type _osc._udp", 22 | "fontsize" : 10.0, 23 | "patching_rect" : [ 103.0, 262.0, 380.0, 19.0 ], 24 | "id" : "obj-6", 25 | "numinlets" : 1, 26 | "fontname" : "Verdana", 27 | "numoutlets" : 0 28 | } 29 | 30 | } 31 | , { 32 | "box" : { 33 | "maxclass" : "button", 34 | "outlettype" : [ "bang" ], 35 | "patching_rect" : [ 103.0, 64.0, 20.0, 20.0 ], 36 | "id" : "obj-4", 37 | "numinlets" : 1, 38 | "numoutlets" : 1 39 | } 40 | 41 | } 42 | , { 43 | "box" : { 44 | "maxclass" : "newobj", 45 | "text" : "print", 46 | "fontsize" : 10.0, 47 | "patching_rect" : [ 103.0, 170.0, 34.0, 19.0 ], 48 | "id" : "obj-2", 49 | "numinlets" : 1, 50 | "fontname" : "Verdana", 51 | "numoutlets" : 0 52 | } 53 | 54 | } 55 | , { 56 | "box" : { 57 | "maxclass" : "newobj", 58 | "text" : "zeroconf.resolve @name \"Un autre service\" @type _osc._udp @domain local.", 59 | "outlettype" : [ "" ], 60 | "fontsize" : 10.0, 61 | "patching_rect" : [ 103.0, 128.0, 399.0, 19.0 ], 62 | "id" : "obj-1", 63 | "numinlets" : 1, 64 | "fontname" : "Verdana", 65 | "numoutlets" : 1 66 | } 67 | 68 | } 69 | ], 70 | "lines" : [ { 71 | "patchline" : { 72 | "source" : [ "obj-1", 0 ], 73 | "destination" : [ "obj-2", 0 ], 74 | "hidden" : 0, 75 | "midpoints" : [ ] 76 | } 77 | 78 | } 79 | , { 80 | "patchline" : { 81 | "source" : [ "obj-4", 0 ], 82 | "destination" : [ "obj-1", 0 ], 83 | "hidden" : 0, 84 | "midpoints" : [ ] 85 | } 86 | 87 | } 88 | ] 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /cassiel.zeroconf/help/zeroconf.service.maxhelp: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 520.0, 360.0, 640.0, 506.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 520.0, 360.0, 640.0, 506.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 10.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Verdana", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 5.0, 5.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "boxes" : [ { 19 | "box" : { 20 | "maxclass" : "newobj", 21 | "text" : "zeroconf.service @name \"Un autre service\" @port 6666 @type _osc._udp", 22 | "id" : "obj-6", 23 | "fontname" : "Verdana", 24 | "numinlets" : 1, 25 | "fontsize" : 10.0, 26 | "numoutlets" : 0, 27 | "patching_rect" : [ 24.0, 154.0, 271.0, 19.0 ] 28 | } 29 | 30 | } 31 | , { 32 | "box" : { 33 | "maxclass" : "comment", 34 | "text" : "ZeroConf.service", 35 | "id" : "obj-9", 36 | "fontname" : "Arial", 37 | "numinlets" : 1, 38 | "fontsize" : 24.0, 39 | "numoutlets" : 0, 40 | "patching_rect" : [ 10.0, 11.0, 196.0, 34.0 ] 41 | } 42 | 43 | } 44 | , { 45 | "box" : { 46 | "maxclass" : "newobj", 47 | "text" : "zeroconf.service @name \"Open Sound Control UDP Service\" @port 12345 @type _osc._udp", 48 | "id" : "obj-1", 49 | "fontname" : "Verdana", 50 | "numinlets" : 1, 51 | "fontsize" : 10.0, 52 | "numoutlets" : 0, 53 | "patching_rect" : [ 23.0, 104.0, 362.0, 19.0 ] 54 | } 55 | 56 | } 57 | ], 58 | "lines" : [ ] 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /cassiel.zeroconf/patchers/zeroconf_example.maxpat: -------------------------------------------------------------------------------- 1 | { 2 | "patcher" : { 3 | "fileversion" : 1, 4 | "rect" : [ 488.0, 594.0, 953.0, 379.0 ], 5 | "bglocked" : 0, 6 | "defrect" : [ 488.0, 594.0, 953.0, 379.0 ], 7 | "openrect" : [ 0.0, 0.0, 0.0, 0.0 ], 8 | "openinpresentation" : 0, 9 | "default_fontsize" : 12.0, 10 | "default_fontface" : 0, 11 | "default_fontname" : "Arial", 12 | "gridonopen" : 0, 13 | "gridsize" : [ 15.0, 15.0 ], 14 | "gridsnaponopen" : 0, 15 | "toolbarvisible" : 1, 16 | "boxanimatetime" : 200, 17 | "imprint" : 0, 18 | "boxes" : [ { 19 | "box" : { 20 | "maxclass" : "button", 21 | "numoutlets" : 1, 22 | "outlettype" : [ "bang" ], 23 | "patching_rect" : [ 20.0, 167.0, 20.0, 20.0 ], 24 | "id" : "obj-27", 25 | "numinlets" : 1 26 | } 27 | 28 | } 29 | , { 30 | "box" : { 31 | "maxclass" : "comment", 32 | "text" : "Choose a service to Test", 33 | "numoutlets" : 0, 34 | "fontname" : "Arial", 35 | "patching_rect" : [ 191.0, 102.0, 150.0, 20.0 ], 36 | "id" : "obj-25", 37 | "fontsize" : 12.0, 38 | "numinlets" : 1 39 | } 40 | 41 | } 42 | , { 43 | "box" : { 44 | "maxclass" : "comment", 45 | "text" : "Test", 46 | "numoutlets" : 0, 47 | "fontname" : "Arial", 48 | "patching_rect" : [ 190.0, 265.0, 150.0, 20.0 ], 49 | "id" : "obj-23", 50 | "fontsize" : 12.0, 51 | "numinlets" : 1 52 | } 53 | 54 | } 55 | , { 56 | "box" : { 57 | "maxclass" : "comment", 58 | "text" : "Browse", 59 | "numoutlets" : 0, 60 | "fontname" : "Arial", 61 | "patching_rect" : [ 68.0, 19.0, 150.0, 20.0 ], 62 | "id" : "obj-21", 63 | "fontsize" : 12.0, 64 | "numinlets" : 1 65 | } 66 | 67 | } 68 | , { 69 | "box" : { 70 | "maxclass" : "button", 71 | "numoutlets" : 1, 72 | "outlettype" : [ "bang" ], 73 | "patching_rect" : [ 458.0, 16.0, 20.0, 20.0 ], 74 | "id" : "obj-19", 75 | "numinlets" : 1 76 | } 77 | 78 | } 79 | , { 80 | "box" : { 81 | "maxclass" : "message", 82 | "text" : "clear", 83 | "numoutlets" : 1, 84 | "outlettype" : [ "" ], 85 | "fontname" : "Arial", 86 | "patching_rect" : [ 4.0, 48.0, 37.0, 18.0 ], 87 | "id" : "obj-18", 88 | "fontsize" : 12.0, 89 | "numinlets" : 2 90 | } 91 | 92 | } 93 | , { 94 | "box" : { 95 | "maxclass" : "newobj", 96 | "text" : "print", 97 | "numoutlets" : 0, 98 | "fontname" : "Arial", 99 | "patching_rect" : [ 22.0, 101.0, 34.0, 20.0 ], 100 | "id" : "obj-6", 101 | "fontsize" : 12.0, 102 | "numinlets" : 1 103 | } 104 | 105 | } 106 | , { 107 | "box" : { 108 | "maxclass" : "button", 109 | "numoutlets" : 1, 110 | "outlettype" : [ "bang" ], 111 | "patching_rect" : [ 458.0, 149.0, 20.0, 20.0 ], 112 | "id" : "obj-17", 113 | "numinlets" : 1 114 | } 115 | 116 | } 117 | , { 118 | "box" : { 119 | "maxclass" : "newobj", 120 | "text" : "print Toto123", 121 | "numoutlets" : 0, 122 | "fontname" : "Arial", 123 | "patching_rect" : [ 458.0, 222.0, 81.0, 20.0 ], 124 | "id" : "obj-13", 125 | "fontsize" : 12.0, 126 | "numinlets" : 1 127 | } 128 | 129 | } 130 | , { 131 | "box" : { 132 | "maxclass" : "newobj", 133 | "text" : "udpreceive 1234", 134 | "numoutlets" : 1, 135 | "outlettype" : [ "" ], 136 | "fontname" : "Arial", 137 | "patching_rect" : [ 458.0, 196.0, 99.0, 20.0 ], 138 | "id" : "obj-14", 139 | "fontsize" : 12.0, 140 | "numinlets" : 1 141 | } 142 | 143 | } 144 | , { 145 | "box" : { 146 | "maxclass" : "newobj", 147 | "text" : "zeroconf.service @name Toto123 @port 1234 @type _osc._udp", 148 | "numoutlets" : 0, 149 | "fontname" : "Arial", 150 | "patching_rect" : [ 458.0, 172.0, 354.0, 20.0 ], 151 | "id" : "obj-15", 152 | "fontsize" : 12.0, 153 | "numinlets" : 1 154 | } 155 | 156 | } 157 | , { 158 | "box" : { 159 | "maxclass" : "newobj", 160 | "text" : "print", 161 | "numoutlets" : 0, 162 | "fontname" : "Arial", 163 | "patching_rect" : [ 60.0, 223.0, 34.0, 20.0 ], 164 | "id" : "obj-12", 165 | "fontsize" : 12.0, 166 | "numinlets" : 1 167 | } 168 | 169 | } 170 | , { 171 | "box" : { 172 | "maxclass" : "button", 173 | "numoutlets" : 1, 174 | "outlettype" : [ "bang" ], 175 | "patching_rect" : [ 41.0, 19.0, 20.0, 20.0 ], 176 | "id" : "obj-8", 177 | "numinlets" : 1 178 | } 179 | 180 | } 181 | , { 182 | "box" : { 183 | "maxclass" : "newobj", 184 | "text" : "print \"An Open Sound Control Service\"", 185 | "numoutlets" : 0, 186 | "fontname" : "Arial", 187 | "patching_rect" : [ 458.0, 96.0, 216.0, 20.0 ], 188 | "id" : "obj-11", 189 | "fontsize" : 12.0, 190 | "numinlets" : 1 191 | } 192 | 193 | } 194 | , { 195 | "box" : { 196 | "maxclass" : "newobj", 197 | "text" : "udpreceive 4321", 198 | "numoutlets" : 1, 199 | "outlettype" : [ "" ], 200 | "fontname" : "Arial", 201 | "patching_rect" : [ 458.0, 70.0, 99.0, 20.0 ], 202 | "id" : "obj-10", 203 | "fontsize" : 12.0, 204 | "numinlets" : 1 205 | } 206 | 207 | } 208 | , { 209 | "box" : { 210 | "maxclass" : "message", 211 | "text" : "name $1, bang", 212 | "numoutlets" : 1, 213 | "outlettype" : [ "" ], 214 | "fontname" : "Arial", 215 | "patching_rect" : [ 41.0, 169.0, 91.0, 18.0 ], 216 | "id" : "obj-9", 217 | "fontsize" : 12.0, 218 | "numinlets" : 2 219 | } 220 | 221 | } 222 | , { 223 | "box" : { 224 | "maxclass" : "message", 225 | "text" : "/test/zeroconf 1 2 3", 226 | "numoutlets" : 1, 227 | "outlettype" : [ "" ], 228 | "fontname" : "Arial", 229 | "patching_rect" : [ 71.0, 266.0, 113.0, 18.0 ], 230 | "id" : "obj-7", 231 | "fontsize" : 12.0, 232 | "numinlets" : 2 233 | } 234 | 235 | } 236 | , { 237 | "box" : { 238 | "maxclass" : "newobj", 239 | "text" : "udpsend localhost 9000", 240 | "numoutlets" : 0, 241 | "fontname" : "Arial", 242 | "patching_rect" : [ 41.0, 303.0, 137.0, 20.0 ], 243 | "id" : "obj-5", 244 | "fontsize" : 12.0, 245 | "numinlets" : 1 246 | } 247 | 248 | } 249 | , { 250 | "box" : { 251 | "maxclass" : "umenu", 252 | "types" : [ ], 253 | "numoutlets" : 3, 254 | "items" : [ ], 255 | "outlettype" : [ "int", "", "" ], 256 | "fontname" : "Arial", 257 | "patching_rect" : [ 41.0, 75.0, 283.0, 20.0 ], 258 | "id" : "obj-4", 259 | "fontsize" : 12.0, 260 | "numinlets" : 1 261 | } 262 | 263 | } 264 | , { 265 | "box" : { 266 | "maxclass" : "newobj", 267 | "text" : "zeroconf.browser @type _osc._udp @domain local.", 268 | "numoutlets" : 1, 269 | "outlettype" : [ "" ], 270 | "fontname" : "Arial", 271 | "patching_rect" : [ 41.0, 47.0, 286.0, 20.0 ], 272 | "id" : "obj-3", 273 | "fontsize" : 12.0, 274 | "numinlets" : 1 275 | } 276 | 277 | } 278 | , { 279 | "box" : { 280 | "maxclass" : "newobj", 281 | "text" : "zeroconf.resolve @domain local. @type _osc._udp", 282 | "numoutlets" : 1, 283 | "outlettype" : [ "" ], 284 | "fontname" : "Verdana", 285 | "patching_rect" : [ 41.0, 195.0, 264.0, 19.0 ], 286 | "id" : "obj-2", 287 | "fontsize" : 10.0, 288 | "numinlets" : 1 289 | } 290 | 291 | } 292 | , { 293 | "box" : { 294 | "maxclass" : "newobj", 295 | "text" : "zeroconf.service @name \"An Open Sound Control Service\" @port 4321 @type _osc._udp", 296 | "numoutlets" : 0, 297 | "fontname" : "Arial", 298 | "patching_rect" : [ 458.0, 46.0, 489.0, 20.0 ], 299 | "id" : "obj-1", 300 | "fontsize" : 12.0, 301 | "numinlets" : 1 302 | } 303 | 304 | } 305 | ], 306 | "lines" : [ { 307 | "patchline" : { 308 | "source" : [ "obj-14", 0 ], 309 | "destination" : [ "obj-13", 0 ], 310 | "hidden" : 0, 311 | "midpoints" : [ ] 312 | } 313 | 314 | } 315 | , { 316 | "patchline" : { 317 | "source" : [ "obj-17", 0 ], 318 | "destination" : [ "obj-15", 0 ], 319 | "hidden" : 0, 320 | "midpoints" : [ ] 321 | } 322 | 323 | } 324 | , { 325 | "patchline" : { 326 | "source" : [ "obj-18", 0 ], 327 | "destination" : [ "obj-4", 0 ], 328 | "hidden" : 0, 329 | "midpoints" : [ 13.5, 71.0, 50.5, 71.0 ] 330 | } 331 | 332 | } 333 | , { 334 | "patchline" : { 335 | "source" : [ "obj-10", 0 ], 336 | "destination" : [ "obj-11", 0 ], 337 | "hidden" : 0, 338 | "midpoints" : [ ] 339 | } 340 | 341 | } 342 | , { 343 | "patchline" : { 344 | "source" : [ "obj-2", 0 ], 345 | "destination" : [ "obj-12", 0 ], 346 | "hidden" : 0, 347 | "midpoints" : [ ] 348 | } 349 | 350 | } 351 | , { 352 | "patchline" : { 353 | "source" : [ "obj-8", 0 ], 354 | "destination" : [ "obj-3", 0 ], 355 | "hidden" : 0, 356 | "midpoints" : [ ] 357 | } 358 | 359 | } 360 | , { 361 | "patchline" : { 362 | "source" : [ "obj-3", 0 ], 363 | "destination" : [ "obj-4", 0 ], 364 | "hidden" : 0, 365 | "midpoints" : [ ] 366 | } 367 | 368 | } 369 | , { 370 | "patchline" : { 371 | "source" : [ "obj-7", 0 ], 372 | "destination" : [ "obj-5", 0 ], 373 | "hidden" : 0, 374 | "midpoints" : [ 80.5, 293.0, 50.5, 293.0 ] 375 | } 376 | 377 | } 378 | , { 379 | "patchline" : { 380 | "source" : [ "obj-2", 0 ], 381 | "destination" : [ "obj-5", 0 ], 382 | "hidden" : 0, 383 | "midpoints" : [ ] 384 | } 385 | 386 | } 387 | , { 388 | "patchline" : { 389 | "source" : [ "obj-9", 0 ], 390 | "destination" : [ "obj-2", 0 ], 391 | "hidden" : 0, 392 | "midpoints" : [ ] 393 | } 394 | 395 | } 396 | , { 397 | "patchline" : { 398 | "source" : [ "obj-4", 1 ], 399 | "destination" : [ "obj-9", 0 ], 400 | "hidden" : 0, 401 | "midpoints" : [ 182.5, 131.5, 50.5, 131.5 ] 402 | } 403 | 404 | } 405 | , { 406 | "patchline" : { 407 | "source" : [ "obj-3", 0 ], 408 | "destination" : [ "obj-6", 0 ], 409 | "hidden" : 0, 410 | "midpoints" : [ 50.5, 72.5, 31.5, 72.5 ] 411 | } 412 | 413 | } 414 | , { 415 | "patchline" : { 416 | "source" : [ "obj-19", 0 ], 417 | "destination" : [ "obj-1", 0 ], 418 | "hidden" : 0, 419 | "midpoints" : [ ] 420 | } 421 | 422 | } 423 | , { 424 | "patchline" : { 425 | "source" : [ "obj-27", 0 ], 426 | "destination" : [ "obj-2", 0 ], 427 | "hidden" : 0, 428 | "midpoints" : [ 29.5, 190.5, 50.5, 190.5 ] 429 | } 430 | 431 | } 432 | ] 433 | } 434 | 435 | } 436 | -------------------------------------------------------------------------------- /deploy_os-x.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DEST="$HOME/Documents/Max 7/Packages" 4 | 5 | rm -rf "$DEST/cassiel.zeroconf" 6 | cp -r cassiel.zeroconf "$DEST/" 7 | -------------------------------------------------------------------------------- /source/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${PRODUCT_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.cassiel.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | ${PRODUCT_VERSION} 15 | CFBundlePackageType 16 | iLaX 17 | CFBundleSignature 18 | max2 19 | CFBundleVersion 20 | 1.0 21 | 22 | CFBundleVersion 23 | ${PRODUCT_VERSION} 24 | CFBundleShortVersionString 25 | ${PRODUCT_VERSION} 26 | CFBundleLongVersionString 27 | ${PRODUCT_NAME} ${PRODUCT_VERSION}, Copyright 2016 Remy Muller + Cassiel.com 28 | 29 | CSResourcesFileMapped 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /source/zeroconf/common/CriticalSection.cpp: -------------------------------------------------------------------------------- 1 | #include "../common/CriticalSection.h" 2 | #include 3 | 4 | using namespace ZeroConf; 5 | 6 | #ifdef WIN32 7 | 8 | #undef WIN32_LEAN_AND_MEAN 9 | #define WIN32_LEAN_AND_MEAN 1 10 | #define _WIN32_WINNT 0x0500 11 | 12 | #include 13 | 14 | CriticalSection::CriticalSection() 15 | { 16 | assert (sizeof (CRITICAL_SECTION) <= sizeof (details)); 17 | InitializeCriticalSection ((CRITICAL_SECTION*)details); 18 | } 19 | 20 | CriticalSection::~CriticalSection() 21 | { 22 | DeleteCriticalSection ((CRITICAL_SECTION*) details); 23 | } 24 | 25 | void CriticalSection::enter() const 26 | { 27 | EnterCriticalSection ((CRITICAL_SECTION*) details); 28 | } 29 | 30 | bool CriticalSection::tryEnter() const 31 | { 32 | return TryEnterCriticalSection ((CRITICAL_SECTION*) details) != FALSE; 33 | } 34 | 35 | void CriticalSection::exit() const 36 | { 37 | LeaveCriticalSection ((CRITICAL_SECTION*) details); 38 | } 39 | 40 | #else 41 | 42 | CriticalSection::CriticalSection() 43 | { 44 | pthread_mutexattr_t atts; 45 | pthread_mutexattr_init (&atts); 46 | pthread_mutexattr_settype (&atts, PTHREAD_MUTEX_RECURSIVE); 47 | pthread_mutex_init (&details, &atts); 48 | } 49 | 50 | CriticalSection::~CriticalSection() 51 | { 52 | pthread_mutex_destroy (&details); 53 | } 54 | 55 | void CriticalSection::enter() const 56 | { 57 | pthread_mutex_lock (&details); 58 | } 59 | 60 | bool CriticalSection::tryEnter() const 61 | { 62 | return pthread_mutex_trylock (&details) == 0; 63 | } 64 | 65 | void CriticalSection::exit() const 66 | { 67 | pthread_mutex_unlock (&details); 68 | } 69 | #endif -------------------------------------------------------------------------------- /source/zeroconf/common/CriticalSection.h: -------------------------------------------------------------------------------- 1 | #ifndef ZeroConf_CriticalSection_H 2 | #define ZeroConf_CriticalSection_H 3 | 4 | #ifndef WIN32 5 | #include 6 | #endif 7 | 8 | namespace ZeroConf 9 | { 10 | class CriticalSection 11 | { 12 | public: 13 | CriticalSection(); 14 | ~CriticalSection(); 15 | 16 | void enter() const; 17 | bool tryEnter() const; 18 | void exit() const; 19 | 20 | private: 21 | #ifdef WIN32 22 | char details[44]; 23 | #else 24 | mutable pthread_mutex_t details; 25 | #endif 26 | }; 27 | 28 | class ScopedLock 29 | { 30 | public: 31 | inline ScopedLock (const CriticalSection& lock) 32 | : mLock(lock) 33 | { 34 | mLock.enter(); 35 | } 36 | inline ~ScopedLock() 37 | { 38 | mLock.exit(); 39 | } 40 | private: 41 | const CriticalSection& mLock; 42 | }; 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /source/zeroconf/common/NetService.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #include "../common/NetService.h" 29 | #include "../common/NetServiceThread.h" 30 | #include "../common/Thread.h" 31 | #include 32 | #include 33 | #include 34 | //#include 35 | #include 36 | 37 | using namespace ZeroConf; 38 | 39 | typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16; 40 | typedef union { unsigned short NotAnInteger; unsigned char b[2]; } Opaque16b; 41 | 42 | static void DNSSD_API register_reply(DNSServiceRef sdRef, 43 | DNSServiceFlags flags, 44 | DNSServiceErrorType errorCode, 45 | const char *name, 46 | const char *regtype, 47 | const char *domain, 48 | void *context ) 49 | { 50 | // do something with the values that have been registered 51 | NetService *self = (NetService *)context; 52 | 53 | switch (errorCode) 54 | { 55 | case kDNSServiceErr_NoError: 56 | if(self->getListener()) 57 | { 58 | self->getListener()->didPublish(self); 59 | } 60 | break; 61 | case kDNSServiceErr_NameConflict: 62 | if(self->getListener()) 63 | { 64 | self->getListener()->didNotPublish(self); 65 | } 66 | break; 67 | default: 68 | if(self->getListener()) 69 | { 70 | self->getListener()->didNotPublish(self); 71 | } 72 | return; 73 | } 74 | } 75 | 76 | static void DNSSD_API resolve_reply(DNSServiceRef client, 77 | const DNSServiceFlags flags, 78 | uint32_t ifIndex, 79 | DNSServiceErrorType errorCode, 80 | const char *fullname, 81 | const char *hosttarget, 82 | uint16_t opaqueport, 83 | uint16_t txtLen, 84 | const char *txtRecord, 85 | void *context) 86 | { 87 | NetService *self = (NetService *)context; 88 | 89 | switch (errorCode) 90 | { 91 | case kDNSServiceErr_NoError: 92 | { 93 | Opaque16b port = { opaqueport }; 94 | uint16_t PortAsNumber = ((uint16_t)port.b[0]) << 8 | port.b[1]; 95 | self->setPort(PortAsNumber); 96 | self->setHostName(hosttarget); 97 | 98 | if(self->getListener()) 99 | { 100 | self->getListener()->didResolveAddress(self); 101 | } 102 | break; 103 | } 104 | default: 105 | break; 106 | } 107 | 108 | // Note: When the desired results have been returned, 109 | // the client MUST terminate the resolve by calling DNSServiceRefDeallocate(). 110 | self->stop(); 111 | } 112 | 113 | //------------------------------------------------------------------------------ 114 | NetService::NetService(const std::string &domain, const std::string &type, const std::string &name, const int port) 115 | : mDNSServiceRef(NULL) 116 | , mDomain(domain) 117 | , mType(type) 118 | , mName(name) 119 | , mPort(port) 120 | , mpListener(NULL) 121 | , mpNetServiceThread(NULL) 122 | { 123 | } 124 | 125 | NetService::NetService(const std::string &domain, const std::string &type, const std::string &name) 126 | : mDNSServiceRef(NULL) 127 | , mDomain(domain) 128 | , mType(type) 129 | , mName(name) 130 | , mPort(-1) 131 | , mpListener(NULL) 132 | , mpNetServiceThread(NULL) 133 | { 134 | } 135 | 136 | NetService::~NetService() 137 | { 138 | stop(); 139 | } 140 | 141 | void NetService::setListener(NetServiceListener *pNetServiceListener) 142 | { 143 | mpListener = pNetServiceListener; 144 | } 145 | 146 | NetServiceListener *NetService::getListener() const 147 | { 148 | return mpListener; 149 | } 150 | 151 | void NetService::setPort(int port) 152 | { 153 | mPort = port; 154 | } 155 | 156 | void NetService::setName(const std::string &name) 157 | { 158 | mName = name; 159 | } 160 | 161 | void NetService::setHostName(const std::string &name) 162 | { 163 | mHostName = name; 164 | } 165 | 166 | void NetService::publish(bool launchThread) 167 | { 168 | publishWithOptions(Options(0), launchThread); 169 | } 170 | 171 | void NetService::publishWithOptions(Options options, bool launchThread) 172 | { 173 | stop(); 174 | 175 | if(mPort<0) 176 | { 177 | if(mpListener) 178 | { 179 | mpListener->didNotPublish(this); 180 | } 181 | return; 182 | } 183 | 184 | DNSServiceFlags flags = options; // default renaming behaviour 185 | uint32_t interfaceIndex = kDNSServiceInterfaceIndexAny; // all interfaces 186 | const char *name = mName.c_str(); /* may be NULL */ 187 | const char *regtype = mType.c_str(); 188 | const char *domain = mDomain.c_str(); /* may be NULL */ 189 | const char *host = ""; /* may be NULL */ 190 | uint16_t PortAsNumber = mPort; 191 | Opaque16 registerPort = { { PortAsNumber >> 8, PortAsNumber & 0xFF } }; 192 | uint16_t txtLen = 0; 193 | const void *txtRecord = ""; /* may be NULL */ 194 | DNSServiceRegisterReply callBack = (DNSServiceRegisterReply)®ister_reply; /* may be NULL */ 195 | void *context = this; /* may be NULL */ 196 | DNSServiceErrorType result = DNSServiceRegister(&mDNSServiceRef, 197 | flags, 198 | interfaceIndex, 199 | name, 200 | regtype, 201 | domain, 202 | host, 203 | registerPort.NotAnInteger, 204 | txtLen, 205 | txtRecord, 206 | callBack, 207 | context); 208 | if(result != kDNSServiceErr_NoError) 209 | { 210 | if(mpListener) 211 | { 212 | mpListener->didNotPublish(this); 213 | } 214 | if(mDNSServiceRef) 215 | DNSServiceRefDeallocate(mDNSServiceRef); 216 | mDNSServiceRef = NULL; 217 | } 218 | else 219 | { 220 | if(mpListener) 221 | { 222 | mpListener->willPublish(this); 223 | } 224 | if(launchThread) 225 | { 226 | mpNetServiceThread = new NetServiceThread(mDNSServiceRef, 1.0); 227 | mpNetServiceThread->startThread(); 228 | } 229 | } 230 | } 231 | 232 | void NetService::resolveWithTimeout(double timeOutInSeconds, bool launchThread) 233 | { 234 | stop(); 235 | 236 | DNSServiceFlags flags = 0; 237 | uint32_t interfaceIndex = kDNSServiceInterfaceIndexAny; // all interfaces 238 | DNSServiceErrorType err = DNSServiceResolve(&mDNSServiceRef, 239 | flags, 240 | interfaceIndex, 241 | mName.c_str(), 242 | mType.c_str(), 243 | mDomain.c_str(), 244 | (DNSServiceResolveReply)&resolve_reply, 245 | this); 246 | 247 | if (!mDNSServiceRef || err != kDNSServiceErr_NoError) 248 | { 249 | if(mpListener) 250 | { 251 | mpListener->didNotResolve(this); 252 | } 253 | if(mDNSServiceRef) 254 | DNSServiceRefDeallocate(mDNSServiceRef); 255 | mDNSServiceRef = NULL; 256 | } 257 | else 258 | { 259 | if(mpListener) 260 | { 261 | mpListener->willResolve(this); 262 | } 263 | if(launchThread) 264 | { 265 | mpNetServiceThread = new NetServiceThread(mDNSServiceRef, 1.0); 266 | mpNetServiceThread->startThread(); 267 | } 268 | } 269 | } 270 | 271 | void NetService::stop() 272 | { 273 | if(mpNetServiceThread) 274 | { 275 | mpNetServiceThread->setThreadShouldExit(); 276 | mpNetServiceThread->waitForThreadToExit(100); 277 | delete mpNetServiceThread; 278 | mpNetServiceThread = NULL; 279 | } 280 | 281 | if(mDNSServiceRef) 282 | { 283 | DNSServiceRefDeallocate(mDNSServiceRef); 284 | mDNSServiceRef = NULL; 285 | } 286 | } 287 | 288 | void NetService::startMonitoring() 289 | { 290 | assert(0); 291 | } 292 | 293 | void NetService::stopMonitoring() 294 | { 295 | assert(0); 296 | } 297 | -------------------------------------------------------------------------------- /source/zeroconf/common/NetService.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #ifndef ZeroConf_NetService_H 29 | #define ZeroConf_NetService_H 30 | 31 | #include 32 | #include "../common/CriticalSection.h" 33 | #include "dns_sd.h" 34 | 35 | namespace ZeroConf 36 | { 37 | class NetService; 38 | class NetServiceThread; 39 | 40 | class NetServiceListener 41 | { 42 | public: 43 | virtual ~NetServiceListener() {} 44 | 45 | virtual void willPublish(NetService *pNetService) = 0; 46 | virtual void didNotPublish(NetService *pNetService) = 0; 47 | virtual void didPublish(NetService *pNetService) = 0; 48 | 49 | virtual void willResolve(NetService *pNetService) = 0; 50 | virtual void didNotResolve(NetService *NetService) = 0; 51 | virtual void didResolveAddress(NetService *pNetService) = 0; 52 | 53 | virtual void didUpdateTXTRecordData(NetService *pNetService) = 0; 54 | 55 | virtual void didStop(NetService *pNetService) = 0; 56 | }; 57 | 58 | /** 59 | C++ equivalent to the Cocoa API class: NSNetService. 60 | cf http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNetService_Class/Reference/Reference.html 61 | 62 | The NetService class represents a network service that your application publishes or uses as a client. 63 | This class and the NetServiceBrowser class use multicast DNS to convey information about network services to and from your application. 64 | The API of NetService provides a convenient way to publish the services offered by your application and to resolve the socket address for a service. 65 | 66 | The types of services you access using NetService are the same types that you access directly using BSD sockets. 67 | HTTP and FTP are two services commonly provided by systems. 68 | (For a list of common services and the ports used by those services, see the file /etc/services.) 69 | Applications can also define their own custom services to provide specific data to clients. 70 | 71 | You can use the NetService class as either a publisher of a service or as a client of a service. 72 | If your application publishes a service, your code must acquire a port and prepare a socket to communicate with clients. 73 | Once your socket is ready, you use the NetService class to notify clients that your service is ready. 74 | If your application is the client of a network service, you can either create an NetService object directly 75 | (if you know the exact host and port information) or you can use an NetServiceBrowser object to browse for services. 76 | 77 | To publish a service, you must initialize your NetService object with the service name, domain, type, and port information. 78 | All of this information must be valid for the socket created by your application. 79 | Once initialized, you call the publish method to broadcast your service information out to the network. 80 | 81 | When connecting to a service, you would normally use the NetServiceBrowser class to locate the service on the network and obtain the corresponding NSNetService object. 82 | Once you have the object, you proceed to call the resolveWithTimeout: method to verify that the service is available and ready for your application. 83 | If it is, the addresses method returns the socket information you can use to connect to the service. 84 | 85 | The methods of NetService operate asynchronously so that your application is not impacted by the speed of the network. 86 | All information about a service is returned to your application through the NetService object’s listener. 87 | You must provide a listener object to respond to messages and to handle errors appropriately. 88 | */ 89 | class NetService 90 | { 91 | public: 92 | enum { NoAutoRename = 1<<0 }; 93 | typedef unsigned int Options; ///< These constants specify options for a network service. 94 | 95 | /** 96 | Constructor used when publishing services. 97 | */ 98 | NetService(const std::string &domain, const std::string &type, const std::string &name, const int port); 99 | 100 | /** 101 | Constructor used when resolving services. 102 | 103 | This method is the appropriate initializer to use to resolve a service. 104 | If you know the values for domain, type, and name of the service you wish to connect to, you can create an NSNetService object using this initializer and call resolveWithTimeout: on the result. 105 | You cannot use this initializer to publish a service. 106 | This initializer passes an invalid port number, which prevents the service from being registered. 107 | Calling publish on an NetService object initialized with this method generates a call to your listener’s netService:didNotPublish: method with an NSNetServicesBadArgumentError error. 108 | */ 109 | NetService(const std::string &domain, const std::string &type, const std::string &name); 110 | virtual ~NetService(); 111 | 112 | void setListener(NetServiceListener *pNetServiceListener); 113 | NetServiceListener *getListener() const; 114 | 115 | void publish(bool launchThread); 116 | void publishWithOptions(Options options, bool launchThread=true); 117 | 118 | void resolveWithTimeout(double timeOutInSeconds, bool launchThread = true); 119 | 120 | /** Halts a currently running attempt to publish or resolve a service. 121 | 122 | this method results in the sending of a netServiceDidStop: message to the delegate. 123 | */ 124 | void stop(); 125 | 126 | void startMonitoring(); 127 | void stopMonitoring(); 128 | 129 | const std::string& getDomain() const { return mDomain; } 130 | 131 | const std::string& getType() const { return mType; } 132 | 133 | void setName(const std::string &name); 134 | const std::string& getName() const { return mName; } 135 | 136 | void setPort(int port); 137 | const int getPort() const {return mPort; } 138 | 139 | void setHostName(const std::string &name); 140 | const std::string& getHostName() const { return mHostName; } 141 | 142 | DNSServiceRef getDNSServiceRef() { return mDNSServiceRef; } 143 | 144 | private: 145 | DNSServiceRef mDNSServiceRef; 146 | std::string mDomain; 147 | std::string mType; 148 | std::string mName; 149 | std::string mHostName; 150 | int mPort; 151 | std::string mTXTRecordData; 152 | NetServiceListener *mpListener; 153 | CriticalSection mCriticalSection; 154 | 155 | NetServiceThread *mpNetServiceThread; 156 | }; 157 | } 158 | 159 | #endif -------------------------------------------------------------------------------- /source/zeroconf/common/NetServiceBrowser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #include "../common/NetServiceBrowser.h" 29 | #include "../common/NetService.h" 30 | #include "../common/NetServiceThread.h" 31 | #include 32 | #include 33 | 34 | #include 35 | 36 | using namespace ZeroConf; 37 | 38 | static void DNSSD_API browse_reply(DNSServiceRef client, 39 | const DNSServiceFlags flags, 40 | uint32_t ifIndex, 41 | DNSServiceErrorType errorCode, 42 | const char *replyName, 43 | const char *replyType, 44 | const char *replyDomain, 45 | void *context) 46 | { 47 | #if 0 48 | std::cout << "name=" << replyName << " type=" << replyType << " domain=" << replyDomain << std::endl; 49 | #endif 50 | #if 1 51 | NetServiceBrowser *self = (NetServiceBrowser *)context; 52 | const bool moreComing = bool(flags & kDNSServiceFlagsMoreComing); 53 | 54 | if(!self->getListener()) return; 55 | 56 | if(flags & kDNSServiceFlagsAdd) 57 | { 58 | self->addService(replyDomain,replyType,replyName, moreComing); 59 | } 60 | else 61 | { 62 | self->removeService(replyDomain,replyType,replyName, moreComing); 63 | } 64 | #endif 65 | } 66 | 67 | NetServiceBrowser::NetServiceBrowser() 68 | : mpListener(NULL) 69 | , mpNetServiceThread(NULL) 70 | , mDNSServiceRef(NULL) 71 | { 72 | } 73 | 74 | NetServiceBrowser::~NetServiceBrowser() 75 | { 76 | stop(); 77 | } 78 | 79 | void NetServiceBrowser::setListener(NetServiceBrowserListener *pNetServiceBrowserListener) 80 | { 81 | mpListener = pNetServiceBrowserListener; 82 | } 83 | 84 | NetServiceBrowserListener* NetServiceBrowser::getListener() const 85 | { 86 | return mpListener; 87 | } 88 | 89 | void NetServiceBrowser::searchForBrowsableDomains() 90 | { 91 | assert(0); 92 | } 93 | 94 | void NetServiceBrowser::searchForRegistrationDomains() 95 | { 96 | assert(0); 97 | } 98 | 99 | void NetServiceBrowser::searchForServicesOfType(const std::string &serviceType, const std::string &domainName, bool launchThread) 100 | { 101 | stop(); 102 | 103 | DNSServiceFlags flags = 0; // default renaming behaviour 104 | uint32_t interfaceIndex = kDNSServiceInterfaceIndexAny; // all interfaces 105 | DNSServiceErrorType err = DNSServiceBrowse(&mDNSServiceRef, 106 | flags, 107 | interfaceIndex, 108 | serviceType.c_str(), 109 | domainName.c_str(), 110 | (DNSServiceBrowseReply)&browse_reply, 111 | this); 112 | 113 | if (!mDNSServiceRef || err != kDNSServiceErr_NoError) 114 | { 115 | if(mpListener) 116 | { 117 | mpListener->didNotSearch(this); 118 | } 119 | if(mDNSServiceRef) 120 | DNSServiceRefDeallocate(mDNSServiceRef); 121 | mDNSServiceRef = NULL; 122 | } 123 | else 124 | { 125 | if(mpListener) 126 | mpListener->willSearch(this); 127 | 128 | if(launchThread) 129 | { 130 | mpNetServiceThread = new NetServiceThread(mDNSServiceRef, 1.0); 131 | mpNetServiceThread->startThread(); 132 | } 133 | } 134 | } 135 | 136 | void NetServiceBrowser::stop() 137 | { 138 | if(mpNetServiceThread) 139 | { 140 | mpNetServiceThread->setThreadShouldExit(); 141 | mpNetServiceThread->waitForThreadToExit(100); 142 | delete mpNetServiceThread; 143 | mpNetServiceThread = NULL; 144 | } 145 | 146 | if(mDNSServiceRef) 147 | DNSServiceRefDeallocate(mDNSServiceRef); 148 | mDNSServiceRef = NULL; 149 | } 150 | 151 | void NetServiceBrowser::addService(const char *domain, const char *type, const char *name, bool moreComing) 152 | { 153 | NetService *pNetService = new NetService(domain, type, name); 154 | { 155 | ScopedLock lock(mCriticalSection); 156 | mServices.push_back(pNetService); 157 | } 158 | if(mpListener) 159 | mpListener->didFindService(this, pNetService, moreComing); 160 | } 161 | 162 | void NetServiceBrowser::removeService(const char *domain, const char *type, const char *name, bool moreComing) 163 | { 164 | ScopedLock lock(mCriticalSection); 165 | for(std::vector::iterator it = mServices.begin(); it != mServices.end();) 166 | { 167 | if((*it)->getName() == name && (*it)->getDomain() == domain && (*it)-> getType() == type) 168 | { 169 | NetService *pNetService = *it; 170 | it = mServices.erase(it); 171 | if(mpListener) 172 | mpListener->didRemoveService(this, pNetService, moreComing); 173 | } 174 | else 175 | { 176 | ++it; 177 | } 178 | } 179 | } 180 | 181 | -------------------------------------------------------------------------------- /source/zeroconf/common/NetServiceBrowser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #ifndef ZeroConf_NetServiceBrowser_H 29 | #define ZeroConf_NetServiceBrowser_H 30 | 31 | #include "../common/CriticalSection.h" 32 | #include 33 | #include 34 | #include "dns_sd.h" 35 | 36 | namespace ZeroConf 37 | { 38 | class NetService; 39 | class NetServiceBrowser; 40 | class NetServiceThread; 41 | 42 | class NetServiceBrowserListener 43 | { 44 | public: 45 | virtual ~NetServiceBrowserListener() {} 46 | 47 | virtual void didFindDomain(NetServiceBrowser *pNetServiceBrowser, const std::string &domainName, bool moreDomainsComing) = 0; 48 | virtual void didRemoveDomain(NetServiceBrowser *pNetServiceBrowser, const std::string &domainName, bool moreDomainsComing) = 0; 49 | 50 | virtual void didFindService(NetServiceBrowser* pNetServiceBrowser, NetService *pNetService, bool moreServicesComing) = 0; 51 | virtual void didRemoveService(NetServiceBrowser *pNetServiceBrowser, NetService *pNetService, bool moreServicesComing) = 0; 52 | 53 | virtual void willSearch(NetServiceBrowser *pNetServiceBrowser) = 0; 54 | virtual void didNotSearch(NetServiceBrowser *pNetServiceBrowser) = 0; 55 | 56 | virtual void didStopSearch(NetServiceBrowser *pNetServiceBrowser) = 0; 57 | }; 58 | 59 | /** C++ equivalent to Cocoa NSNetServiceBrowser 60 | cf http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNetServiceBrowser_Class/Reference/Reference.html 61 | 62 | The NetServiceBrowser class defines an interface for finding published services on a network using multicast DNS. 63 | An instance of NetServiceBrowser is known as a network service browser. 64 | 65 | Services can range from standard services, such as HTTP and FTP, to custom services defined by other applications. 66 | You can use a network service browser in your code to obtain the list of accessible domains and then to obtain an NetService object for each discovered service. 67 | Each network service browser performs one search at a time, so if you want to perform multiple simultaneous searches, use multiple network service browsers. 68 | 69 | A network service browser performs all searches asynchronously using the current run loop to execute the search in the background. 70 | Results from a search are returned through the associated listener object, which your client application must provide. 71 | Searching proceeds in the background until the object receives a stop message. 72 | 73 | To use an NetServiceBrowser object to search for services, allocate it, initialize it, and assign a listener. 74 | Once your object is ready, you begin by gathering the list of accessible domains using either the searchForRegistrationDomains or searchForBrowsableDomains methods. 75 | From the list of returned domains, you can pick one and use the searchForServicesOfType method to search for services in that domain. 76 | 77 | The NetServiceBrowser class provides two ways to search for domains. 78 | In most cases, your client should use the searchForRegistrationDomains method to search only for local domains to which the host machine has registration authority. 79 | This is the preferred method for accessing domains as it guarantees that the host machine can connect to services in the returned domains. 80 | Access to domains outside this list may be more limited. 81 | */ 82 | class NetServiceBrowser 83 | { 84 | public: 85 | NetServiceBrowser(); 86 | virtual ~NetServiceBrowser(); 87 | 88 | void setListener(NetServiceBrowserListener *pNetServiceBrowserListener); 89 | NetServiceBrowserListener* getListener() const; 90 | 91 | void searchForBrowsableDomains(); 92 | void searchForRegistrationDomains(); 93 | 94 | void searchForServicesOfType(const std::string &serviceType, const std::string &domainName, bool launchThread=true); 95 | 96 | /** Halts a currently running search or resolution. */ 97 | void stop(); 98 | 99 | void addService(const char *domain, const char *type, const char *name, bool moreComing); 100 | void removeService(const char *domain, const char *type, const char *name, bool moreComming); 101 | 102 | DNSServiceRef getDNSServiceRef() { return mDNSServiceRef; } 103 | 104 | private: 105 | DNSServiceRef mDNSServiceRef; 106 | NetServiceBrowserListener *mpListener; 107 | CriticalSection mCriticalSection; 108 | NetServiceThread *mpNetServiceThread; 109 | std::vector mServices; 110 | }; 111 | } 112 | 113 | #endif -------------------------------------------------------------------------------- /source/zeroconf/common/NetServiceThread.cpp: -------------------------------------------------------------------------------- 1 | #include "../common/NetServiceThread.h" 2 | #include 3 | #include 4 | #include 5 | //#include 6 | 7 | using namespace ZeroConf; 8 | 9 | NetServiceThread::NetServiceThread(DNSServiceRef dnsServiceRef, double timeOutInSeconds) 10 | : mDNSServiceRef(dnsServiceRef) 11 | , mTimeOut(timeOutInSeconds) 12 | { 13 | } 14 | 15 | NetServiceThread::~NetServiceThread() 16 | { 17 | if(!waitForThreadToExit(100)) 18 | { 19 | stopThread(1); 20 | } 21 | } 22 | 23 | bool NetServiceThread::poll(DNSServiceRef dnsServiceRef, double timeOutInSeconds, DNSServiceErrorType &err) 24 | { 25 | assert(dnsServiceRef); 26 | 27 | err = kDNSServiceErr_NoError; 28 | 29 | fd_set readfds; 30 | FD_ZERO(&readfds); 31 | 32 | int dns_sd_fd = DNSServiceRefSockFD(dnsServiceRef); 33 | int nfds = dns_sd_fd+1; 34 | FD_SET(dns_sd_fd, &readfds); 35 | 36 | struct timeval tv; 37 | tv.tv_sec = long(floor(timeOutInSeconds)); 38 | tv.tv_usec = long(1000000*(timeOutInSeconds - tv.tv_sec)); 39 | 40 | int result = select(nfds,&readfds,NULL,NULL,&tv); 41 | if(result>0 && FD_ISSET(dns_sd_fd, &readfds)) 42 | { 43 | err = DNSServiceProcessResult(dnsServiceRef); 44 | return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | bool NetServiceThread::poll1(DNSServiceRef dnsServiceRef, double timeOutInSeconds, DNSServiceErrorType &err) 51 | { 52 | assert(dnsServiceRef); 53 | err = DNSServiceProcessResult(dnsServiceRef); 54 | return true; 55 | } 56 | 57 | void NetServiceThread::run() 58 | { 59 | std::cout << "NetServiceThread::start()" << std::endl; 60 | 61 | while (!threadShouldExit()) 62 | { 63 | DNSServiceErrorType err = kDNSServiceErr_NoError; 64 | if(poll(mDNSServiceRef, mTimeOut, err)) 65 | { 66 | if(err>0) 67 | { 68 | setThreadShouldExit(); 69 | } 70 | } 71 | } 72 | std::cout << "NetServiceThread::stop()" << std::endl; 73 | } 74 | -------------------------------------------------------------------------------- /source/zeroconf/common/NetServiceThread.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #ifndef ZeroConf_NetServiceThread_H 29 | #define ZeroConf_NetServiceThread_H 30 | 31 | #include 32 | #include "../common/Thread.h" 33 | #include "dns_sd.h" 34 | 35 | namespace ZeroConf 36 | { 37 | class NetServiceThread : public Thread 38 | { 39 | public: 40 | NetServiceThread(DNSServiceRef dnsServiceRef, double timeOutInSeconds); 41 | ~NetServiceThread(); 42 | 43 | virtual void run(); 44 | 45 | static bool poll1(DNSServiceRef dnsServiceRef, double timeOutInSeconds, DNSServiceErrorType &err); 46 | static bool poll(DNSServiceRef dnsServiceRef, double timeOutInSeconds, DNSServiceErrorType &err); 47 | 48 | private: 49 | DNSServiceRef mDNSServiceRef; 50 | double mTimeOut; 51 | }; 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /source/zeroconf/common/Thread.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #include "../common/Thread.h" 29 | #include 30 | 31 | using namespace ZeroConf; 32 | 33 | #ifdef WIN32 34 | 35 | #undef WIN32_LEAN_AND_MEAN 36 | #define WIN32_LEAN_AND_MEAN 1 37 | #define _WIN32_WINNT 0x0500 38 | #include 39 | #include 40 | 41 | static unsigned int __stdcall threadEntryPoint (void* userData) 42 | { 43 | Thread::threadEntryPoint((Thread*)userData); 44 | 45 | _endthreadex (0); 46 | return 0; 47 | } 48 | 49 | static void *createThread(void *pUser) 50 | { 51 | unsigned int threadId; 52 | 53 | return (void*) _beginthreadex (0, 0, &threadEntryPoint, pUser, 0, &threadId); 54 | } 55 | 56 | static void killThread(void *pHandle) 57 | { 58 | if (pHandle != 0) 59 | { 60 | TerminateThread (pHandle, 0); 61 | } 62 | } 63 | 64 | static void threadSleep(int ms) 65 | { 66 | Sleep(ms); 67 | } 68 | 69 | static void closeThread(void *pHandle) 70 | { 71 | CloseHandle ((HANDLE) pHandle); 72 | } 73 | 74 | #else 75 | 76 | static void *threadEntryPoint(void *pUser) 77 | { 78 | //const ScopedAutoReleasePool pool; 79 | Thread::threadEntryPoint((Thread*)pUser); 80 | return NULL; 81 | } 82 | 83 | static void *createThread(void *pUser) 84 | { 85 | pthread_t handle = 0; 86 | 87 | if (pthread_create (&handle, 0, threadEntryPoint, pUser) == 0) 88 | { 89 | pthread_detach (handle); 90 | return (void*) handle; 91 | } 92 | 93 | return 0; 94 | } 95 | 96 | static void killThread(void *pHandle) 97 | { 98 | if (pHandle != NULL) 99 | pthread_cancel ((pthread_t) pHandle); 100 | } 101 | 102 | static void threadSleep(int ms) 103 | { 104 | struct timespec time; 105 | time.tv_sec = ms / 1000; 106 | time.tv_nsec = (ms % 1000) * 1000000; 107 | nanosleep (&time, 0); 108 | } 109 | 110 | static void closeThread(void *pHandle) 111 | { 112 | // nothing to do on posix 113 | } 114 | 115 | #endif 116 | 117 | Thread::Thread() 118 | : mpThreadHandle(NULL) 119 | , mShouldExit(false) 120 | { 121 | } 122 | 123 | Thread::~Thread() 124 | { 125 | stopThread(100); 126 | } 127 | 128 | void Thread::startThread() 129 | { 130 | const ScopedLock lock(mCriticalSection); 131 | 132 | mShouldExit = false; 133 | if(mpThreadHandle == NULL) 134 | { 135 | mpThreadHandle = createThread(this); 136 | } 137 | } 138 | 139 | void Thread::stopThread(const int timeOut) 140 | { 141 | const ScopedLock lock(mCriticalSection); 142 | 143 | if(isThreadRunning()) 144 | { 145 | setThreadShouldExit(); 146 | // notify 147 | 148 | if(timeOut != 0) 149 | waitForThreadToExit(timeOut); 150 | 151 | if(isThreadRunning()) 152 | { 153 | killThread(mpThreadHandle); 154 | mpThreadHandle = NULL; 155 | } 156 | } 157 | } 158 | 159 | 160 | bool Thread::isThreadRunning() const 161 | { 162 | return mpThreadHandle != NULL; 163 | } 164 | 165 | bool Thread::threadShouldExit() const 166 | { 167 | return mShouldExit; 168 | } 169 | 170 | void Thread::setThreadShouldExit() 171 | { 172 | mShouldExit = true; 173 | } 174 | 175 | bool Thread::waitForThreadToExit(const int timeOut) 176 | { 177 | int count = timeOut; 178 | 179 | while (isThreadRunning()) { 180 | if(timeOut>0 && --count < 0) 181 | return false; 182 | 183 | sleep(1); 184 | } 185 | 186 | return true; 187 | } 188 | 189 | void Thread::sleep(int ms) 190 | { 191 | threadSleep(ms); 192 | } 193 | 194 | 195 | void Thread::threadEntryPoint(Thread *pThread) 196 | { 197 | pThread->run(); 198 | 199 | closeThread(pThread->mpThreadHandle); 200 | 201 | pThread->mpThreadHandle = NULL; 202 | } 203 | -------------------------------------------------------------------------------- /source/zeroconf/common/Thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | 29 | #ifndef ZeroConf_Thread_H 30 | #define ZeroConf_Thread_H 31 | 32 | #include "../common/CriticalSection.h" 33 | 34 | namespace ZeroConf 35 | { 36 | class Thread 37 | { 38 | public: 39 | Thread(); 40 | virtual ~Thread(); 41 | 42 | virtual void run() = 0; 43 | 44 | void startThread(); 45 | void stopThread(const int timeOut=-1); 46 | 47 | bool isThreadRunning() const; 48 | bool threadShouldExit() const; 49 | void setThreadShouldExit(); 50 | bool waitForThreadToExit(const int timeOut=-1); 51 | 52 | static void sleep(int ms); 53 | static void threadEntryPoint(Thread *pThread); 54 | 55 | private: 56 | void *mpThreadHandle; 57 | CriticalSection mCriticalSection; 58 | bool mShouldExit; 59 | }; 60 | } 61 | 62 | #endif -------------------------------------------------------------------------------- /source/zeroconf/common/VERSION.h: -------------------------------------------------------------------------------- 1 | // VERSION.h 2 | // zeroconf.browser 3 | // 4 | // 1.0.0, 2015-12-31: first proper build for Max 7 package manager. 5 | 6 | #ifndef VERSION_h 7 | #define VERSION "1.0.0" 8 | #define VERSION_h 9 | 10 | #endif /* VERSION_h */ 11 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_browser/zeroconf.browser.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2009 Remy Muller. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining 5 | a copy of this software and associated documentation files 6 | (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, 9 | and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | Any person wishing to distribute modifications to the Software is 16 | requested to send the modifications to the original developer so that 17 | they can be incorporated into the canonical version. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | 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 | #include "../common/VERSION.h" 29 | #include "ext.h" 30 | #include "ext_obex.h" 31 | #include "../common/NetServiceBrowser.h" 32 | #include "../common/NetService.h" 33 | #include "../common/NetServiceThread.h" 34 | #include 35 | #include 36 | #include 37 | 38 | using namespace ZeroConf; 39 | 40 | class Browser; 41 | 42 | struct zeroconf_browser 43 | { 44 | t_object ob; // the object itself (must be first) 45 | t_symbol *type; 46 | t_symbol *domain; 47 | void *out; 48 | Browser *mpBrowser; 49 | }; 50 | 51 | class Browser : public NetServiceBrowser, public NetServiceBrowserListener 52 | { 53 | zeroconf_browser *mpExternal; 54 | std::set mServices; 55 | CriticalSection mCriticalSection; // CriticalSection for shared access to mServices 56 | 57 | public: 58 | Browser(zeroconf_browser *x) 59 | : NetServiceBrowser() 60 | , mpExternal(x) 61 | { 62 | setListener(this); 63 | } 64 | 65 | void search(const std::string &type, const std::string &domain, bool launchThread) 66 | { 67 | if(!type.empty()) 68 | { 69 | stop(); 70 | { 71 | ScopedLock lock(mCriticalSection); 72 | mServices.clear(); 73 | } 74 | searchForServicesOfType(type, domain, launchThread); 75 | } 76 | } 77 | 78 | private: 79 | virtual void didFindDomain(NetServiceBrowser *pNetServiceBrowser, const std::string &domainName, bool moreDomainsComing) { } 80 | virtual void didRemoveDomain(NetServiceBrowser *pNetServiceBrowser, const std::string &domainName, bool moreDomainsComing) { } 81 | 82 | void outputListOfServices() 83 | { 84 | t_atom at[1]; 85 | outlet_anything(mpExternal->out, gensym("clear"), 0, NULL); 86 | 87 | ScopedLock lock(mCriticalSection); 88 | for(std::set::iterator it=mServices.begin(); it != mServices.end(); ++it) 89 | { 90 | atom_setsym(at, gensym(const_cast(it->c_str()))); 91 | outlet_anything(mpExternal->out, gensym("append"), 1, at); 92 | } 93 | } 94 | 95 | virtual void didFindService(NetServiceBrowser* pNetServiceBrowser, NetService *pNetService, bool moreServicesComing) 96 | { 97 | { 98 | ScopedLock lock(mCriticalSection); 99 | mServices.insert(pNetService->getName()); 100 | } 101 | 102 | if(!moreServicesComing) 103 | outputListOfServices(); 104 | } 105 | 106 | virtual void didRemoveService(NetServiceBrowser *pNetServiceBrowser, NetService *pNetService, bool moreServicesComing) 107 | { 108 | bool erased = false; 109 | { 110 | std::set::iterator it = mServices.find(pNetService->getName()); 111 | if(it != mServices.end()) 112 | { 113 | erased = true; 114 | ScopedLock lock(mCriticalSection); 115 | mServices.erase(it); 116 | } 117 | } 118 | 119 | //if(!moreServicesComing) // doesn't seem to be ever set to false 120 | if(erased) 121 | outputListOfServices(); 122 | } 123 | 124 | virtual void willSearch(NetServiceBrowser *pNetServiceBrowser) { } 125 | virtual void didNotSearch(NetServiceBrowser *pNetServiceBrowser) { } 126 | virtual void didStopSearch(NetServiceBrowser *pNetServiceBrowser) { } 127 | }; 128 | 129 | //------------------------------------------------------------------------------ 130 | t_class *zeroconf_browser_class; 131 | 132 | void zeroconf_browser_poll(zeroconf_browser *x, t_symbol *sym, short argc, t_atom *arv) 133 | { 134 | // poll for results 135 | if(x->mpBrowser->getDNSServiceRef()) 136 | { 137 | DNSServiceErrorType err = kDNSServiceErr_NoError; 138 | if(NetServiceThread::poll(x->mpBrowser->getDNSServiceRef(), 0.001, err) && err > 0) 139 | { 140 | object_post((t_object*)x, "error %d", err); 141 | x->mpBrowser->stop(); 142 | } 143 | else if(x->mpBrowser->getDNSServiceRef()) // we check again, because it might have change in reaction to a callback 144 | { 145 | schedule_defer(x, (method)zeroconf_browser_poll, 1000, NULL, 0, NULL); // reschedule in 1 sec 146 | } 147 | } 148 | } 149 | 150 | void zeroconf_browser_bang(zeroconf_browser *x) 151 | { 152 | x->mpBrowser->search(x->type->s_name, x->domain->s_name, false); 153 | 154 | schedule_defer(x, (method)zeroconf_browser_poll, 1000, NULL, 0, NULL); 155 | } 156 | 157 | void zeroconf_browser_browse(zeroconf_browser *x, t_symbol *s, long argc, t_atom *argv) 158 | { 159 | bool valid = false; 160 | switch(argc) 161 | { 162 | case 2: 163 | if(argv[1].a_type == A_SYM) 164 | { 165 | x->domain = atom_getsym(argv+1); 166 | } 167 | case 1: 168 | if(argv[0].a_type == A_SYM) 169 | { 170 | valid = true; 171 | x->type = atom_getsym(argv+0); 172 | } 173 | default: 174 | break; 175 | } 176 | 177 | if(valid) 178 | zeroconf_browser_bang(x); 179 | } 180 | 181 | void zeroconf_browser_assist(zeroconf_browser *x, void *b, long m, long a, char *s) 182 | { 183 | if (m == ASSIST_INLET) 184 | { 185 | sprintf(s, "I am inlet %ld", a); 186 | } 187 | else 188 | { 189 | sprintf(s, "I am outlet %ld", a); 190 | } 191 | } 192 | 193 | void zeroconf_browser_free(zeroconf_browser *x) 194 | { 195 | if(x->mpBrowser) 196 | { 197 | delete x->mpBrowser; 198 | } 199 | } 200 | 201 | void *zeroconf_browser_new(t_symbol *s, long argc, t_atom *argv) 202 | { 203 | zeroconf_browser *x = NULL; 204 | 205 | if ((x = (zeroconf_browser *)object_alloc(zeroconf_browser_class))) 206 | { 207 | x->out = outlet_new(x, NULL); 208 | x->type = gensym(""); 209 | x->domain = gensym("local."); 210 | x->mpBrowser = new Browser(x); 211 | attr_args_process(x, argc, argv); 212 | 213 | zeroconf_browser_bang(x); 214 | } 215 | return (x); 216 | } 217 | 218 | void ext_main(void *r) 219 | { 220 | t_class *c = class_new("zeroconf.browser", (method)zeroconf_browser_new, (method)zeroconf_browser_free, (long)sizeof(zeroconf_browser), 0L, A_GIMME, 0); 221 | 222 | class_addmethod(c, (method)zeroconf_browser_bang, "bang", 0); 223 | class_addmethod(c, (method)zeroconf_browser_browse, "browse", A_GIMME, 0); 224 | class_addmethod(c, (method)zeroconf_browser_assist, "assist", A_CANT, 0); 225 | 226 | CLASS_ATTR_SYM(c, "type", 0, zeroconf_browser, type); 227 | CLASS_ATTR_SYM(c, "domain", 0, zeroconf_browser, domain); 228 | 229 | class_register(CLASS_BOX, c); /* CLASS_NOBOX */ 230 | zeroconf_browser_class = c; 231 | 232 | post("| zeroconf.browser - code by Remy Muller"); 233 | post("| This maintenance release by Nick Rothwell, nick@cassiel.com"); 234 | post("| zeroconf suite version: %s", VERSION); 235 | } 236 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_browser/zeroconf.browser.def: -------------------------------------------------------------------------------- 1 | LIBRARY zeroconf.browser.mxe 2 | 3 | EXPORTS 4 | main 5 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_browser/zeroconf.browser.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroconf.browser", "zeroconf.browser.vcproj", "{73069FC3-D989-47DB-B15F-625703EED4DA}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.Build.0 = Debug|Win32 14 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.ActiveCfg = Release|Win32 15 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_browser/zeroconf.browser.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 28 | 31 | 34 | 37 | 40 | 51 | 70 | 73 | 78 | 81 | 98 | 101 | 104 | 107 | 110 | 113 | 116 | 120 | 121 | 132 | 135 | 138 | 141 | 144 | 155 | 174 | 177 | 182 | 185 | 203 | 206 | 209 | 212 | 215 | 218 | 221 | 225 | 226 | 227 | 228 | 229 | 230 | 234 | 237 | 238 | 241 | 242 | 243 | 247 | 248 | 251 | 254 | 255 | 258 | 259 | 262 | 263 | 266 | 267 | 270 | 271 | 274 | 275 | 278 | 279 | 282 | 283 | 286 | 287 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_browser/zeroconf.browser.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742311C35ADE80043014A /* CriticalSection.cpp */; }; 11 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742321C35ADE80043014A /* NetService.cpp */; }; 12 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */; }; 13 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742341C35ADE80043014A /* NetServiceThread.cpp */; }; 14 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742351C35ADE80043014A /* Thread.cpp */; }; 15 | 222B12E90F140BDF008B1A46 /* zeroconf.browser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 222B12E80F140BDF008B1A46 /* zeroconf.browser.cpp */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 01B742311C35ADE80043014A /* CriticalSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CriticalSection.cpp; path = ../common/CriticalSection.cpp; sourceTree = ""; }; 20 | 01B742321C35ADE80043014A /* NetService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetService.cpp; path = ../common/NetService.cpp; sourceTree = ""; }; 21 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceBrowser.cpp; path = ../common/NetServiceBrowser.cpp; sourceTree = ""; }; 22 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceThread.cpp; path = ../common/NetServiceThread.cpp; sourceTree = ""; }; 23 | 01B742351C35ADE80043014A /* Thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Thread.cpp; path = ../common/Thread.cpp; sourceTree = ""; }; 24 | 222B12E80F140BDF008B1A46 /* zeroconf.browser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zeroconf.browser.cpp; sourceTree = ""; }; 25 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = maxmspsdk.xcconfig; path = ../../maxmspsdk.xcconfig; sourceTree = SOURCE_ROOT; }; 26 | 2FBBEAE508F335360078DB84 /* zeroconf.browser.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = zeroconf.browser.mxo; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 2FBBEADC08F335360078DB84 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 089C166AFE841209C02AAC07 /* iterator */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */, 44 | 222B12E80F140BDF008B1A46 /* zeroconf.browser.cpp */, 45 | 01B742311C35ADE80043014A /* CriticalSection.cpp */, 46 | 01B742321C35ADE80043014A /* NetService.cpp */, 47 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */, 48 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */, 49 | 01B742351C35ADE80043014A /* Thread.cpp */, 50 | 19C28FB4FE9D528D11CA2CBB /* Products */, 51 | ); 52 | name = iterator; 53 | sourceTree = ""; 54 | }; 55 | 19C28FB4FE9D528D11CA2CBB /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 2FBBEAE508F335360078DB84 /* zeroconf.browser.mxo */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | /* End PBXGroup section */ 64 | 65 | /* Begin PBXHeadersBuildPhase section */ 66 | 2FBBEAD708F335360078DB84 /* Headers */ = { 67 | isa = PBXHeadersBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXHeadersBuildPhase section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | 2FBBEAD608F335360078DB84 /* max-external */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */; 79 | buildPhases = ( 80 | 2FBBEAD708F335360078DB84 /* Headers */, 81 | 2FBBEAD808F335360078DB84 /* Resources */, 82 | 2FBBEADA08F335360078DB84 /* Sources */, 83 | 2FBBEADC08F335360078DB84 /* Frameworks */, 84 | 2FBBEADF08F335360078DB84 /* Rez */, 85 | ); 86 | buildRules = ( 87 | ); 88 | dependencies = ( 89 | ); 90 | name = "max-external"; 91 | productName = iterator; 92 | productReference = 2FBBEAE508F335360078DB84 /* zeroconf.browser.mxo */; 93 | productType = "com.apple.product-type.bundle"; 94 | }; 95 | /* End PBXNativeTarget section */ 96 | 97 | /* Begin PBXProject section */ 98 | 089C1669FE841209C02AAC07 /* Project object */ = { 99 | isa = PBXProject; 100 | attributes = { 101 | LastUpgradeCheck = 0610; 102 | }; 103 | buildConfigurationList = 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.browser" */; 104 | compatibilityVersion = "Xcode 3.2"; 105 | developmentRegion = English; 106 | hasScannedForEncodings = 1; 107 | knownRegions = ( 108 | en, 109 | ); 110 | mainGroup = 089C166AFE841209C02AAC07 /* iterator */; 111 | projectDirPath = ""; 112 | projectRoot = ""; 113 | targets = ( 114 | 2FBBEAD608F335360078DB84 /* max-external */, 115 | ); 116 | }; 117 | /* End PBXProject section */ 118 | 119 | /* Begin PBXResourcesBuildPhase section */ 120 | 2FBBEAD808F335360078DB84 /* Resources */ = { 121 | isa = PBXResourcesBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXResourcesBuildPhase section */ 128 | 129 | /* Begin PBXRezBuildPhase section */ 130 | 2FBBEADF08F335360078DB84 /* Rez */ = { 131 | isa = PBXRezBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXRezBuildPhase section */ 138 | 139 | /* Begin PBXSourcesBuildPhase section */ 140 | 2FBBEADA08F335360078DB84 /* Sources */ = { 141 | isa = PBXSourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */, 145 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */, 146 | 222B12E90F140BDF008B1A46 /* zeroconf.browser.cpp in Sources */, 147 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */, 148 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */, 149 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXSourcesBuildPhase section */ 154 | 155 | /* Begin XCBuildConfiguration section */ 156 | 2FBBEAD008F335010078DB84 /* Development */ = { 157 | isa = XCBuildConfiguration; 158 | buildSettings = { 159 | }; 160 | name = Development; 161 | }; 162 | 2FBBEAD108F335010078DB84 /* Deployment */ = { 163 | isa = XCBuildConfiguration; 164 | buildSettings = { 165 | }; 166 | name = Deployment; 167 | }; 168 | 2FBBEAE108F335360078DB84 /* Development */ = { 169 | isa = XCBuildConfiguration; 170 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 171 | buildSettings = { 172 | COPY_PHASE_STRIP = NO; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 175 | }; 176 | name = Development; 177 | }; 178 | 2FBBEAE208F335360078DB84 /* Deployment */ = { 179 | isa = XCBuildConfiguration; 180 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 181 | buildSettings = { 182 | COPY_PHASE_STRIP = YES; 183 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 184 | }; 185 | name = Deployment; 186 | }; 187 | /* End XCBuildConfiguration section */ 188 | 189 | /* Begin XCConfigurationList section */ 190 | 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.browser" */ = { 191 | isa = XCConfigurationList; 192 | buildConfigurations = ( 193 | 2FBBEAD008F335010078DB84 /* Development */, 194 | 2FBBEAD108F335010078DB84 /* Deployment */, 195 | ); 196 | defaultConfigurationIsVisible = 0; 197 | defaultConfigurationName = Development; 198 | }; 199 | 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */ = { 200 | isa = XCConfigurationList; 201 | buildConfigurations = ( 202 | 2FBBEAE108F335360078DB84 /* Development */, 203 | 2FBBEAE208F335360078DB84 /* Deployment */, 204 | ); 205 | defaultConfigurationIsVisible = 0; 206 | defaultConfigurationName = Development; 207 | }; 208 | /* End XCConfigurationList section */ 209 | }; 210 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 211 | } 212 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_resolve/zeroconf.resolve.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | 4 | #include "../common/VERSION.h" 5 | #include "ext.h" 6 | #include "ext_obex.h" 7 | #include "../common/NetService.h" 8 | #include "../common/NetServiceThread.h" 9 | #include 10 | 11 | using namespace ZeroConf; 12 | 13 | class Service; 14 | 15 | struct zeroconf_resolve 16 | { 17 | t_object ob; // the object itself (must be first) 18 | t_symbol *name; 19 | t_symbol *type; 20 | t_symbol *domain; 21 | void *out; 22 | Service *mpService; 23 | }; 24 | 25 | class Service : public NetService, NetServiceListener 26 | { 27 | zeroconf_resolve *mpExternal; 28 | 29 | public: 30 | Service(const std::string &domain, 31 | const std::string &type, 32 | const std::string &name, 33 | zeroconf_resolve *x) 34 | : NetService(domain, type, name) 35 | , mpExternal(x) 36 | { 37 | setListener(this); 38 | } 39 | 40 | virtual void willPublish(NetService *pNetService) {} 41 | virtual void didNotPublish(NetService *pNetService) {} 42 | virtual void didPublish(NetService *pNetService) {} 43 | virtual void willResolve(NetService *pNetService) {} 44 | virtual void didNotResolve(NetService *NetService) 45 | { 46 | object_post((t_object *)mpExternal, "didNotResolve" ); 47 | } 48 | virtual void didResolveAddress(NetService *pNetService) 49 | { 50 | t_atom at[1]; 51 | 52 | atom_setsym(at,gensym(const_cast(pNetService->getHostName().c_str()))); 53 | outlet_anything(mpExternal->out, gensym("host"), 1, at); 54 | 55 | atom_setlong(at, pNetService->getPort()); 56 | outlet_anything(mpExternal->out, gensym("port"), 1, at); 57 | } 58 | virtual void didUpdateTXTRecordData(NetService *pNetService) {} 59 | virtual void didStop(NetService *pNetService) {} 60 | }; 61 | 62 | //------------------------------------------------------------------------------ 63 | t_class *zeroconf_resolve_class; 64 | 65 | void zeroconf_resolve_poll(zeroconf_resolve *x, t_symbol *sym, short argc, t_atom *arv) 66 | { 67 | // poll for results 68 | if(x->mpService && x->mpService->getDNSServiceRef()) 69 | { 70 | DNSServiceErrorType err = kDNSServiceErr_NoError; 71 | if(NetServiceThread::poll(x->mpService->getDNSServiceRef(), 0.001, err)) 72 | { 73 | if(err > 0) 74 | object_post((t_object*)x, "error %d", err); 75 | x->mpService->stop(); 76 | } 77 | } 78 | 79 | if(x->mpService && x->mpService->getDNSServiceRef()) // we check again, because it might have change in reaction to a callback 80 | { 81 | schedule_defer(x, (method)zeroconf_resolve_poll, 1000, NULL, 0, NULL); // reschedule in 1 sec 82 | } 83 | } 84 | 85 | void zeroconf_resolve_bang(zeroconf_resolve *x) 86 | { 87 | if(x->mpService) 88 | delete x->mpService; 89 | x->mpService = NULL; 90 | 91 | x->mpService = new Service(x->domain->s_name, 92 | x->type->s_name, 93 | x->name->s_name, 94 | x); 95 | x->mpService->resolveWithTimeout(10.0, false); 96 | 97 | schedule_defer(x, (method)zeroconf_resolve_poll, 1000, NULL, 0, NULL); // reschedule in 1 sec 98 | } 99 | 100 | void zeroconf_resolve_assist(zeroconf_resolve *x, void *b, long m, long a, char *s) 101 | { 102 | if (m == ASSIST_INLET) 103 | { 104 | sprintf(s, "I am inlet %ld", a); 105 | } 106 | else 107 | { 108 | sprintf(s, "I am outlet %ld", a); 109 | } 110 | } 111 | 112 | void zeroconf_resolve_free(zeroconf_resolve *x) 113 | { 114 | if(x->mpService) 115 | { 116 | delete x->mpService; 117 | } 118 | } 119 | 120 | void *zeroconf_resolve_new(t_symbol *s, long argc, t_atom *argv) 121 | { 122 | zeroconf_resolve *x = NULL; 123 | 124 | if ((x = (zeroconf_resolve *)object_alloc(zeroconf_resolve_class))) 125 | { 126 | x->mpService = NULL; 127 | x->name = gensym(""); 128 | x->type = gensym(""); 129 | x->domain = gensym("local."); 130 | x->out = outlet_new(x, NULL); 131 | attr_args_process(x, argc, argv); 132 | 133 | zeroconf_resolve_bang(x); 134 | } 135 | return (x); 136 | } 137 | 138 | void ext_main(void *r) 139 | { 140 | t_class *c = class_new("zeroconf.resolve", (method)zeroconf_resolve_new, (method)zeroconf_resolve_free, (long)sizeof(zeroconf_resolve), 0L, A_GIMME, 0); 141 | 142 | class_addmethod(c, (method)zeroconf_resolve_bang, "bang", 0); 143 | class_addmethod(c, (method)zeroconf_resolve_assist, "assist", A_CANT, 0); 144 | 145 | CLASS_ATTR_SYM(c, "name", 0, zeroconf_resolve, name); 146 | CLASS_ATTR_SYM(c, "type", 0, zeroconf_resolve, type); 147 | CLASS_ATTR_SYM(c, "domain", 0, zeroconf_resolve, domain); 148 | 149 | class_register(CLASS_BOX, c); /* CLASS_NOBOX */ 150 | zeroconf_resolve_class = c; 151 | 152 | post("| zeroconf.resolve - code by Remy Muller"); 153 | post("| This maintenance release by Nick Rothwell, nick@cassiel.com"); 154 | post("| zeroconf suite version: %s", VERSION); 155 | } 156 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_resolve/zeroconf.resolve.def: -------------------------------------------------------------------------------- 1 | LIBRARY zeroconf.resolve.mxe 2 | 3 | EXPORTS 4 | main 5 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_resolve/zeroconf.resolve.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroconf.resolve", "zeroconf.resolve.vcproj", "{73069FC3-D989-47DB-B15F-625703EED4DA}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.Build.0 = Debug|Win32 14 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.ActiveCfg = Release|Win32 15 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_resolve/zeroconf.resolve.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 28 | 31 | 34 | 37 | 40 | 51 | 70 | 73 | 78 | 81 | 98 | 101 | 104 | 107 | 110 | 113 | 116 | 120 | 121 | 132 | 135 | 138 | 141 | 144 | 155 | 174 | 177 | 182 | 185 | 203 | 206 | 209 | 212 | 215 | 218 | 221 | 225 | 226 | 227 | 228 | 229 | 230 | 234 | 237 | 238 | 241 | 242 | 243 | 247 | 248 | 251 | 254 | 255 | 258 | 259 | 262 | 263 | 266 | 267 | 270 | 271 | 274 | 275 | 278 | 279 | 282 | 283 | 286 | 287 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_resolve/zeroconf.resolve.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742311C35ADE80043014A /* CriticalSection.cpp */; }; 11 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742321C35ADE80043014A /* NetService.cpp */; }; 12 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */; }; 13 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742341C35ADE80043014A /* NetServiceThread.cpp */; }; 14 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742351C35ADE80043014A /* Thread.cpp */; }; 15 | 222B12E90F140BDF008B1A46 /* zeroconf.resolve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 222B12E80F140BDF008B1A46 /* zeroconf.resolve.cpp */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 01B742311C35ADE80043014A /* CriticalSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CriticalSection.cpp; path = ../common/CriticalSection.cpp; sourceTree = ""; }; 20 | 01B742321C35ADE80043014A /* NetService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetService.cpp; path = ../common/NetService.cpp; sourceTree = ""; }; 21 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceBrowser.cpp; path = ../common/NetServiceBrowser.cpp; sourceTree = ""; }; 22 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceThread.cpp; path = ../common/NetServiceThread.cpp; sourceTree = ""; }; 23 | 01B742351C35ADE80043014A /* Thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Thread.cpp; path = ../common/Thread.cpp; sourceTree = ""; }; 24 | 222B12E80F140BDF008B1A46 /* zeroconf.resolve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zeroconf.resolve.cpp; sourceTree = ""; }; 25 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = maxmspsdk.xcconfig; path = ../../maxmspsdk.xcconfig; sourceTree = SOURCE_ROOT; }; 26 | 2FBBEAE508F335360078DB84 /* zeroconf.resolve.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = zeroconf.resolve.mxo; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 2FBBEADC08F335360078DB84 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 089C166AFE841209C02AAC07 /* iterator */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */, 44 | 222B12E80F140BDF008B1A46 /* zeroconf.resolve.cpp */, 45 | 01B742311C35ADE80043014A /* CriticalSection.cpp */, 46 | 01B742321C35ADE80043014A /* NetService.cpp */, 47 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */, 48 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */, 49 | 01B742351C35ADE80043014A /* Thread.cpp */, 50 | 19C28FB4FE9D528D11CA2CBB /* Products */, 51 | ); 52 | name = iterator; 53 | sourceTree = ""; 54 | }; 55 | 19C28FB4FE9D528D11CA2CBB /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 2FBBEAE508F335360078DB84 /* zeroconf.resolve.mxo */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | /* End PBXGroup section */ 64 | 65 | /* Begin PBXHeadersBuildPhase section */ 66 | 2FBBEAD708F335360078DB84 /* Headers */ = { 67 | isa = PBXHeadersBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXHeadersBuildPhase section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | 2FBBEAD608F335360078DB84 /* max-external */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */; 79 | buildPhases = ( 80 | 2FBBEAD708F335360078DB84 /* Headers */, 81 | 2FBBEAD808F335360078DB84 /* Resources */, 82 | 2FBBEADA08F335360078DB84 /* Sources */, 83 | 2FBBEADC08F335360078DB84 /* Frameworks */, 84 | 2FBBEADF08F335360078DB84 /* Rez */, 85 | ); 86 | buildRules = ( 87 | ); 88 | dependencies = ( 89 | ); 90 | name = "max-external"; 91 | productName = iterator; 92 | productReference = 2FBBEAE508F335360078DB84 /* zeroconf.resolve.mxo */; 93 | productType = "com.apple.product-type.bundle"; 94 | }; 95 | /* End PBXNativeTarget section */ 96 | 97 | /* Begin PBXProject section */ 98 | 089C1669FE841209C02AAC07 /* Project object */ = { 99 | isa = PBXProject; 100 | attributes = { 101 | LastUpgradeCheck = 0610; 102 | }; 103 | buildConfigurationList = 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.resolve" */; 104 | compatibilityVersion = "Xcode 3.2"; 105 | developmentRegion = English; 106 | hasScannedForEncodings = 1; 107 | knownRegions = ( 108 | en, 109 | ); 110 | mainGroup = 089C166AFE841209C02AAC07 /* iterator */; 111 | projectDirPath = ""; 112 | projectRoot = ""; 113 | targets = ( 114 | 2FBBEAD608F335360078DB84 /* max-external */, 115 | ); 116 | }; 117 | /* End PBXProject section */ 118 | 119 | /* Begin PBXResourcesBuildPhase section */ 120 | 2FBBEAD808F335360078DB84 /* Resources */ = { 121 | isa = PBXResourcesBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXResourcesBuildPhase section */ 128 | 129 | /* Begin PBXRezBuildPhase section */ 130 | 2FBBEADF08F335360078DB84 /* Rez */ = { 131 | isa = PBXRezBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXRezBuildPhase section */ 138 | 139 | /* Begin PBXSourcesBuildPhase section */ 140 | 2FBBEADA08F335360078DB84 /* Sources */ = { 141 | isa = PBXSourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */, 145 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */, 146 | 222B12E90F140BDF008B1A46 /* zeroconf.resolve.cpp in Sources */, 147 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */, 148 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */, 149 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXSourcesBuildPhase section */ 154 | 155 | /* Begin XCBuildConfiguration section */ 156 | 2FBBEAD008F335010078DB84 /* Development */ = { 157 | isa = XCBuildConfiguration; 158 | buildSettings = { 159 | }; 160 | name = Development; 161 | }; 162 | 2FBBEAD108F335010078DB84 /* Deployment */ = { 163 | isa = XCBuildConfiguration; 164 | buildSettings = { 165 | }; 166 | name = Deployment; 167 | }; 168 | 2FBBEAE108F335360078DB84 /* Development */ = { 169 | isa = XCBuildConfiguration; 170 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 171 | buildSettings = { 172 | COPY_PHASE_STRIP = NO; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 175 | }; 176 | name = Development; 177 | }; 178 | 2FBBEAE208F335360078DB84 /* Deployment */ = { 179 | isa = XCBuildConfiguration; 180 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 181 | buildSettings = { 182 | COPY_PHASE_STRIP = YES; 183 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 184 | }; 185 | name = Deployment; 186 | }; 187 | /* End XCBuildConfiguration section */ 188 | 189 | /* Begin XCConfigurationList section */ 190 | 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.resolve" */ = { 191 | isa = XCConfigurationList; 192 | buildConfigurations = ( 193 | 2FBBEAD008F335010078DB84 /* Development */, 194 | 2FBBEAD108F335010078DB84 /* Deployment */, 195 | ); 196 | defaultConfigurationIsVisible = 0; 197 | defaultConfigurationName = Development; 198 | }; 199 | 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */ = { 200 | isa = XCConfigurationList; 201 | buildConfigurations = ( 202 | 2FBBEAE108F335360078DB84 /* Development */, 203 | 2FBBEAE208F335360078DB84 /* Deployment */, 204 | ); 205 | defaultConfigurationIsVisible = 0; 206 | defaultConfigurationName = Development; 207 | }; 208 | /* End XCConfigurationList section */ 209 | }; 210 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 211 | } 212 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_service/zeroconf.service.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | */ 3 | 4 | #include "../common/VERSION.h" 5 | #include "ext.h" 6 | #include "ext_obex.h" 7 | #include "../common/NetService.h" 8 | #include "../common/NetServiceThread.h" 9 | #include 10 | 11 | using namespace ZeroConf; 12 | 13 | class Service; 14 | 15 | struct zeroconf_service 16 | { 17 | t_object ob; // the object itself (must be first) 18 | t_symbol *name; 19 | t_symbol *type; 20 | t_symbol *domain; 21 | long port; 22 | Service *mpService; 23 | }; 24 | 25 | class Service : public NetService, public NetServiceListener 26 | { 27 | zeroconf_service *mpExternal; 28 | public: 29 | Service(const std::string &domain, 30 | const std::string &type, 31 | const std::string &name, 32 | const int port, 33 | zeroconf_service *x) 34 | : NetService(domain, type, name, port) 35 | , mpExternal(x) 36 | { 37 | setListener(this); 38 | } 39 | 40 | private: 41 | virtual void willPublish(NetService *pNetService) {} 42 | virtual void didNotPublish(NetService *pNetService) { object_post((t_object *)mpExternal, "didNotPublish" ); } 43 | virtual void didPublish(NetService *pNetService) 44 | { 45 | object_post((t_object *)mpExternal, "Service published: %s %d", pNetService->getName().c_str(), pNetService->getPort()); 46 | } 47 | 48 | virtual void willResolve(NetService *pNetService) {} 49 | virtual void didNotResolve(NetService *NetService) {} 50 | virtual void didResolveAddress(NetService *pNetService) {} 51 | virtual void didUpdateTXTRecordData(NetService *pNetService) {} 52 | virtual void didStop(NetService *pNetService) {} 53 | }; 54 | 55 | //------------------------------------------------------------------------------ 56 | t_class *zeroconf_service_class; 57 | 58 | void zeroconf_service_poll(zeroconf_service *x, t_symbol *sym, short argc, t_atom *arv) 59 | { 60 | // poll for results 61 | if(x->mpService && x->mpService->getDNSServiceRef()) 62 | { 63 | DNSServiceErrorType err = kDNSServiceErr_NoError; 64 | if(NetServiceThread::poll(x->mpService->getDNSServiceRef(), 0.001, err)) 65 | { 66 | if(err > 0) 67 | { 68 | x->mpService->stop(); 69 | object_post((t_object*)x, "error %d", err); 70 | } 71 | } 72 | else 73 | { 74 | if(x->mpService && x->mpService->getDNSServiceRef()) // we check again, because it might have change in reaction to a callback 75 | { 76 | schedule_defer(x, (method)zeroconf_service_poll, 1000, NULL, 0, NULL); // reschedule in 1 sec 77 | } 78 | } 79 | } 80 | } 81 | 82 | void zeroconf_service_bang(zeroconf_service *x) 83 | { 84 | if(x->mpService) 85 | { 86 | delete x->mpService; 87 | x->mpService = NULL; 88 | } 89 | 90 | x->mpService = new Service(x->domain->s_name, 91 | x->type->s_name, 92 | x->name->s_name, 93 | x->port, 94 | x); 95 | x->mpService->publish(false); 96 | 97 | schedule_defer(x, (method)zeroconf_service_poll, 1000, NULL, 0, NULL); // reschedule in 1 sec 98 | } 99 | 100 | void zeroconf_service_assist(zeroconf_service *x, void *b, long m, long a, char *s) 101 | { 102 | if (m == ASSIST_INLET) 103 | { 104 | sprintf(s, "I am inlet %ld", a); 105 | } 106 | else 107 | { 108 | sprintf(s, "I am outlet %ld", a); 109 | } 110 | } 111 | 112 | void zeroconf_service_free(zeroconf_service *x) 113 | { 114 | if(x->mpService) 115 | { 116 | delete x->mpService; 117 | } 118 | } 119 | 120 | void *zeroconf_service_new(t_symbol *s, long argc, t_atom *argv) 121 | { 122 | zeroconf_service *x = NULL; 123 | 124 | if ((x = (zeroconf_service *)object_alloc(zeroconf_service_class))) 125 | { 126 | x->mpService = NULL; 127 | x->name = gensym(""); 128 | x->type = gensym(""); 129 | x->domain = gensym(""); 130 | x->port = 0; 131 | attr_args_process(x, argc, argv); 132 | 133 | zeroconf_service_bang(x); 134 | } 135 | 136 | return (x); 137 | } 138 | 139 | void ext_main(void *r) 140 | { 141 | t_class *c = class_new("zeroconf.service", (method)zeroconf_service_new, (method)zeroconf_service_free, (long)sizeof(zeroconf_service), 0L, A_GIMME, 0); 142 | 143 | class_addmethod(c, (method)zeroconf_service_bang, "bang", 0); 144 | class_addmethod(c, (method)zeroconf_service_assist, "assist", A_CANT, 0); 145 | 146 | CLASS_ATTR_SYM(c, "name", 0, zeroconf_service, name); 147 | CLASS_ATTR_SYM(c, "type", 0, zeroconf_service, type); 148 | CLASS_ATTR_SYM(c, "domain", 0, zeroconf_service, domain); 149 | CLASS_ATTR_LONG(c, "port", 0, zeroconf_service, port); 150 | 151 | class_register(CLASS_BOX, c); /* CLASS_NOBOX */ 152 | zeroconf_service_class = c; 153 | 154 | post("| zeroconf.service - code by Remy Muller"); 155 | post("| This maintenance release by Nick Rothwell, nick@cassiel.com"); 156 | post("| zeroconf suite version: %s", VERSION); 157 | } 158 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_service/zeroconf.service.def: -------------------------------------------------------------------------------- 1 | LIBRARY zeroconf.service.mxe 2 | 3 | EXPORTS 4 | main 5 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_service/zeroconf.service.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroconf", "zeroconf.service.vcproj", "{73069FC3-D989-47DB-B15F-625703EED4DA}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Debug|Win32.Build.0 = Debug|Win32 14 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.ActiveCfg = Release|Win32 15 | {73069FC3-D989-47DB-B15F-625703EED4DA}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_service/zeroconf.service.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 28 | 31 | 34 | 37 | 40 | 51 | 70 | 73 | 78 | 81 | 98 | 101 | 104 | 107 | 110 | 113 | 116 | 120 | 121 | 132 | 135 | 138 | 141 | 144 | 155 | 174 | 177 | 182 | 185 | 203 | 206 | 209 | 212 | 215 | 218 | 221 | 225 | 226 | 227 | 228 | 229 | 230 | 234 | 237 | 238 | 241 | 242 | 243 | 247 | 248 | 251 | 254 | 255 | 258 | 259 | 262 | 263 | 266 | 267 | 270 | 271 | 274 | 275 | 278 | 279 | 282 | 283 | 286 | 287 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /source/zeroconf/zeroconf_service/zeroconf.service.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742311C35ADE80043014A /* CriticalSection.cpp */; }; 11 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742321C35ADE80043014A /* NetService.cpp */; }; 12 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */; }; 13 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742341C35ADE80043014A /* NetServiceThread.cpp */; }; 14 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B742351C35ADE80043014A /* Thread.cpp */; }; 15 | 222B12E90F140BDF008B1A46 /* zeroconf.service.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 222B12E80F140BDF008B1A46 /* zeroconf.service.cpp */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 01B742311C35ADE80043014A /* CriticalSection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CriticalSection.cpp; path = ../common/CriticalSection.cpp; sourceTree = ""; }; 20 | 01B742321C35ADE80043014A /* NetService.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetService.cpp; path = ../common/NetService.cpp; sourceTree = ""; }; 21 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceBrowser.cpp; path = ../common/NetServiceBrowser.cpp; sourceTree = ""; }; 22 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetServiceThread.cpp; path = ../common/NetServiceThread.cpp; sourceTree = ""; }; 23 | 01B742351C35ADE80043014A /* Thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Thread.cpp; path = ../common/Thread.cpp; sourceTree = ""; }; 24 | 222B12E80F140BDF008B1A46 /* zeroconf.service.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zeroconf.service.cpp; sourceTree = ""; }; 25 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = maxmspsdk.xcconfig; path = ../../maxmspsdk.xcconfig; sourceTree = SOURCE_ROOT; }; 26 | 2FBBEAE508F335360078DB84 /* zeroconf.service.mxo */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = zeroconf.service.mxo; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 2FBBEADC08F335360078DB84 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 089C166AFE841209C02AAC07 /* iterator */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */, 44 | 222B12E80F140BDF008B1A46 /* zeroconf.service.cpp */, 45 | 01B742311C35ADE80043014A /* CriticalSection.cpp */, 46 | 01B742321C35ADE80043014A /* NetService.cpp */, 47 | 01B742331C35ADE80043014A /* NetServiceBrowser.cpp */, 48 | 01B742341C35ADE80043014A /* NetServiceThread.cpp */, 49 | 01B742351C35ADE80043014A /* Thread.cpp */, 50 | 19C28FB4FE9D528D11CA2CBB /* Products */, 51 | ); 52 | name = iterator; 53 | sourceTree = ""; 54 | }; 55 | 19C28FB4FE9D528D11CA2CBB /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 2FBBEAE508F335360078DB84 /* zeroconf.service.mxo */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | /* End PBXGroup section */ 64 | 65 | /* Begin PBXHeadersBuildPhase section */ 66 | 2FBBEAD708F335360078DB84 /* Headers */ = { 67 | isa = PBXHeadersBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXHeadersBuildPhase section */ 74 | 75 | /* Begin PBXNativeTarget section */ 76 | 2FBBEAD608F335360078DB84 /* max-external */ = { 77 | isa = PBXNativeTarget; 78 | buildConfigurationList = 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */; 79 | buildPhases = ( 80 | 2FBBEAD708F335360078DB84 /* Headers */, 81 | 2FBBEAD808F335360078DB84 /* Resources */, 82 | 2FBBEADA08F335360078DB84 /* Sources */, 83 | 2FBBEADC08F335360078DB84 /* Frameworks */, 84 | 2FBBEADF08F335360078DB84 /* Rez */, 85 | ); 86 | buildRules = ( 87 | ); 88 | dependencies = ( 89 | ); 90 | name = "max-external"; 91 | productName = iterator; 92 | productReference = 2FBBEAE508F335360078DB84 /* zeroconf.service.mxo */; 93 | productType = "com.apple.product-type.bundle"; 94 | }; 95 | /* End PBXNativeTarget section */ 96 | 97 | /* Begin PBXProject section */ 98 | 089C1669FE841209C02AAC07 /* Project object */ = { 99 | isa = PBXProject; 100 | attributes = { 101 | LastUpgradeCheck = 0610; 102 | }; 103 | buildConfigurationList = 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.service" */; 104 | compatibilityVersion = "Xcode 3.2"; 105 | developmentRegion = English; 106 | hasScannedForEncodings = 1; 107 | knownRegions = ( 108 | en, 109 | ); 110 | mainGroup = 089C166AFE841209C02AAC07 /* iterator */; 111 | projectDirPath = ""; 112 | projectRoot = ""; 113 | targets = ( 114 | 2FBBEAD608F335360078DB84 /* max-external */, 115 | ); 116 | }; 117 | /* End PBXProject section */ 118 | 119 | /* Begin PBXResourcesBuildPhase section */ 120 | 2FBBEAD808F335360078DB84 /* Resources */ = { 121 | isa = PBXResourcesBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | ); 125 | runOnlyForDeploymentPostprocessing = 0; 126 | }; 127 | /* End PBXResourcesBuildPhase section */ 128 | 129 | /* Begin PBXRezBuildPhase section */ 130 | 2FBBEADF08F335360078DB84 /* Rez */ = { 131 | isa = PBXRezBuildPhase; 132 | buildActionMask = 2147483647; 133 | files = ( 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXRezBuildPhase section */ 138 | 139 | /* Begin PBXSourcesBuildPhase section */ 140 | 2FBBEADA08F335360078DB84 /* Sources */ = { 141 | isa = PBXSourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | 01B742391C35ADE80043014A /* NetServiceThread.cpp in Sources */, 145 | 01B742361C35ADE80043014A /* CriticalSection.cpp in Sources */, 146 | 222B12E90F140BDF008B1A46 /* zeroconf.service.cpp in Sources */, 147 | 01B742381C35ADE80043014A /* NetServiceBrowser.cpp in Sources */, 148 | 01B742371C35ADE80043014A /* NetService.cpp in Sources */, 149 | 01B7423A1C35ADE80043014A /* Thread.cpp in Sources */, 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | }; 153 | /* End PBXSourcesBuildPhase section */ 154 | 155 | /* Begin XCBuildConfiguration section */ 156 | 2FBBEAD008F335010078DB84 /* Development */ = { 157 | isa = XCBuildConfiguration; 158 | buildSettings = { 159 | }; 160 | name = Development; 161 | }; 162 | 2FBBEAD108F335010078DB84 /* Deployment */ = { 163 | isa = XCBuildConfiguration; 164 | buildSettings = { 165 | }; 166 | name = Deployment; 167 | }; 168 | 2FBBEAE108F335360078DB84 /* Development */ = { 169 | isa = XCBuildConfiguration; 170 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 171 | buildSettings = { 172 | COPY_PHASE_STRIP = NO; 173 | GCC_OPTIMIZATION_LEVEL = 0; 174 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 175 | }; 176 | name = Development; 177 | }; 178 | 2FBBEAE208F335360078DB84 /* Deployment */ = { 179 | isa = XCBuildConfiguration; 180 | baseConfigurationReference = 22CF10220EE984600054F513 /* maxmspsdk.xcconfig */; 181 | buildSettings = { 182 | COPY_PHASE_STRIP = YES; 183 | OTHER_LDFLAGS = "$(C74_SYM_LINKER_FLAGS)"; 184 | }; 185 | name = Deployment; 186 | }; 187 | /* End XCBuildConfiguration section */ 188 | 189 | /* Begin XCConfigurationList section */ 190 | 2FBBEACF08F335010078DB84 /* Build configuration list for PBXProject "zeroconf.service" */ = { 191 | isa = XCConfigurationList; 192 | buildConfigurations = ( 193 | 2FBBEAD008F335010078DB84 /* Development */, 194 | 2FBBEAD108F335010078DB84 /* Deployment */, 195 | ); 196 | defaultConfigurationIsVisible = 0; 197 | defaultConfigurationName = Development; 198 | }; 199 | 2FBBEAE008F335360078DB84 /* Build configuration list for PBXNativeTarget "max-external" */ = { 200 | isa = XCConfigurationList; 201 | buildConfigurations = ( 202 | 2FBBEAE108F335360078DB84 /* Development */, 203 | 2FBBEAE208F335360078DB84 /* Deployment */, 204 | ); 205 | defaultConfigurationIsVisible = 0; 206 | defaultConfigurationName = Development; 207 | }; 208 | /* End XCConfigurationList section */ 209 | }; 210 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 211 | } 212 | -------------------------------------------------------------------------------- /zipped-externals/osx/zeroconf_20110520_osx_universal.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cassiel/zeroconf/be9cd4ab180528e99df1a5593f8a47b0817a7084/zipped-externals/osx/zeroconf_20110520_osx_universal.zip -------------------------------------------------------------------------------- /zipped-externals/win32/vcredist_x86.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cassiel/zeroconf/be9cd4ab180528e99df1a5593f8a47b0817a7084/zipped-externals/win32/vcredist_x86.exe -------------------------------------------------------------------------------- /zipped-externals/win32/zeroconf_20110226_win32.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cassiel/zeroconf/be9cd4ab180528e99df1a5593f8a47b0817a7084/zipped-externals/win32/zeroconf_20110226_win32.zip --------------------------------------------------------------------------------