PageRenderTime 77ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/azureus-4.7.0.2/com/aelitis/azureus/core/devices/impl/DeviceiTunes.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 656 lines | 438 code | 186 blank | 32 comment | 66 complexity | 8b5c1914ba8380b15fe9168548d0ca9e MD5 | raw file
  1. /*
  2. * Created on Feb 10, 2009
  3. * Created by Paul Gardner
  4. *
  5. * Copyright 2009 Vuze, Inc. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; version 2 of the License only.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. package com.aelitis.azureus.core.devices.impl;
  21. import java.io.File;
  22. import java.io.IOException;
  23. import java.net.InetAddress;
  24. import java.text.SimpleDateFormat;
  25. import java.util.ArrayList;
  26. import java.util.Date;
  27. import java.util.List;
  28. import java.util.Map;
  29. import org.gudy.azureus2.core3.internat.MessageText;
  30. import org.gudy.azureus2.core3.util.AERunnable;
  31. import org.gudy.azureus2.core3.util.AESemaphore;
  32. import org.gudy.azureus2.core3.util.AEThread2;
  33. import org.gudy.azureus2.core3.util.AsyncDispatcher;
  34. import org.gudy.azureus2.core3.util.Debug;
  35. import org.gudy.azureus2.core3.util.IndentWriter;
  36. import org.gudy.azureus2.core3.util.SystemTime;
  37. import org.gudy.azureus2.plugins.PluginInterface;
  38. import org.gudy.azureus2.plugins.ipc.IPCInterface;
  39. import com.aelitis.azureus.core.devices.*;
  40. import com.aelitis.azureus.core.devices.DeviceManager.UnassociatedDevice;
  41. public class
  42. DeviceiTunes
  43. extends DeviceMediaRendererImpl
  44. implements DeviceMediaRenderer
  45. {
  46. private static final String UID = "a5d7869e-1ab9-6098-fef9-88476d988455";
  47. private static final Object ERRROR_KEY_ITUNES = new Object();
  48. private static final int INSTALL_CHECK_PERIOD = 60*1000;
  49. private static final int RUNNING_CHECK_PERIOD = 30*1000;
  50. private static final int DEVICE_CHECK_PERIOD = 10*1000;
  51. private static final int INSTALL_CHECK_TICKS = INSTALL_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
  52. private static final int RUNNING_CHECK_TICKS = RUNNING_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
  53. private static final int DEVICE_CHECK_TICKS = DEVICE_CHECK_PERIOD / DeviceManagerImpl.DEVICE_UPDATE_PERIOD;
  54. private static final Object COPY_ERROR_KEY = new Object();
  55. private PluginInterface itunes;
  56. private volatile boolean is_installed;
  57. private volatile boolean is_running;
  58. private boolean copy_outstanding;
  59. private boolean copy_outstanding_set;
  60. private AEThread2 copy_thread;
  61. private AESemaphore copy_sem = new AESemaphore( "Device:copy" );
  62. private AsyncDispatcher async_dispatcher = new AsyncDispatcher( 5000 );
  63. private long last_update_fail;
  64. private int consec_fails;
  65. protected
  66. DeviceiTunes(
  67. DeviceManagerImpl _manager,
  68. PluginInterface _itunes )
  69. {
  70. super( _manager, UID, "iTunes", true );
  71. itunes = _itunes;
  72. }
  73. protected
  74. DeviceiTunes(
  75. DeviceManagerImpl _manager,
  76. Map _map )
  77. throws IOException
  78. {
  79. super( _manager, _map );
  80. }
  81. protected boolean
  82. updateFrom(
  83. DeviceImpl _other,
  84. boolean _is_alive )
  85. {
  86. if ( !super.updateFrom( _other, _is_alive )){
  87. return( false );
  88. }
  89. if ( !( _other instanceof DeviceiTunes )){
  90. Debug.out( "Inconsistent" );
  91. return( false );
  92. }
  93. DeviceiTunes other = (DeviceiTunes)_other;
  94. itunes = other.itunes;
  95. return( true );
  96. }
  97. protected void
  98. initialise()
  99. {
  100. super.initialise();
  101. if ( getPersistentBooleanProperty( PP_COPY_OUTSTANDING, false )){
  102. setCopyOutstanding();
  103. }
  104. addListener(
  105. new TranscodeTargetListener()
  106. {
  107. public void
  108. fileAdded(
  109. TranscodeFile file )
  110. {
  111. if ( file.isComplete() && !file.isCopiedToDevice()){
  112. setCopyOutstanding();
  113. }
  114. }
  115. public void
  116. fileChanged(
  117. TranscodeFile file,
  118. int type,
  119. Object data )
  120. {
  121. if ( file.isComplete() && !file.isCopiedToDevice()){
  122. setCopyOutstanding();
  123. }
  124. }
  125. public void
  126. fileRemoved(
  127. TranscodeFile file )
  128. {
  129. copy_sem.release();
  130. }
  131. });
  132. }
  133. protected String
  134. getDeviceClassification()
  135. {
  136. return( "apple." );
  137. }
  138. public int
  139. getRendererSpecies()
  140. {
  141. return( RS_ITUNES );
  142. }
  143. public InetAddress
  144. getAddress()
  145. {
  146. return( null );
  147. }
  148. public boolean
  149. canRemove()
  150. {
  151. // no user-initiated removal, they need to uninstall the plugin
  152. return( false );
  153. }
  154. public boolean
  155. isLivenessDetectable()
  156. {
  157. return( true );
  158. }
  159. protected void
  160. destroy()
  161. {
  162. super.destroy();
  163. }
  164. protected void
  165. updateStatus(
  166. int tick_count )
  167. {
  168. super.updateStatus( tick_count );
  169. updateStatusSupport( tick_count );
  170. if ( is_installed && is_running ){
  171. alive();
  172. }else{
  173. dead();
  174. }
  175. }
  176. protected void
  177. updateStatusSupport(
  178. int tick_count )
  179. {
  180. if ( itunes == null ){
  181. return;
  182. }
  183. if ( !is_installed ){
  184. if ( tick_count % INSTALL_CHECK_TICKS == 0 ){
  185. updateiTunesStatus();
  186. return;
  187. }
  188. }
  189. if ( !is_running ){
  190. if ( tick_count % RUNNING_CHECK_TICKS == 0 ){
  191. updateiTunesStatus();
  192. return;
  193. }
  194. }
  195. if ( tick_count % DEVICE_CHECK_TICKS == 0 ){
  196. updateiTunesStatus();
  197. }
  198. }
  199. protected void
  200. updateiTunesStatus()
  201. {
  202. if ( getManager().isClosing()){
  203. return;
  204. }
  205. IPCInterface ipc = itunes.getIPC();
  206. try{
  207. Map<String,Object> properties = (Map<String,Object>)ipc.invoke( "getProperties", new Object[]{} );
  208. is_installed = (Boolean)properties.get( "installed" );
  209. boolean was_running = is_running;
  210. is_running = (Boolean)properties.get( "running" );
  211. if ( is_running && !was_running ){
  212. copy_sem.release();
  213. }
  214. if ( !( is_installed || is_running )){
  215. last_update_fail = 0;
  216. }
  217. String info = null;
  218. if ( getCopyToDevicePending() > 0 ){
  219. if ( !is_installed ){
  220. info = MessageText.getString( "device.itunes.install" );
  221. }else if ( !is_running ){
  222. if ( !getAutoStartDevice()){
  223. info = MessageText.getString( "device.itunes.start" );
  224. }
  225. }
  226. }
  227. setInfo( ERRROR_KEY_ITUNES, info );
  228. Throwable error = (Throwable)properties.get( "error" );
  229. if ( error != null ){
  230. throw( error );
  231. }
  232. /*
  233. List<Map<String,Object>> sources = (List<Map<String,Object>>)properties.get( "sources" );
  234. if ( sources != null ){
  235. for ( Map<String,Object> source: sources ){
  236. System.out.println( source );
  237. }
  238. }
  239. */
  240. last_update_fail = 0;
  241. consec_fails = 0;
  242. setError( ERRROR_KEY_ITUNES, null );
  243. }catch( Throwable e ){
  244. long now = SystemTime.getMonotonousTime();
  245. consec_fails++;
  246. if ( last_update_fail == 0 ){
  247. last_update_fail = now;
  248. }else if ( now - last_update_fail > 60*1000 && consec_fails >= 3 ){
  249. setError( ERRROR_KEY_ITUNES, MessageText.getString( "device.itunes.install_problem" ));
  250. }
  251. log( "iTunes IPC failed", e );
  252. }
  253. }
  254. public boolean
  255. canCopyToDevice()
  256. {
  257. return( true );
  258. }
  259. public int
  260. getCopyToDevicePending()
  261. {
  262. synchronized( this ){
  263. if ( !copy_outstanding ){
  264. return( 0 );
  265. }
  266. }
  267. TranscodeFileImpl[] files = getFiles();
  268. int result = 0;
  269. for ( TranscodeFileImpl file: files ){
  270. if ( file.isComplete() && !file.isCopiedToDevice()){
  271. result++;
  272. }
  273. }
  274. return( result );
  275. }
  276. protected void
  277. setCopyOutstanding()
  278. {
  279. synchronized( this ){
  280. copy_outstanding_set = true;
  281. if ( copy_thread == null ){
  282. copy_thread =
  283. new AEThread2( "Device:copier", true )
  284. {
  285. public void
  286. run()
  287. {
  288. performCopy();
  289. }
  290. };
  291. copy_thread.start();
  292. }
  293. copy_sem.release();
  294. }
  295. }
  296. public boolean
  297. canAutoStartDevice()
  298. {
  299. return( true );
  300. }
  301. public boolean
  302. getAutoStartDevice()
  303. {
  304. return( getPersistentBooleanProperty( PP_AUTO_START, PR_AUTO_START_DEFAULT ));
  305. }
  306. public void
  307. setAutoStartDevice(
  308. boolean auto )
  309. {
  310. setPersistentBooleanProperty( PP_AUTO_START, auto );
  311. if ( auto ){
  312. copy_sem.release();
  313. }
  314. }
  315. public boolean
  316. canAssociate()
  317. {
  318. return( false );
  319. }
  320. public boolean
  321. canRestrictAccess()
  322. {
  323. return( false );
  324. }
  325. public void
  326. associate(
  327. UnassociatedDevice assoc )
  328. {
  329. }
  330. protected void
  331. performCopy()
  332. {
  333. synchronized( this ){
  334. copy_outstanding = true;
  335. async_dispatcher.dispatch(
  336. new AERunnable()
  337. {
  338. public void
  339. runSupport()
  340. {
  341. setPersistentBooleanProperty( PP_COPY_OUTSTANDING, true );
  342. }
  343. });
  344. }
  345. while( true ){
  346. if ( copy_sem.reserve( 60*1000 )){
  347. while( copy_sem.reserveIfAvailable());
  348. }
  349. boolean auto_start = getAutoStartDevice();
  350. synchronized( this ){
  351. if ( itunes == null || ( !is_running && !( auto_start && is_installed ))){
  352. if ( !( copy_outstanding || copy_outstanding_set )){
  353. copy_thread = null;
  354. break;
  355. }
  356. continue;
  357. }
  358. copy_outstanding_set = false;
  359. }
  360. TranscodeFileImpl[] files = getFiles();
  361. List<TranscodeFileImpl> to_copy = new ArrayList<TranscodeFileImpl>();
  362. boolean borked_exist = false;
  363. for ( TranscodeFileImpl file: files ){
  364. if ( file.isComplete() && !file.isCopiedToDevice()){
  365. if ( file.getCopyToDeviceFails() < 3 ){
  366. to_copy.add( file );
  367. }else{
  368. borked_exist = true;
  369. }
  370. }
  371. }
  372. if ( borked_exist ){
  373. setError( COPY_ERROR_KEY, MessageText.getString( "device.error.copyfail2") );
  374. }
  375. synchronized( this ){
  376. if ( to_copy.size() == 0 && !copy_outstanding_set && !borked_exist ){
  377. copy_outstanding = false;
  378. async_dispatcher.dispatch(
  379. new AERunnable()
  380. {
  381. public void
  382. runSupport()
  383. {
  384. setError( COPY_ERROR_KEY, null );
  385. setPersistentBooleanProperty( PP_COPY_OUTSTANDING, false );
  386. }
  387. });
  388. copy_thread = null;
  389. break;
  390. }
  391. }
  392. for ( TranscodeFileImpl transcode_file: to_copy ){
  393. try{
  394. File file = transcode_file.getTargetFile().getFile();
  395. try{
  396. IPCInterface ipc = itunes.getIPC();
  397. if ( !is_running ){
  398. log( "Auto-starting iTunes" );
  399. }
  400. Map<String,Object> result = (Map<String,Object>)ipc.invoke( "addFileToLibrary", new Object[]{ file } );
  401. Throwable error = (Throwable)result.get( "error" );
  402. if ( error != null ){
  403. throw( error );
  404. }
  405. is_running = true;
  406. log( "Added file '" + file + ": " + result );
  407. transcode_file.setCopiedToDevice( true );
  408. }catch( Throwable e ){
  409. transcode_file.setCopyToDeviceFailed();
  410. log( "Failed to copy file " + file, e );
  411. }
  412. }catch( TranscodeException e ){
  413. // file has been deleted
  414. }
  415. }
  416. }
  417. }
  418. public boolean
  419. isBrowsable()
  420. {
  421. return( false );
  422. }
  423. public browseLocation[]
  424. getBrowseLocations()
  425. {
  426. return null;
  427. }
  428. protected void
  429. getDisplayProperties(
  430. List<String[]> dp )
  431. {
  432. super.getDisplayProperties( dp );
  433. if ( itunes == null ){
  434. addDP( dp, "devices.comp.missing", "<null>" );
  435. }else{
  436. updateiTunesStatus();
  437. addDP( dp, "devices.installed", is_installed );
  438. addDP( dp, "MyTrackerView.status.started", is_running );
  439. addDP( dp, "devices.copy.pending", copy_outstanding );
  440. addDP( dp, "devices.auto.start", getAutoStartDevice());
  441. }
  442. }
  443. public String
  444. getStatus()
  445. {
  446. if ( is_running ){
  447. return( MessageText.getString( "device.itunes.status.running" ));
  448. }else if ( is_installed ){
  449. return( MessageText.getString( "device.itunes.status.notrunning" ));
  450. }else{
  451. return( MessageText.getString( "device.itunes.status.notinstalled" ));
  452. }
  453. }
  454. public void
  455. generate(
  456. IndentWriter writer )
  457. {
  458. super.generate( writer );
  459. try{
  460. writer.indent();
  461. writer.println( "itunes=" + itunes + ", installed=" + is_installed + ", running=" + is_running + ", auto_start=" + getAutoStartDevice());
  462. writer.println( "copy_os=" + copy_outstanding + ", last_fail=" + new SimpleDateFormat().format( new Date( last_update_fail )));
  463. }finally{
  464. writer.exdent();
  465. }
  466. }
  467. }